Popup windows will be hidden when minimizing the main frame.
[wine.git] / objects / cursoricon.c
blob6d64d18d82356fd694eac964bf7e3a0339bb8146
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 "color.h"
41 #include "bitmap.h"
42 #include "cursoricon.h"
43 #include "dc.h"
44 #include "gdi.h"
45 #include "global.h"
46 #include "module.h"
47 #include "debugtools.h"
48 #include "task.h"
49 #include "user.h"
50 #include "input.h"
51 #include "display.h"
52 #include "message.h"
53 #include "winerror.h"
55 DECLARE_DEBUG_CHANNEL(cursor)
56 DECLARE_DEBUG_CHANNEL(icon)
58 static HCURSOR hActiveCursor = 0; /* Active cursor */
59 static INT CURSOR_ShowCount = 0; /* Cursor display count */
60 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
63 /**********************************************************************
64 * ICONCACHE for cursors/icons loaded with LR_SHARED.
66 * FIXME: This should not be allocated on the system heap, but on a
67 * subsystem-global heap (i.e. one for all Win16 processes,
68 * and one each for every Win32 process).
70 typedef struct tagICONCACHE
72 struct tagICONCACHE *next;
74 HMODULE hModule;
75 HRSRC hRsrc;
76 HRSRC hGroupRsrc;
77 HANDLE handle;
79 INT count;
81 } ICONCACHE;
83 static ICONCACHE *IconAnchor = NULL;
84 static CRITICAL_SECTION IconCrst;
85 static DWORD ICON_HOTSPOT = 0x42424242;
87 /**********************************************************************
88 * CURSORICON_Init
90 void CURSORICON_Init( void )
92 InitializeCriticalSection( &IconCrst );
93 MakeCriticalSectionGlobal( &IconCrst );
96 /**********************************************************************
97 * CURSORICON_FindSharedIcon
99 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
101 HANDLE handle = 0;
102 ICONCACHE *ptr;
104 EnterCriticalSection( &IconCrst );
106 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
107 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
109 ptr->count++;
110 handle = ptr->handle;
111 break;
114 LeaveCriticalSection( &IconCrst );
116 return handle;
119 /*************************************************************************
120 * CURSORICON_FindCache
122 * Given a handle, find the coresponding cache element
124 * PARAMS
125 * Handle [I] handle to an Image
127 * RETURNS
128 * Success: The cache entry
129 * Failure: NULL
132 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
134 ICONCACHE *ptr;
135 ICONCACHE *pRet=NULL;
136 BOOL IsFound = FALSE;
137 int count;
139 EnterCriticalSection( &IconCrst );
141 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
143 if ( handle == ptr->handle )
145 IsFound = TRUE;
146 pRet = ptr;
150 LeaveCriticalSection( &IconCrst );
152 return pRet;
155 /**********************************************************************
156 * CURSORICON_AddSharedIcon
158 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
160 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
161 if ( !ptr ) return;
163 ptr->hModule = hModule;
164 ptr->hRsrc = hRsrc;
165 ptr->handle = handle;
166 ptr->hGroupRsrc = hGroupRsrc;
167 ptr->count = 1;
169 EnterCriticalSection( &IconCrst );
170 ptr->next = IconAnchor;
171 IconAnchor = ptr;
172 LeaveCriticalSection( &IconCrst );
175 /**********************************************************************
176 * CURSORICON_DelSharedIcon
178 static INT CURSORICON_DelSharedIcon( HANDLE handle )
180 INT count = -1;
181 ICONCACHE *ptr;
183 EnterCriticalSection( &IconCrst );
185 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
186 if ( ptr->handle == handle )
188 if ( ptr->count > 0 ) ptr->count--;
189 count = ptr->count;
190 break;
193 LeaveCriticalSection( &IconCrst );
195 return count;
198 /**********************************************************************
199 * CURSORICON_FreeModuleIcons
201 void CURSORICON_FreeModuleIcons( HMODULE hModule )
203 ICONCACHE **ptr = &IconAnchor;
205 if ( HIWORD( hModule ) )
206 hModule = MapHModuleLS( hModule );
207 else
208 hModule = GetExePtr( hModule );
210 EnterCriticalSection( &IconCrst );
212 while ( *ptr )
214 if ( (*ptr)->hModule == hModule )
216 ICONCACHE *freePtr = *ptr;
217 *ptr = freePtr->next;
219 GlobalFree16( freePtr->handle );
220 HeapFree( SystemHeap, 0, freePtr );
221 continue;
223 ptr = &(*ptr)->next;
226 LeaveCriticalSection( &IconCrst );
229 /**********************************************************************
230 * CURSORICON_FindBestIcon
232 * Find the icon closest to the requested size and number of colors.
234 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
235 int height, int colors )
237 int i;
238 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
239 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
240 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
242 if (dir->idCount < 1)
244 WARN_(icon)("Empty directory!\n" );
245 return NULL;
247 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
249 /* Find Best Fit */
250 iTotalDiff = 0xFFFFFFFF;
251 iColorDiff = 0xFFFFFFFF;
252 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
254 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
255 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
257 if(iTotalDiff > (iTempXDiff + iTempYDiff))
259 iXDiff = iTempXDiff;
260 iYDiff = iTempYDiff;
261 iTotalDiff = iXDiff + iYDiff;
265 /* Find Best Colors for Best Fit */
266 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
268 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
269 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
271 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
272 if(iColorDiff > iTempColorDiff)
274 bestEntry = entry;
275 iColorDiff = iTempColorDiff;
280 return bestEntry;
284 /**********************************************************************
285 * CURSORICON_FindBestCursor
287 * Find the cursor closest to the requested size.
288 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
289 * ignored too
291 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
292 int width, int height, int color)
294 int i, maxwidth, maxheight;
295 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
297 if (dir->idCount < 1)
299 WARN_(cursor)("Empty directory!\n" );
300 return NULL;
302 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
304 /* Double height to account for AND and XOR masks */
306 height *= 2;
308 /* First find the largest one smaller than or equal to the requested size*/
310 maxwidth = maxheight = 0;
311 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
312 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
313 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
314 (entry->wBitCount == 1))
316 bestEntry = entry;
317 maxwidth = entry->ResInfo.cursor.wWidth;
318 maxheight = entry->ResInfo.cursor.wHeight;
320 if (bestEntry) return bestEntry;
322 /* Now find the smallest one larger than the requested size */
324 maxwidth = maxheight = 255;
325 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
326 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
327 (entry->wBitCount == 1))
329 bestEntry = entry;
330 maxwidth = entry->ResInfo.cursor.wWidth;
331 maxheight = entry->ResInfo.cursor.wHeight;
334 return bestEntry;
337 /*********************************************************************
338 * The main purpose of this function is to create fake resource directory
339 * and fake resource entries. There are several reasons for this:
340 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
341 * fields
342 * There are some "bad" cursor files which do not have
343 * bColorCount initialized but instead one must read this info
344 * directly from corresponding DIB sections
345 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
347 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
348 CURSORICONDIR **res, LPBYTE **ptr)
350 LPBYTE _free;
351 CURSORICONFILEDIR *bits;
352 int entries, size, i;
354 *res = NULL;
355 *ptr = NULL;
356 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
358 /* FIXME: test for inimated icons
359 * hack to load the first icon from the *.ani file
361 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
362 { LPBYTE pos = (LPBYTE) bits;
363 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
365 for (;;)
366 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
367 { FIXME_(cursor)("icon entry found! %p\n", bits);
368 pos+=4;
369 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
370 { goto fail;
372 bits=(CURSORICONFILEDIR*)(pos+4);
373 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
374 break;
376 pos+=2;
377 if (pos>=(LPBYTE)bits+766) goto fail;
380 if (!(entries = bits->idCount)) goto fail;
381 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
382 _free = (LPBYTE) size;
384 for (i=0; i < entries; i++)
385 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
387 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
388 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
389 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
391 _free = (LPBYTE)(*res) + (int)_free;
392 memcpy((*res), bits, 6);
393 for (i=0; i<entries; i++)
395 ((LPBYTE*)(*ptr))[i] = _free;
396 if (fCursor) {
397 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
398 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
399 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
400 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
401 _free+=sizeof(POINT16);
402 } else {
403 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
404 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
405 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
407 (*res)->idEntries[i].wPlanes=1;
408 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
409 bits->idEntries[i].dwDIBOffset))->biBitCount;
410 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
411 (*res)->idEntries[i].wResId=i+1;
413 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
414 (*res)->idEntries[i].dwBytesInRes);
415 _free += (*res)->idEntries[i].dwBytesInRes;
417 UnmapViewOfFile( bits );
418 return TRUE;
419 fail:
420 if (*res) HeapFree( GetProcessHeap(), 0, *res );
421 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
422 UnmapViewOfFile( bits );
423 return FALSE;
427 /**********************************************************************
428 * CURSORICON_CreateFromResource
430 * Create a cursor or icon from in-memory resource template.
432 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
433 * with cbSize parameter as well.
435 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
436 UINT cbSize, BOOL bIcon, DWORD dwVersion,
437 INT width, INT height, UINT loadflags )
439 int sizeAnd, sizeXor;
440 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
441 BITMAPOBJ *bmpXor, *bmpAnd;
442 POINT16 hotspot;
443 BITMAPINFO *bmi;
444 HDC hdc;
445 BOOL DoStretch;
446 INT size;
448 hotspot.x = ICON_HOTSPOT;
449 hotspot.y = ICON_HOTSPOT;
451 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
452 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
453 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
454 if (dwVersion == 0x00020000)
456 FIXME_(cursor)("\t2.xx resources are not supported\n");
457 return 0;
460 if (bIcon)
461 bmi = (BITMAPINFO *)bits;
462 else /* get the hotspot */
464 POINT16 *pt = (POINT16 *)bits;
465 hotspot = *pt;
466 bmi = (BITMAPINFO *)(pt + 1);
468 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
470 if (!width) width = bmi->bmiHeader.biWidth;
471 if (!height) height = bmi->bmiHeader.biHeight/2;
472 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
473 (bmi->bmiHeader.biWidth != width);
475 /* Check bitmap header */
477 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
478 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
479 bmi->bmiHeader.biCompression != BI_RGB) )
481 WARN_(cursor)("\tinvalid resource bitmap header.\n");
482 return 0;
485 if( (hdc = GetDC( 0 )) )
487 BITMAPINFO* pInfo;
489 /* Make sure we have room for the monochrome bitmap later on.
490 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
491 * up to and including the biBitCount. In-memory icon resource
492 * format is as follows:
494 * BITMAPINFOHEADER icHeader // DIB header
495 * RGBQUAD icColors[] // Color table
496 * BYTE icXOR[] // DIB bits for XOR mask
497 * BYTE icAND[] // DIB bits for AND mask
500 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
501 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
503 memcpy( pInfo, bmi, size );
504 pInfo->bmiHeader.biHeight /= 2;
506 /* Create the XOR bitmap */
508 if (DoStretch) {
509 if(bIcon)
511 hXorBits = CreateCompatibleBitmap(hdc, width, height);
513 else
515 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
517 if(hXorBits)
519 HBITMAP hOld;
520 HDC hMem = CreateCompatibleDC(hdc);
521 BOOL res;
523 if (hMem) {
524 hOld = SelectObject(hMem, hXorBits);
525 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
526 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
527 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
528 SelectObject(hMem, hOld);
529 DeleteDC(hMem);
530 } else res = FALSE;
531 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
533 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
534 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
535 if( hXorBits )
537 char* bits = (char *)bmi + size +
538 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
539 bmi->bmiHeader.biHeight,
540 bmi->bmiHeader.biBitCount) / 2;
542 pInfo->bmiHeader.biBitCount = 1;
543 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
545 RGBQUAD *rgb = pInfo->bmiColors;
547 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
548 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
549 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
550 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
552 else
554 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
556 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
557 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
560 /* Create the AND bitmap */
562 if (DoStretch) {
563 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
564 HBITMAP hOld;
565 HDC hMem = CreateCompatibleDC(hdc);
566 BOOL res;
568 if (hMem) {
569 hOld = SelectObject(hMem, hAndBits);
570 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
571 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
572 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
573 SelectObject(hMem, hOld);
574 DeleteDC(hMem);
575 } else res = FALSE;
576 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
578 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
579 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
581 if( !hAndBits ) DeleteObject( hXorBits );
583 HeapFree( GetProcessHeap(), 0, pInfo );
585 ReleaseDC( 0, hdc );
588 if( !hXorBits || !hAndBits )
590 WARN_(cursor)("\tunable to create an icon bitmap.\n");
591 return 0;
594 /* Now create the CURSORICONINFO structure */
595 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
596 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
597 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
598 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
600 if (hObj) hObj = GlobalReAlloc16( hObj,
601 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
602 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
603 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
604 if (hObj)
606 CURSORICONINFO *info;
608 /* Make it owned by the module */
609 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
611 info = (CURSORICONINFO *)GlobalLock16( hObj );
612 info->ptHotSpot.x = hotspot.x;
613 info->ptHotSpot.y = hotspot.y;
614 info->nWidth = bmpXor->bitmap.bmWidth;
615 info->nHeight = bmpXor->bitmap.bmHeight;
616 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
617 info->bPlanes = bmpXor->bitmap.bmPlanes;
618 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
620 /* Transfer the bitmap bits to the CURSORICONINFO structure */
622 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
623 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
624 GlobalUnlock16( hObj );
627 DeleteObject( hXorBits );
628 DeleteObject( hAndBits );
629 return hObj;
633 /**********************************************************************
634 * CreateIconFromResourceEx16 (USER.450)
636 * FIXME: not sure about exact parameter types
638 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
639 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
641 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
642 width, height, cFlag);
646 /**********************************************************************
647 * CreateIconFromResource (USER32.76)
649 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
650 BOOL bIcon, DWORD dwVersion)
652 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
656 /**********************************************************************
657 * CreateIconFromResourceEx32 (USER32.77)
659 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
660 BOOL bIcon, DWORD dwVersion,
661 INT width, INT height,
662 UINT cFlag )
664 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
665 if( pTask )
666 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
667 width, height, cFlag );
668 return 0;
671 /**********************************************************************
672 * CURSORICON_Load
674 * Load a cursor or icon from resource or file.
676 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
677 INT width, INT height, INT colors,
678 BOOL fCursor, UINT loadflags )
680 HANDLE handle = 0, h = 0;
681 HANDLE hRsrc;
682 CURSORICONDIR *dir;
683 CURSORICONDIRENTRY *dirEntry;
684 LPBYTE bits;
686 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
688 LPBYTE *ptr;
689 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
690 return 0;
691 if (fCursor)
692 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
693 else
694 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
695 bits = ptr[dirEntry->wResId-1];
696 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
697 !fCursor, 0x00030000, width, height, loadflags);
698 HeapFree( GetProcessHeap(), 0, dir );
699 HeapFree( GetProcessHeap(), 0, ptr );
702 else if ( !hInstance ) /* Load OEM cursor/icon */
704 WORD resid;
705 HDC hdc;
707 if ( HIWORD(name) )
709 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
710 if( ansi[0]=='#') /*Check for '#xxx' name */
712 resid = atoi(ansi+1);
713 HeapFree( GetProcessHeap(), 0, ansi );
715 else
717 HeapFree( GetProcessHeap(), 0, ansi );
718 return 0;
721 else resid = LOWORD(name);
722 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
723 if (hdc) {
724 DC *dc = DC_GetDCPtr( hdc );
725 if (dc->funcs->pLoadOEMResource)
726 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
727 GDI_HEAP_UNLOCK( hdc );
728 DeleteDC( hdc );
732 else /* Load from resource */
734 HANDLE hGroupRsrc;
735 WORD wResId;
736 DWORD dwBytesInRes;
738 /* Normalize hInstance (must be uniquely represented for icon cache) */
740 if ( HIWORD( hInstance ) )
741 hInstance = MapHModuleLS( hInstance );
742 else
743 hInstance = GetExePtr( hInstance );
745 /* Get directory resource ID */
747 if (!(hRsrc = FindResourceW( hInstance, name,
748 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
749 return 0;
750 hGroupRsrc = hRsrc;
751 /* If shared icon, check whether it was already loaded */
753 if ( (loadflags & LR_SHARED)
754 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
755 return h;
757 /* Find the best entry in the directory */
759 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
760 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
761 if (fCursor)
762 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
763 width, height, 1);
764 else
765 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
766 width, height, colors );
767 if (!dirEntry) return 0;
768 wResId = dirEntry->wResId;
769 dwBytesInRes = dirEntry->dwBytesInRes;
770 FreeResource( handle );
772 /* Load the resource */
774 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
775 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
776 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
777 bits = (LPBYTE)LockResource( handle );
778 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
779 !fCursor, 0x00030000, width, height, loadflags);
780 FreeResource( handle );
782 /* If shared icon, add to icon cache */
784 if ( h && (loadflags & LR_SHARED) )
785 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
788 return h;
791 /***********************************************************************
792 * CURSORICON_Copy
794 * Make a copy of a cursor or icon.
796 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
798 char *ptrOld, *ptrNew;
799 int size;
800 HGLOBAL16 hNew;
802 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
803 if (!(hInstance = GetExePtr( hInstance ))) return 0;
804 size = GlobalSize16( handle );
805 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
806 FarSetOwner16( hNew, hInstance );
807 ptrNew = (char *)GlobalLock16( hNew );
808 memcpy( ptrNew, ptrOld, size );
809 GlobalUnlock16( handle );
810 GlobalUnlock16( hNew );
811 return hNew;
814 /*************************************************************************
815 * CURSORICON_ExtCopy
817 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
819 * PARAMS
820 * Handle [I] handle to an Image
821 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
822 * iDesiredCX [I] The Desired width of the Image
823 * iDesiredCY [I] The desired height of the Image
824 * nFlags [I] The flags from CopyImage
826 * RETURNS
827 * Success: The new handle of the Image
829 * NOTES
830 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
831 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
832 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
837 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
838 INT iDesiredCX, INT iDesiredCY,
839 UINT nFlags)
841 HGLOBAL16 hNew=0;
843 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
844 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
846 if(Handle == 0)
848 return 0;
851 /* Best Fit or Monochrome */
852 if( (nFlags & LR_COPYFROMRESOURCE
853 && (iDesiredCX > 0 || iDesiredCY > 0))
854 || nFlags & LR_MONOCHROME)
856 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
858 /* Not Found in Cache, then do a strait copy
860 if(pIconCache == NULL)
862 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
863 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
864 if(nFlags & LR_COPYFROMRESOURCE)
866 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
869 else
871 int iTargetCX, iTargetCY;
872 LPBYTE pBits;
873 HANDLE hMem;
874 HRSRC hRsrc;
875 DWORD dwBytesInRes;
876 WORD wResId;
877 CURSORICONDIR *pDir;
878 CURSORICONDIRENTRY *pDirEntry;
879 BOOL bIsIcon = (nType == IMAGE_ICON);
881 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
883 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
884 || (iDesiredCX == 0 && iDesiredCY == 0))
886 iDesiredCY = GetSystemMetrics(bIsIcon ?
887 SM_CYICON : SM_CYCURSOR);
888 iDesiredCX = GetSystemMetrics(bIsIcon ?
889 SM_CXICON : SM_CXCURSOR);
892 /* Retreive the CURSORICONDIRENTRY
894 if (!(hMem = LoadResource( pIconCache->hModule ,
895 pIconCache->hGroupRsrc)))
897 return 0;
899 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
901 return 0;
904 /* Find Best Fit
906 if(bIsIcon)
908 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
909 pDir, iDesiredCX, iDesiredCY, 256);
911 else
913 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
914 pDir, iDesiredCX, iDesiredCY, 1);
917 wResId = pDirEntry->wResId;
918 dwBytesInRes = pDirEntry->dwBytesInRes;
919 FreeResource(hMem);
921 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
922 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
923 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
925 /* Get the Best Fit
927 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
928 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
930 return 0;
932 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
934 return 0;
937 pBits = (LPBYTE)LockResource( hMem );
939 iTargetCY = GetSystemMetrics(SM_CYICON);
940 iTargetCX = GetSystemMetrics(SM_CXICON);
942 /* Create a New Icon with the proper dimension
944 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
945 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
946 FreeResource(hMem);
949 else
951 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
952 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
954 return hNew;
957 /***********************************************************************
958 * CURSORICON_IconToCursor
960 * Converts bitmap to mono and truncates if icon is too large (should
961 * probably do StretchBlt() instead).
963 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
965 HCURSOR16 hRet = 0;
966 CURSORICONINFO *pIcon = NULL;
967 HTASK16 hTask = GetCurrentTask();
968 TDB* pTask = (TDB *)GlobalLock16(hTask);
970 if(hIcon && pTask)
971 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
972 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
974 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
977 pIcon = GlobalLock16(hRet);
979 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
981 GlobalUnlock(hRet);
983 else
985 BYTE pAndBits[128];
986 BYTE pXorBits[128];
987 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
988 BYTE* psPtr, *pxbPtr = pXorBits;
989 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
990 BYTE* pbc = NULL;
992 CURSORICONINFO cI;
994 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
995 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
997 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
998 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
999 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1001 memset(pXorBits, 0, 128);
1002 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1003 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1004 cI.nWidth = 32; cI.nHeight = 32;
1005 cI.nWidthBytes = 4; /* 32x1bpp */
1007 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1008 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1010 for( iy = 0; iy < maxy; iy++ )
1012 unsigned shift = iy % 2;
1014 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1015 (and_width > 4) ? 4 : and_width );
1016 for( ix = 0; ix < maxx; ix++ )
1018 if( bSemiTransparent && ((ix+shift)%2) )
1020 /* set AND bit, XOR bit stays 0 */
1022 pbc = pAndBits + iy * 4 + ix/8;
1023 *pbc |= 0x80 >> (ix%8);
1025 else
1027 /* keep AND bit, set XOR bit */
1029 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1030 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1031 if(!PALETTE_Driver->pIsDark(val))
1033 pbc = pxbPtr + ix/8;
1034 *pbc |= 0x80 >> (ix%8);
1038 psPtr += xor_width;
1039 pxbPtr += 4;
1042 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1044 if( !hRet ) /* fall back on default drag cursor */
1045 hRet = CURSORICON_Copy( pTask->hInstance ,
1046 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1047 GetSystemMetrics(SM_CXCURSOR),
1048 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1051 return hRet;
1055 /***********************************************************************
1056 * LoadCursor16 (USER.173)
1058 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1060 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1061 return LoadCursorA( hInstance, nameStr );
1065 /***********************************************************************
1066 * LoadIcon16 (USER.174)
1068 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1070 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1071 return LoadIconA( hInstance, nameStr );
1075 /***********************************************************************
1076 * CreateCursor16 (USER.406)
1078 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1079 INT16 xHotSpot, INT16 yHotSpot,
1080 INT16 nWidth, INT16 nHeight,
1081 LPCVOID lpANDbits, LPCVOID lpXORbits )
1083 CURSORICONINFO info;
1085 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1086 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1088 info.ptHotSpot.x = xHotSpot;
1089 info.ptHotSpot.y = yHotSpot;
1090 info.nWidth = nWidth;
1091 info.nHeight = nHeight;
1092 info.nWidthBytes = 0;
1093 info.bPlanes = 1;
1094 info.bBitsPerPixel = 1;
1096 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1100 /***********************************************************************
1101 * CreateCursor32 (USER32.67)
1103 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1104 INT xHotSpot, INT yHotSpot,
1105 INT nWidth, INT nHeight,
1106 LPCVOID lpANDbits, LPCVOID lpXORbits )
1108 CURSORICONINFO info;
1110 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1111 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1113 info.ptHotSpot.x = xHotSpot;
1114 info.ptHotSpot.y = yHotSpot;
1115 info.nWidth = nWidth;
1116 info.nHeight = nHeight;
1117 info.nWidthBytes = 0;
1118 info.bPlanes = 1;
1119 info.bBitsPerPixel = 1;
1121 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1125 /***********************************************************************
1126 * CreateIcon16 (USER.407)
1128 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1129 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1130 LPCVOID lpANDbits, LPCVOID lpXORbits )
1132 CURSORICONINFO info;
1134 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1135 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1137 info.ptHotSpot.x = ICON_HOTSPOT;
1138 info.ptHotSpot.y = ICON_HOTSPOT;
1139 info.nWidth = nWidth;
1140 info.nHeight = nHeight;
1141 info.nWidthBytes = 0;
1142 info.bPlanes = bPlanes;
1143 info.bBitsPerPixel = bBitsPixel;
1145 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1149 /***********************************************************************
1150 * CreateIcon32 (USER32.75)
1152 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1153 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1154 LPCVOID lpANDbits, LPCVOID lpXORbits )
1156 CURSORICONINFO info;
1158 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1159 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1161 info.ptHotSpot.x = ICON_HOTSPOT;
1162 info.ptHotSpot.y = ICON_HOTSPOT;
1163 info.nWidth = nWidth;
1164 info.nHeight = nHeight;
1165 info.nWidthBytes = 0;
1166 info.bPlanes = bPlanes;
1167 info.bBitsPerPixel = bBitsPixel;
1169 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1173 /***********************************************************************
1174 * CreateCursorIconIndirect (USER.408)
1176 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1177 CURSORICONINFO *info,
1178 LPCVOID lpANDbits,
1179 LPCVOID lpXORbits )
1181 HGLOBAL16 handle;
1182 char *ptr;
1183 int sizeAnd, sizeXor;
1185 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1186 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1187 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1188 sizeXor = info->nHeight * info->nWidthBytes;
1189 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1190 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1191 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1192 return 0;
1193 if (hInstance) FarSetOwner16( handle, hInstance );
1194 ptr = (char *)GlobalLock16( handle );
1195 memcpy( ptr, info, sizeof(*info) );
1196 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1197 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1198 GlobalUnlock16( handle );
1199 return handle;
1203 /***********************************************************************
1204 * CopyIcon16 (USER.368)
1206 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1208 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1209 return CURSORICON_Copy( hInstance, hIcon );
1213 /***********************************************************************
1214 * CopyIcon32 (USER32.60)
1216 HICON WINAPI CopyIcon( HICON hIcon )
1218 HTASK16 hTask = GetCurrentTask ();
1219 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1220 TRACE_(icon)("%04x\n", hIcon );
1221 return CURSORICON_Copy( pTask->hInstance, hIcon );
1225 /***********************************************************************
1226 * CopyCursor16 (USER.369)
1228 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1230 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1231 return CURSORICON_Copy( hInstance, hCursor );
1234 /**********************************************************************
1235 * CURSORICON_Destroy (USER.610)
1237 * This routine is actually exported from Win95 USER under the name
1238 * DestroyIcon32 ... The behaviour implemented here should mimic
1239 * the Win95 one exactly, especially the return values, which
1240 * depend on the setting of various flags.
1242 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1244 WORD retv;
1246 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1248 /* Check whether destroying active cursor */
1250 if ( hActiveCursor == handle )
1252 ERR_(cursor)("Destroying active cursor!\n" );
1253 SetCursor( 0 );
1256 /* Try shared cursor/icon first */
1258 if ( !(flags & CID_NONSHARED) )
1260 INT count = CURSORICON_DelSharedIcon( handle );
1262 if ( count != -1 )
1263 return (flags & CID_WIN32)? TRUE : (count == 0);
1265 /* FIXME: OEM cursors/icons should be recognized */
1268 /* Now assume non-shared cursor/icon */
1270 retv = GlobalFree16( handle );
1271 return (flags & CID_RESOURCE)? retv : TRUE;
1274 /***********************************************************************
1275 * DestroyIcon16 (USER.457)
1277 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1279 return CURSORICON_Destroy( hIcon, 0 );
1282 /***********************************************************************
1283 * DestroyIcon (USER32.133)
1285 BOOL WINAPI DestroyIcon( HICON hIcon )
1287 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1290 /***********************************************************************
1291 * DestroyCursor16 (USER.458)
1293 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1295 return CURSORICON_Destroy( hCursor, 0 );
1298 /***********************************************************************
1299 * DestroyCursor (USER32.132)
1301 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1303 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1307 /***********************************************************************
1308 * DrawIcon16 (USER.84)
1310 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1312 return DrawIcon( hdc, x, y, hIcon );
1316 /***********************************************************************
1317 * DrawIcon32 (USER32.159)
1319 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1321 CURSORICONINFO *ptr;
1322 HDC hMemDC;
1323 HBITMAP hXorBits, hAndBits;
1324 COLORREF oldFg, oldBg;
1326 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1327 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1328 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1329 (char *)(ptr+1) );
1330 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1331 ptr->bBitsPerPixel, (char *)(ptr + 1)
1332 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1333 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1334 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1336 if (hXorBits && hAndBits)
1338 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1339 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1340 SelectObject( hMemDC, hXorBits );
1341 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1342 SelectObject( hMemDC, hBitTemp );
1344 DeleteDC( hMemDC );
1345 if (hXorBits) DeleteObject( hXorBits );
1346 if (hAndBits) DeleteObject( hAndBits );
1347 GlobalUnlock16( hIcon );
1348 SetTextColor( hdc, oldFg );
1349 SetBkColor( hdc, oldBg );
1350 return TRUE;
1354 /***********************************************************************
1355 * DumpIcon (USER.459)
1357 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1358 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1360 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1361 int sizeAnd, sizeXor;
1363 if (!info) return 0;
1364 sizeXor = info->nHeight * info->nWidthBytes;
1365 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1366 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1367 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1368 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1369 return MAKELONG( sizeXor, sizeXor );
1373 /***********************************************************************
1374 * SetCursor16 (USER.69)
1376 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1378 return (HCURSOR16)SetCursor( hCursor );
1382 /***********************************************************************
1383 * SetCursor32 (USER32.472)
1384 * RETURNS:
1385 * A handle to the previous cursor shape.
1387 HCURSOR WINAPI SetCursor(
1388 HCURSOR hCursor /* Handle of cursor to show */
1390 HCURSOR hOldCursor;
1392 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1393 TRACE_(cursor)("%04x\n", hCursor );
1394 hOldCursor = hActiveCursor;
1395 hActiveCursor = hCursor;
1396 /* Change the cursor shape only if it is visible */
1397 if (CURSOR_ShowCount >= 0)
1399 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1400 GlobalUnlock16( hActiveCursor );
1402 return hOldCursor;
1406 /***********************************************************************
1407 * SetCursorPos16 (USER.70)
1409 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1411 SetCursorPos( x, y );
1415 /***********************************************************************
1416 * SetCursorPos32 (USER32.474)
1418 BOOL WINAPI SetCursorPos( INT x, INT y )
1420 DISPLAY_MoveCursor( x, y );
1421 return TRUE;
1425 /***********************************************************************
1426 * ShowCursor16 (USER.71)
1428 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1430 return ShowCursor( bShow );
1434 /***********************************************************************
1435 * ShowCursor32 (USER32.530)
1437 INT WINAPI ShowCursor( BOOL bShow )
1439 TRACE_(cursor)("%d, count=%d\n",
1440 bShow, CURSOR_ShowCount );
1442 if (bShow)
1444 if (++CURSOR_ShowCount == 0) /* Show it */
1446 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1447 GlobalUnlock16( hActiveCursor );
1450 else
1452 if (--CURSOR_ShowCount == -1) /* Hide it */
1453 DISPLAY_SetCursor( NULL );
1455 return CURSOR_ShowCount;
1459 /***********************************************************************
1460 * GetCursor16 (USER.247)
1462 HCURSOR16 WINAPI GetCursor16(void)
1464 return hActiveCursor;
1468 /***********************************************************************
1469 * GetCursor32 (USER32.227)
1471 HCURSOR WINAPI GetCursor(void)
1473 return hActiveCursor;
1477 /***********************************************************************
1478 * ClipCursor16 (USER.16)
1480 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1482 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1483 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1484 return TRUE;
1488 /***********************************************************************
1489 * ClipCursor32 (USER32.53)
1491 BOOL WINAPI ClipCursor( const RECT *rect )
1493 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1494 else CopyRect( &CURSOR_ClipRect, rect );
1495 return TRUE;
1499 /***********************************************************************
1500 * GetCursorPos16 (USER.17)
1502 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1504 if (!pt) return 0;
1506 pt->x = PosX;
1507 pt->y = PosY;
1509 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1510 return 1;
1514 /***********************************************************************
1515 * GetCursorPos32 (USER32.229)
1517 BOOL WINAPI GetCursorPos( POINT *pt )
1519 BOOL ret;
1521 POINT16 pt16;
1522 ret = GetCursorPos16( &pt16 );
1523 if (pt) CONV_POINT16TO32( &pt16, pt );
1524 return ((pt) ? ret : 0);
1528 /***********************************************************************
1529 * GetClipCursor16 (USER.309)
1531 void WINAPI GetClipCursor16( RECT16 *rect )
1533 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1537 /***********************************************************************
1538 * GetClipCursor32 (USER32.221)
1540 BOOL WINAPI GetClipCursor( RECT *rect )
1542 if (rect)
1544 CopyRect( rect, &CURSOR_ClipRect );
1545 return TRUE;
1547 return FALSE;
1550 /**********************************************************************
1551 * LookupIconIdFromDirectoryEx16 (USER.364)
1553 * FIXME: exact parameter sizes
1555 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1556 INT16 width, INT16 height, UINT16 cFlag )
1558 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1559 UINT16 retVal = 0;
1560 if( dir && !dir->idReserved && (dir->idType & 3) )
1562 CURSORICONDIRENTRY* entry;
1563 HDC hdc;
1564 UINT palEnts;
1565 int colors;
1566 hdc = GetDC(0);
1567 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1568 if (palEnts == 0)
1569 palEnts = 256;
1570 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1572 ReleaseDC(0, hdc);
1574 if( bIcon )
1575 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1576 else
1577 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1579 if( entry ) retVal = entry->wResId;
1581 else WARN_(cursor)("invalid resource directory\n");
1582 return retVal;
1585 /**********************************************************************
1586 * LookupIconIdFromDirectoryEx32 (USER32.380)
1588 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1589 INT width, INT height, UINT cFlag )
1591 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1594 /**********************************************************************
1595 * LookupIconIdFromDirectory (USER.???)
1597 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1599 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1600 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1601 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1604 /**********************************************************************
1605 * LookupIconIdFromDirectory (USER32.379)
1607 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1609 return LookupIconIdFromDirectoryEx( dir, bIcon,
1610 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1611 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1614 /**********************************************************************
1615 * GetIconID (USER.455)
1617 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1619 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1621 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1622 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1624 switch(resType)
1626 case RT_CURSOR16:
1627 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1628 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1629 case RT_ICON16:
1630 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1631 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1632 default:
1633 WARN_(cursor)("invalid res type %ld\n", resType );
1635 return 0;
1638 /**********************************************************************
1639 * LoadCursorIconHandler (USER.336)
1641 * Supposed to load resources of Windows 2.x applications.
1643 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1645 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1646 hResource, hModule, hRsrc);
1647 return (HGLOBAL16)0;
1650 /**********************************************************************
1651 * LoadDIBIconHandler (USER.357)
1653 * RT_ICON resource loader, installed by USER_SignalProc when module
1654 * is initialized.
1656 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1658 /* If hResource is zero we must allocate a new memory block, if it's
1659 * non-zero but GlobalLock() returns NULL then it was discarded and
1660 * we have to recommit some memory, otherwise we just need to check
1661 * the block size. See LoadProc() in 16-bit SDK for more.
1664 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1665 if( hMemObj )
1667 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1668 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1669 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1670 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1672 return hMemObj;
1675 /**********************************************************************
1676 * LoadDIBCursorHandler (USER.356)
1678 * RT_CURSOR resource loader. Same as above.
1680 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1682 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1683 if( hMemObj )
1685 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1686 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1687 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1688 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1690 return hMemObj;
1693 /**********************************************************************
1694 * LoadIconHandler (USER.456)
1696 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1698 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1700 TRACE_(cursor)("hRes=%04x\n",hResource);
1702 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1703 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1706 /***********************************************************************
1707 * LoadCursorW (USER32.362)
1709 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1711 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1712 LR_SHARED | LR_DEFAULTSIZE );
1715 /***********************************************************************
1716 * LoadCursorA (USER32.359)
1718 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1720 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1721 LR_SHARED | LR_DEFAULTSIZE );
1724 /***********************************************************************
1725 * LoadCursorFromFileW (USER32.361)
1727 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1729 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1730 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1733 /***********************************************************************
1734 * LoadCursorFromFileA (USER32.360)
1736 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1738 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1739 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1742 /***********************************************************************
1743 * LoadIconW (USER32.364)
1745 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1747 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1748 LR_SHARED | LR_DEFAULTSIZE );
1751 /***********************************************************************
1752 * LoadIconA (USER32.363)
1754 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1756 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1757 LR_SHARED | LR_DEFAULTSIZE );
1760 /**********************************************************************
1761 * GetIconInfo16 (USER.395)
1763 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1765 ICONINFO ii32;
1766 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1768 iconinfo->fIcon = ii32.fIcon;
1769 iconinfo->xHotspot = ii32.xHotspot;
1770 iconinfo->yHotspot = ii32.yHotspot;
1771 iconinfo->hbmMask = ii32.hbmMask;
1772 iconinfo->hbmColor = ii32.hbmColor;
1773 return ret;
1776 /**********************************************************************
1777 * GetIconInfo32 (USER32.242)
1779 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1780 CURSORICONINFO *ciconinfo;
1782 ciconinfo = GlobalLock16(hIcon);
1783 if (!ciconinfo)
1784 return FALSE;
1786 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1787 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1789 iconinfo->fIcon = TRUE;
1790 iconinfo->xHotspot = 0;
1791 iconinfo->yHotspot = 0;
1793 else
1795 iconinfo->fIcon = FALSE;
1796 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1797 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1800 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1801 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1802 (char *)(ciconinfo + 1)
1803 + ciconinfo->nHeight *
1804 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1805 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1806 1, 1, (char *)(ciconinfo + 1));
1808 GlobalUnlock16(hIcon);
1810 return TRUE;
1813 /**********************************************************************
1814 * CreateIconIndirect (USER32.78)
1816 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1817 BITMAPOBJ *bmpXor,*bmpAnd;
1818 HICON hObj;
1819 int sizeXor,sizeAnd;
1821 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1822 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1824 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1825 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1827 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1828 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1829 if (hObj)
1831 CURSORICONINFO *info;
1833 info = (CURSORICONINFO *)GlobalLock16( hObj );
1835 /* If we are creating an icon, the hotspot is unused */
1836 if (iconinfo->fIcon)
1838 info->ptHotSpot.x = ICON_HOTSPOT;
1839 info->ptHotSpot.y = ICON_HOTSPOT;
1841 else
1843 info->ptHotSpot.x = iconinfo->xHotspot;
1844 info->ptHotSpot.y = iconinfo->yHotspot;
1847 info->nWidth = bmpXor->bitmap.bmWidth;
1848 info->nHeight = bmpXor->bitmap.bmHeight;
1849 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1850 info->bPlanes = bmpXor->bitmap.bmPlanes;
1851 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1853 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1855 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1856 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1857 GlobalUnlock16( hObj );
1859 return hObj;
1863 /**********************************************************************
1865 DrawIconEx16 (USER.394)
1867 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1868 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1869 HBRUSH16 hbr, UINT16 flags)
1871 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1872 istep, hbr, flags);
1876 /******************************************************************************
1877 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1879 * NOTES
1880 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1882 * PARAMS
1883 * hdc [I] Handle to device context
1884 * x0 [I] X coordinate of upper left corner
1885 * y0 [I] Y coordinate of upper left corner
1886 * hIcon [I] Handle to icon to draw
1887 * cxWidth [I] Width of icon
1888 * cyWidth [I] Height of icon
1889 * istep [I] Index of frame in animated cursor
1890 * hbr [I] Handle to background brush
1891 * flags [I] Icon-drawing flags
1893 * RETURNS
1894 * Success: TRUE
1895 * Failure: FALSE
1897 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1898 INT cxWidth, INT cyWidth, UINT istep,
1899 HBRUSH hbr, UINT flags )
1901 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1902 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1903 BOOL result = FALSE, DoOffscreen = FALSE;
1904 HBITMAP hB_off = 0, hOld = 0;
1906 if (!ptr) return FALSE;
1908 if (istep)
1909 FIXME_(icon)("Ignoring istep=%d\n", istep);
1910 if (flags & DI_COMPAT)
1911 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1913 /* Calculate the size of the destination image. */
1914 if (cxWidth == 0)
1916 if (flags & DI_DEFAULTSIZE)
1917 cxWidth = GetSystemMetrics (SM_CXICON);
1918 else
1919 cxWidth = ptr->nWidth;
1921 if (cyWidth == 0)
1923 if (flags & DI_DEFAULTSIZE)
1924 cyWidth = GetSystemMetrics (SM_CYICON);
1925 else
1926 cyWidth = ptr->nHeight;
1929 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1930 STOCK_HOLLOW_BRUSH)))
1932 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1933 if (object)
1935 UINT16 magic = object->wMagic;
1936 GDI_HEAP_UNLOCK(hbr);
1937 DoOffscreen = magic == BRUSH_MAGIC;
1940 if (DoOffscreen) {
1941 RECT r;
1943 r.left = 0;
1944 r.top = 0;
1945 r.right = cxWidth;
1946 r.bottom = cxWidth;
1948 hDC_off = CreateCompatibleDC(hdc);
1949 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1950 if (hDC_off && hB_off) {
1951 hOld = SelectObject(hDC_off, hB_off);
1952 FillRect(hDC_off, &r, hbr);
1956 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1958 HBITMAP hXorBits, hAndBits;
1959 COLORREF oldFg, oldBg;
1960 INT nStretchMode;
1962 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1964 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1965 ptr->bPlanes, ptr->bBitsPerPixel,
1966 (char *)(ptr + 1)
1967 + ptr->nHeight *
1968 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1969 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1970 1, 1, (char *)(ptr+1) );
1971 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1972 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1974 if (hXorBits && hAndBits)
1976 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1977 if (flags & DI_MASK)
1979 if (DoOffscreen)
1980 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1981 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1982 else
1983 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1984 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1986 SelectObject( hMemDC, hXorBits );
1987 if (flags & DI_IMAGE)
1989 if (DoOffscreen)
1990 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1991 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1992 else
1993 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1994 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1996 SelectObject( hMemDC, hBitTemp );
1997 result = TRUE;
2000 SetTextColor( hdc, oldFg );
2001 SetBkColor( hdc, oldBg );
2002 if (hXorBits) DeleteObject( hXorBits );
2003 if (hAndBits) DeleteObject( hAndBits );
2004 SetStretchBltMode (hdc, nStretchMode);
2005 if (DoOffscreen) {
2006 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2007 SelectObject(hDC_off, hOld);
2010 if (hMemDC) DeleteDC( hMemDC );
2011 if (hDC_off) DeleteDC(hDC_off);
2012 if (hB_off) DeleteObject(hB_off);
2013 GlobalUnlock16( hIcon );
2014 return result;