Serge Ivanov
[wine.git] / windows / cursoricon.c
blobe0917810be7c4ebbd55cafe238f3915b09ff3fcc
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);
57 DECLARE_DEBUG_CHANNEL(resource);
59 static HCURSOR hActiveCursor = 0; /* Active cursor */
60 static INT CURSOR_ShowCount = 0; /* Cursor display count */
61 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
64 /**********************************************************************
65 * ICONCACHE for cursors/icons loaded with LR_SHARED.
67 * FIXME: This should not be allocated on the system heap, but on a
68 * subsystem-global heap (i.e. one for all Win16 processes,
69 * and one each for every Win32 process).
71 typedef struct tagICONCACHE
73 struct tagICONCACHE *next;
75 HMODULE hModule;
76 HRSRC hRsrc;
77 HRSRC hGroupRsrc;
78 HANDLE handle;
80 INT count;
82 } ICONCACHE;
84 static ICONCACHE *IconAnchor = NULL;
85 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
86 static DWORD ICON_HOTSPOT = 0x42424242;
88 /**********************************************************************
89 * CURSORICON_FindSharedIcon
91 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
93 HANDLE handle = 0;
94 ICONCACHE *ptr;
96 EnterCriticalSection( &IconCrst );
98 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
99 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
101 ptr->count++;
102 handle = ptr->handle;
103 break;
106 LeaveCriticalSection( &IconCrst );
108 return handle;
111 /*************************************************************************
112 * CURSORICON_FindCache
114 * Given a handle, find the coresponding cache element
116 * PARAMS
117 * Handle [I] handle to an Image
119 * RETURNS
120 * Success: The cache entry
121 * Failure: NULL
124 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
126 ICONCACHE *ptr;
127 ICONCACHE *pRet=NULL;
128 BOOL IsFound = FALSE;
129 int count;
131 EnterCriticalSection( &IconCrst );
133 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
135 if ( handle == ptr->handle )
137 IsFound = TRUE;
138 pRet = ptr;
142 LeaveCriticalSection( &IconCrst );
144 return pRet;
147 /**********************************************************************
148 * CURSORICON_AddSharedIcon
150 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
152 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
153 if ( !ptr ) return;
155 ptr->hModule = hModule;
156 ptr->hRsrc = hRsrc;
157 ptr->handle = handle;
158 ptr->hGroupRsrc = hGroupRsrc;
159 ptr->count = 1;
161 EnterCriticalSection( &IconCrst );
162 ptr->next = IconAnchor;
163 IconAnchor = ptr;
164 LeaveCriticalSection( &IconCrst );
167 /**********************************************************************
168 * CURSORICON_DelSharedIcon
170 static INT CURSORICON_DelSharedIcon( HANDLE handle )
172 INT count = -1;
173 ICONCACHE *ptr;
175 EnterCriticalSection( &IconCrst );
177 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
178 if ( ptr->handle == handle )
180 if ( ptr->count > 0 ) ptr->count--;
181 count = ptr->count;
182 break;
185 LeaveCriticalSection( &IconCrst );
187 return count;
190 /**********************************************************************
191 * CURSORICON_FreeModuleIcons
193 void CURSORICON_FreeModuleIcons( HMODULE hModule )
195 ICONCACHE **ptr = &IconAnchor;
197 if ( HIWORD( hModule ) )
198 hModule = MapHModuleLS( hModule );
199 else
200 hModule = GetExePtr( hModule );
202 EnterCriticalSection( &IconCrst );
204 while ( *ptr )
206 if ( (*ptr)->hModule == hModule )
208 ICONCACHE *freePtr = *ptr;
209 *ptr = freePtr->next;
211 GlobalFree16( freePtr->handle );
212 HeapFree( SystemHeap, 0, freePtr );
213 continue;
215 ptr = &(*ptr)->next;
218 LeaveCriticalSection( &IconCrst );
221 /**********************************************************************
222 * CURSORICON_FindBestIcon
224 * Find the icon closest to the requested size and number of colors.
226 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
227 int height, int colors )
229 int i;
230 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
231 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
232 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
234 if (dir->idCount < 1)
236 WARN_(icon)("Empty directory!\n" );
237 return NULL;
239 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
241 /* Find Best Fit */
242 iTotalDiff = 0xFFFFFFFF;
243 iColorDiff = 0xFFFFFFFF;
244 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
246 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
247 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
249 if(iTotalDiff > (iTempXDiff + iTempYDiff))
251 iXDiff = iTempXDiff;
252 iYDiff = iTempYDiff;
253 iTotalDiff = iXDiff + iYDiff;
257 /* Find Best Colors for Best Fit */
258 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
260 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
261 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
263 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
264 if(iColorDiff > iTempColorDiff)
266 bestEntry = entry;
267 iColorDiff = iTempColorDiff;
272 return bestEntry;
276 /**********************************************************************
277 * CURSORICON_FindBestCursor
279 * Find the cursor closest to the requested size.
280 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
281 * ignored too
283 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
284 int width, int height, int color)
286 int i, maxwidth, maxheight;
287 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
289 if (dir->idCount < 1)
291 WARN_(cursor)("Empty directory!\n" );
292 return NULL;
294 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
296 /* Double height to account for AND and XOR masks */
298 height *= 2;
300 /* First find the largest one smaller than or equal to the requested size*/
302 maxwidth = maxheight = 0;
303 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
304 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
305 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
306 (entry->wBitCount == 1))
308 bestEntry = entry;
309 maxwidth = entry->ResInfo.cursor.wWidth;
310 maxheight = entry->ResInfo.cursor.wHeight;
312 if (bestEntry) return bestEntry;
314 /* Now find the smallest one larger than the requested size */
316 maxwidth = maxheight = 255;
317 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
318 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
319 (entry->wBitCount == 1))
321 bestEntry = entry;
322 maxwidth = entry->ResInfo.cursor.wWidth;
323 maxheight = entry->ResInfo.cursor.wHeight;
326 return bestEntry;
329 /*********************************************************************
330 * The main purpose of this function is to create fake resource directory
331 * and fake resource entries. There are several reasons for this:
332 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
333 * fields
334 * There are some "bad" cursor files which do not have
335 * bColorCount initialized but instead one must read this info
336 * directly from corresponding DIB sections
337 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
339 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
340 CURSORICONDIR **res, LPBYTE **ptr)
342 LPBYTE _free;
343 CURSORICONFILEDIR *bits;
344 int entries, size, i;
346 *res = NULL;
347 *ptr = NULL;
348 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
350 /* FIXME: test for inimated icons
351 * hack to load the first icon from the *.ani file
353 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
354 { LPBYTE pos = (LPBYTE) bits;
355 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
357 for (;;)
358 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
359 { FIXME_(cursor)("icon entry found! %p\n", bits);
360 pos+=4;
361 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
362 { goto fail;
364 bits=(CURSORICONFILEDIR*)(pos+4);
365 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
366 break;
368 pos+=2;
369 if (pos>=(LPBYTE)bits+766) goto fail;
372 if (!(entries = bits->idCount)) goto fail;
373 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
374 _free = (LPBYTE) size;
376 for (i=0; i < entries; i++)
377 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
379 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
380 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
381 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
383 _free = (LPBYTE)(*res) + (int)_free;
384 memcpy((*res), bits, 6);
385 for (i=0; i<entries; i++)
387 ((LPBYTE*)(*ptr))[i] = _free;
388 if (fCursor) {
389 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
390 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
391 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
392 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
393 _free+=sizeof(POINT16);
394 } else {
395 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
396 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
397 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
399 (*res)->idEntries[i].wPlanes=1;
400 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
401 bits->idEntries[i].dwDIBOffset))->biBitCount;
402 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
403 (*res)->idEntries[i].wResId=i+1;
405 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
406 (*res)->idEntries[i].dwBytesInRes);
407 _free += (*res)->idEntries[i].dwBytesInRes;
409 UnmapViewOfFile( bits );
410 return TRUE;
411 fail:
412 if (*res) HeapFree( GetProcessHeap(), 0, *res );
413 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
414 UnmapViewOfFile( bits );
415 return FALSE;
419 /**********************************************************************
420 * CURSORICON_CreateFromResource
422 * Create a cursor or icon from in-memory resource template.
424 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
425 * with cbSize parameter as well.
427 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
428 UINT cbSize, BOOL bIcon, DWORD dwVersion,
429 INT width, INT height, UINT loadflags )
431 int sizeAnd, sizeXor;
432 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
433 BITMAPOBJ *bmpXor, *bmpAnd;
434 POINT16 hotspot;
435 BITMAPINFO *bmi;
436 HDC hdc;
437 BOOL DoStretch;
438 INT size;
440 hotspot.x = ICON_HOTSPOT;
441 hotspot.y = ICON_HOTSPOT;
443 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
444 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
445 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
446 if (dwVersion == 0x00020000)
448 FIXME_(cursor)("\t2.xx resources are not supported\n");
449 return 0;
452 if (bIcon)
453 bmi = (BITMAPINFO *)bits;
454 else /* get the hotspot */
456 POINT16 *pt = (POINT16 *)bits;
457 hotspot = *pt;
458 bmi = (BITMAPINFO *)(pt + 1);
460 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
462 if (!width) width = bmi->bmiHeader.biWidth;
463 if (!height) height = bmi->bmiHeader.biHeight/2;
464 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
465 (bmi->bmiHeader.biWidth != width);
467 /* Check bitmap header */
469 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
470 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
471 bmi->bmiHeader.biCompression != BI_RGB) )
473 WARN_(cursor)("\tinvalid resource bitmap header.\n");
474 return 0;
477 if( (hdc = GetDC( 0 )) )
479 BITMAPINFO* pInfo;
481 /* Make sure we have room for the monochrome bitmap later on.
482 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
483 * up to and including the biBitCount. In-memory icon resource
484 * format is as follows:
486 * BITMAPINFOHEADER icHeader // DIB header
487 * RGBQUAD icColors[] // Color table
488 * BYTE icXOR[] // DIB bits for XOR mask
489 * BYTE icAND[] // DIB bits for AND mask
492 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
493 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
495 memcpy( pInfo, bmi, size );
496 pInfo->bmiHeader.biHeight /= 2;
498 /* Create the XOR bitmap */
500 if (DoStretch) {
501 if(bIcon)
503 hXorBits = CreateCompatibleBitmap(hdc, width, height);
505 else
507 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
509 if(hXorBits)
511 HBITMAP hOld;
512 HDC hMem = CreateCompatibleDC(hdc);
513 BOOL res;
515 if (hMem) {
516 hOld = SelectObject(hMem, hXorBits);
517 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
518 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
519 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
520 SelectObject(hMem, hOld);
521 DeleteDC(hMem);
522 } else res = FALSE;
523 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
525 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
526 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
527 if( hXorBits )
529 char* bits = (char *)bmi + size +
530 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
531 bmi->bmiHeader.biHeight,
532 bmi->bmiHeader.biBitCount) / 2;
534 pInfo->bmiHeader.biBitCount = 1;
535 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
537 RGBQUAD *rgb = pInfo->bmiColors;
539 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
540 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
541 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
542 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
544 else
546 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
548 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
549 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
552 /* Create the AND bitmap */
554 if (DoStretch) {
555 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
556 HBITMAP hOld;
557 HDC hMem = CreateCompatibleDC(hdc);
558 BOOL res;
560 if (hMem) {
561 hOld = SelectObject(hMem, hAndBits);
562 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
563 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
564 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
565 SelectObject(hMem, hOld);
566 DeleteDC(hMem);
567 } else res = FALSE;
568 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
570 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
571 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
573 if( !hAndBits ) DeleteObject( hXorBits );
575 HeapFree( GetProcessHeap(), 0, pInfo );
577 ReleaseDC( 0, hdc );
580 if( !hXorBits || !hAndBits )
582 WARN_(cursor)("\tunable to create an icon bitmap.\n");
583 return 0;
586 /* Now create the CURSORICONINFO structure */
587 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
588 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
589 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
590 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
592 if (hObj) hObj = GlobalReAlloc16( hObj,
593 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
594 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
595 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
596 if (hObj)
598 CURSORICONINFO *info;
600 /* Make it owned by the module */
601 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
603 info = (CURSORICONINFO *)GlobalLock16( hObj );
604 info->ptHotSpot.x = hotspot.x;
605 info->ptHotSpot.y = hotspot.y;
606 info->nWidth = bmpXor->bitmap.bmWidth;
607 info->nHeight = bmpXor->bitmap.bmHeight;
608 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
609 info->bPlanes = bmpXor->bitmap.bmPlanes;
610 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
612 /* Transfer the bitmap bits to the CURSORICONINFO structure */
614 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
615 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
616 GlobalUnlock16( hObj );
619 DeleteObject( hXorBits );
620 DeleteObject( hAndBits );
621 return hObj;
625 /**********************************************************************
626 * CreateIconFromResourceEx16 (USER.450)
628 * FIXME: not sure about exact parameter types
630 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
631 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
633 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
634 width, height, cFlag);
638 /**********************************************************************
639 * CreateIconFromResource (USER32.76)
641 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
642 BOOL bIcon, DWORD dwVersion)
644 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
648 /**********************************************************************
649 * CreateIconFromResourceEx (USER32.77)
651 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
652 BOOL bIcon, DWORD dwVersion,
653 INT width, INT height,
654 UINT cFlag )
656 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
657 if( pTask )
658 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
659 width, height, cFlag );
660 return 0;
663 /**********************************************************************
664 * CURSORICON_Load
666 * Load a cursor or icon from resource or file.
668 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
669 INT width, INT height, INT colors,
670 BOOL fCursor, UINT loadflags )
672 HANDLE handle = 0, h = 0;
673 HANDLE hRsrc;
674 CURSORICONDIR *dir;
675 CURSORICONDIRENTRY *dirEntry;
676 LPBYTE bits;
678 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
680 LPBYTE *ptr;
681 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
682 return 0;
683 if (fCursor)
684 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
685 else
686 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
687 bits = ptr[dirEntry->wResId-1];
688 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
689 !fCursor, 0x00030000, width, height, loadflags);
690 HeapFree( GetProcessHeap(), 0, dir );
691 HeapFree( GetProcessHeap(), 0, ptr );
694 else if ( !hInstance ) /* Load OEM cursor/icon */
696 WORD resid;
697 HDC hdc;
699 if ( HIWORD(name) )
701 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
702 if( ansi[0]=='#') /*Check for '#xxx' name */
704 resid = atoi(ansi+1);
705 HeapFree( GetProcessHeap(), 0, ansi );
707 else
709 HeapFree( GetProcessHeap(), 0, ansi );
710 return 0;
713 else resid = LOWORD(name);
714 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
715 if (hdc) {
716 DC *dc = DC_GetDCPtr( hdc );
717 if (dc->funcs->pLoadOEMResource)
718 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
719 GDI_HEAP_UNLOCK( hdc );
720 DeleteDC( hdc );
724 else /* Load from resource */
726 HANDLE hGroupRsrc;
727 WORD wResId;
728 DWORD dwBytesInRes;
730 /* Normalize hInstance (must be uniquely represented for icon cache) */
732 if ( HIWORD( hInstance ) )
733 hInstance = MapHModuleLS( hInstance );
734 else
735 hInstance = GetExePtr( hInstance );
737 /* Get directory resource ID */
739 if (!(hRsrc = FindResourceW( hInstance, name,
740 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
741 return 0;
742 hGroupRsrc = hRsrc;
743 /* If shared icon, check whether it was already loaded */
745 if ( (loadflags & LR_SHARED)
746 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
747 return h;
749 /* Find the best entry in the directory */
751 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
752 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
753 if (fCursor)
754 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
755 width, height, 1);
756 else
757 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
758 width, height, colors );
759 if (!dirEntry) return 0;
760 wResId = dirEntry->wResId;
761 dwBytesInRes = dirEntry->dwBytesInRes;
762 FreeResource( handle );
764 /* Load the resource */
766 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
767 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
768 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
769 bits = (LPBYTE)LockResource( handle );
770 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
771 !fCursor, 0x00030000, width, height, loadflags);
772 FreeResource( handle );
774 /* If shared icon, add to icon cache */
776 if ( h && (loadflags & LR_SHARED) )
777 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
780 return h;
783 /***********************************************************************
784 * CURSORICON_Copy
786 * Make a copy of a cursor or icon.
788 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
790 char *ptrOld, *ptrNew;
791 int size;
792 HGLOBAL16 hNew;
794 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
795 if (!(hInstance = GetExePtr( hInstance ))) return 0;
796 size = GlobalSize16( handle );
797 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
798 FarSetOwner16( hNew, hInstance );
799 ptrNew = (char *)GlobalLock16( hNew );
800 memcpy( ptrNew, ptrOld, size );
801 GlobalUnlock16( handle );
802 GlobalUnlock16( hNew );
803 return hNew;
806 /*************************************************************************
807 * CURSORICON_ExtCopy
809 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
811 * PARAMS
812 * Handle [I] handle to an Image
813 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
814 * iDesiredCX [I] The Desired width of the Image
815 * iDesiredCY [I] The desired height of the Image
816 * nFlags [I] The flags from CopyImage
818 * RETURNS
819 * Success: The new handle of the Image
821 * NOTES
822 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
823 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
824 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
829 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
830 INT iDesiredCX, INT iDesiredCY,
831 UINT nFlags)
833 HGLOBAL16 hNew=0;
835 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
836 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
838 if(Handle == 0)
840 return 0;
843 /* Best Fit or Monochrome */
844 if( (nFlags & LR_COPYFROMRESOURCE
845 && (iDesiredCX > 0 || iDesiredCY > 0))
846 || nFlags & LR_MONOCHROME)
848 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
850 /* Not Found in Cache, then do a strait copy
852 if(pIconCache == NULL)
854 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
855 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
856 if(nFlags & LR_COPYFROMRESOURCE)
858 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
861 else
863 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
864 LPBYTE pBits;
865 HANDLE hMem;
866 HRSRC hRsrc;
867 DWORD dwBytesInRes;
868 WORD wResId;
869 CURSORICONDIR *pDir;
870 CURSORICONDIRENTRY *pDirEntry;
871 BOOL bIsIcon = (nType == IMAGE_ICON);
873 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
875 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
876 || (iDesiredCX == 0 && iDesiredCY == 0))
878 iDesiredCY = GetSystemMetrics(bIsIcon ?
879 SM_CYICON : SM_CYCURSOR);
880 iDesiredCX = GetSystemMetrics(bIsIcon ?
881 SM_CXICON : SM_CXCURSOR);
884 /* Retreive the CURSORICONDIRENTRY
886 if (!(hMem = LoadResource( pIconCache->hModule ,
887 pIconCache->hGroupRsrc)))
889 return 0;
891 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
893 return 0;
896 /* Find Best Fit
898 if(bIsIcon)
900 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
901 pDir, iDesiredCX, iDesiredCY, 256);
903 else
905 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
906 pDir, iDesiredCX, iDesiredCY, 1);
909 wResId = pDirEntry->wResId;
910 dwBytesInRes = pDirEntry->dwBytesInRes;
911 FreeResource(hMem);
913 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
914 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
915 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
917 /* Get the Best Fit
919 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
920 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
922 return 0;
924 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
926 return 0;
929 pBits = (LPBYTE)LockResource( hMem );
931 if(nFlags & LR_DEFAULTSIZE)
933 iTargetCY = GetSystemMetrics(SM_CYICON);
934 iTargetCX = GetSystemMetrics(SM_CXICON);
937 /* Create a New Icon with the proper dimension
939 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
940 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
941 FreeResource(hMem);
944 else
946 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
947 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
949 return hNew;
952 /***********************************************************************
953 * CURSORICON_IconToCursor
955 * Converts bitmap to mono and truncates if icon is too large (should
956 * probably do StretchBlt() instead).
958 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
960 HCURSOR16 hRet = 0;
961 CURSORICONINFO *pIcon = NULL;
962 HTASK16 hTask = GetCurrentTask();
963 TDB* pTask = (TDB *)GlobalLock16(hTask);
965 if(hIcon && pTask)
966 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
967 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
969 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
972 pIcon = GlobalLock16(hRet);
974 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
976 GlobalUnlock16(hRet);
978 else
980 BYTE pAndBits[128];
981 BYTE pXorBits[128];
982 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
983 BYTE* psPtr, *pxbPtr = pXorBits;
984 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
985 BYTE* pbc = NULL;
987 CURSORICONINFO cI;
989 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
990 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
992 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
993 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
994 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
996 memset(pXorBits, 0, 128);
997 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
998 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
999 cI.nWidth = 32; cI.nHeight = 32;
1000 cI.nWidthBytes = 4; /* 32x1bpp */
1002 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1003 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1005 for( iy = 0; iy < maxy; iy++ )
1007 unsigned shift = iy % 2;
1009 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1010 (and_width > 4) ? 4 : and_width );
1011 for( ix = 0; ix < maxx; ix++ )
1013 if( bSemiTransparent && ((ix+shift)%2) )
1015 /* set AND bit, XOR bit stays 0 */
1017 pbc = pAndBits + iy * 4 + ix/8;
1018 *pbc |= 0x80 >> (ix%8);
1020 else
1022 /* keep AND bit, set XOR bit */
1024 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1025 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1026 if(!PALETTE_Driver->pIsDark(val))
1028 pbc = pxbPtr + ix/8;
1029 *pbc |= 0x80 >> (ix%8);
1033 psPtr += xor_width;
1034 pxbPtr += 4;
1037 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1039 if( !hRet ) /* fall back on default drag cursor */
1040 hRet = CURSORICON_Copy( pTask->hInstance ,
1041 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1042 GetSystemMetrics(SM_CXCURSOR),
1043 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1046 return hRet;
1050 /***********************************************************************
1051 * LoadCursor16 (USER.173)
1053 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1055 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1056 return LoadCursorA( hInstance, nameStr );
1060 /***********************************************************************
1061 * LoadIcon16 (USER.174)
1063 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1065 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1066 return LoadIconA( hInstance, nameStr );
1070 /***********************************************************************
1071 * CreateCursor16 (USER.406)
1073 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1074 INT16 xHotSpot, INT16 yHotSpot,
1075 INT16 nWidth, INT16 nHeight,
1076 LPCVOID lpANDbits, LPCVOID lpXORbits )
1078 CURSORICONINFO info;
1080 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1081 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1083 info.ptHotSpot.x = xHotSpot;
1084 info.ptHotSpot.y = yHotSpot;
1085 info.nWidth = nWidth;
1086 info.nHeight = nHeight;
1087 info.nWidthBytes = 0;
1088 info.bPlanes = 1;
1089 info.bBitsPerPixel = 1;
1091 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1095 /***********************************************************************
1096 * CreateCursor (USER32.67)
1098 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1099 INT xHotSpot, INT yHotSpot,
1100 INT nWidth, INT nHeight,
1101 LPCVOID lpANDbits, LPCVOID lpXORbits )
1103 CURSORICONINFO info;
1105 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1106 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1108 info.ptHotSpot.x = xHotSpot;
1109 info.ptHotSpot.y = yHotSpot;
1110 info.nWidth = nWidth;
1111 info.nHeight = nHeight;
1112 info.nWidthBytes = 0;
1113 info.bPlanes = 1;
1114 info.bBitsPerPixel = 1;
1116 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1120 /***********************************************************************
1121 * CreateIcon16 (USER.407)
1123 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1124 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1125 LPCVOID lpANDbits, LPCVOID lpXORbits )
1127 CURSORICONINFO info;
1129 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1130 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1132 info.ptHotSpot.x = ICON_HOTSPOT;
1133 info.ptHotSpot.y = ICON_HOTSPOT;
1134 info.nWidth = nWidth;
1135 info.nHeight = nHeight;
1136 info.nWidthBytes = 0;
1137 info.bPlanes = bPlanes;
1138 info.bBitsPerPixel = bBitsPixel;
1140 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1144 /***********************************************************************
1145 * CreateIcon (USER32.75)
1147 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1148 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1149 LPCVOID lpANDbits, LPCVOID lpXORbits )
1151 CURSORICONINFO info;
1153 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1154 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1156 info.ptHotSpot.x = ICON_HOTSPOT;
1157 info.ptHotSpot.y = ICON_HOTSPOT;
1158 info.nWidth = nWidth;
1159 info.nHeight = nHeight;
1160 info.nWidthBytes = 0;
1161 info.bPlanes = bPlanes;
1162 info.bBitsPerPixel = bBitsPixel;
1164 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1168 /***********************************************************************
1169 * CreateCursorIconIndirect (USER.408)
1171 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1172 CURSORICONINFO *info,
1173 LPCVOID lpANDbits,
1174 LPCVOID lpXORbits )
1176 HGLOBAL16 handle;
1177 char *ptr;
1178 int sizeAnd, sizeXor;
1180 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1181 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1182 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1183 sizeXor = info->nHeight * info->nWidthBytes;
1184 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1185 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1186 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1187 return 0;
1188 if (hInstance) FarSetOwner16( handle, hInstance );
1189 ptr = (char *)GlobalLock16( handle );
1190 memcpy( ptr, info, sizeof(*info) );
1191 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1192 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1193 GlobalUnlock16( handle );
1194 return handle;
1198 /***********************************************************************
1199 * CopyIcon16 (USER.368)
1201 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1203 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1204 return CURSORICON_Copy( hInstance, hIcon );
1208 /***********************************************************************
1209 * CopyIcon (USER32.60)
1211 HICON WINAPI CopyIcon( HICON hIcon )
1213 HTASK16 hTask = GetCurrentTask ();
1214 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1215 TRACE_(icon)("%04x\n", hIcon );
1216 return CURSORICON_Copy( pTask->hInstance, hIcon );
1220 /***********************************************************************
1221 * CopyCursor16 (USER.369)
1223 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1225 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1226 return CURSORICON_Copy( hInstance, hCursor );
1229 /**********************************************************************
1230 * CURSORICON_Destroy (USER.610)
1232 * This routine is actually exported from Win95 USER under the name
1233 * DestroyIcon32 ... The behaviour implemented here should mimic
1234 * the Win95 one exactly, especially the return values, which
1235 * depend on the setting of various flags.
1237 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1239 WORD retv;
1241 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1243 /* Check whether destroying active cursor */
1245 if ( hActiveCursor == handle )
1247 ERR_(cursor)("Destroying active cursor!\n" );
1248 SetCursor( 0 );
1251 /* Try shared cursor/icon first */
1253 if ( !(flags & CID_NONSHARED) )
1255 INT count = CURSORICON_DelSharedIcon( handle );
1257 if ( count != -1 )
1258 return (flags & CID_WIN32)? TRUE : (count == 0);
1260 /* FIXME: OEM cursors/icons should be recognized */
1263 /* Now assume non-shared cursor/icon */
1265 retv = GlobalFree16( handle );
1266 return (flags & CID_RESOURCE)? retv : TRUE;
1269 /***********************************************************************
1270 * DestroyIcon16 (USER.457)
1272 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1274 return CURSORICON_Destroy( hIcon, 0 );
1277 /***********************************************************************
1278 * DestroyIcon (USER32.133)
1280 BOOL WINAPI DestroyIcon( HICON hIcon )
1282 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1285 /***********************************************************************
1286 * DestroyCursor16 (USER.458)
1288 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1290 return CURSORICON_Destroy( hCursor, 0 );
1293 /***********************************************************************
1294 * DestroyCursor (USER32.132)
1296 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1298 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1302 /***********************************************************************
1303 * DrawIcon16 (USER.84)
1305 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1307 return DrawIcon( hdc, x, y, hIcon );
1311 /***********************************************************************
1312 * DrawIcon (USER32.159)
1314 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1316 CURSORICONINFO *ptr;
1317 HDC hMemDC;
1318 HBITMAP hXorBits, hAndBits;
1319 COLORREF oldFg, oldBg;
1321 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1322 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1323 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1324 (char *)(ptr+1) );
1325 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1326 ptr->bBitsPerPixel, (char *)(ptr + 1)
1327 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1328 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1329 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1331 if (hXorBits && hAndBits)
1333 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1334 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1335 SelectObject( hMemDC, hXorBits );
1336 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1337 SelectObject( hMemDC, hBitTemp );
1339 DeleteDC( hMemDC );
1340 if (hXorBits) DeleteObject( hXorBits );
1341 if (hAndBits) DeleteObject( hAndBits );
1342 GlobalUnlock16( hIcon );
1343 SetTextColor( hdc, oldFg );
1344 SetBkColor( hdc, oldBg );
1345 return TRUE;
1349 /***********************************************************************
1350 * DumpIcon (USER.459)
1352 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1353 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1355 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1356 int sizeAnd, sizeXor;
1358 if (!info) return 0;
1359 sizeXor = info->nHeight * info->nWidthBytes;
1360 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1361 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1362 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1363 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1364 return MAKELONG( sizeXor, sizeXor );
1368 /***********************************************************************
1369 * SetCursor16 (USER.69)
1371 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1373 return (HCURSOR16)SetCursor( hCursor );
1377 /***********************************************************************
1378 * SetCursor (USER32.472)
1379 * RETURNS:
1380 * A handle to the previous cursor shape.
1382 HCURSOR WINAPI SetCursor(
1383 HCURSOR hCursor /* Handle of cursor to show */
1385 HCURSOR hOldCursor;
1387 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1388 TRACE_(cursor)("%04x\n", hCursor );
1389 hOldCursor = hActiveCursor;
1390 hActiveCursor = hCursor;
1391 /* Change the cursor shape only if it is visible */
1392 if (CURSOR_ShowCount >= 0)
1394 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1395 GlobalUnlock16( hActiveCursor );
1397 return hOldCursor;
1401 /***********************************************************************
1402 * SetCursorPos16 (USER.70)
1404 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1406 SetCursorPos( x, y );
1410 /***********************************************************************
1411 * SetCursorPos (USER32.474)
1413 BOOL WINAPI SetCursorPos( INT x, INT y )
1415 DISPLAY_MoveCursor( x, y );
1416 return TRUE;
1420 /***********************************************************************
1421 * ShowCursor16 (USER.71)
1423 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1425 return ShowCursor( bShow );
1429 /***********************************************************************
1430 * ShowCursor (USER32.530)
1432 INT WINAPI ShowCursor( BOOL bShow )
1434 TRACE_(cursor)("%d, count=%d\n",
1435 bShow, CURSOR_ShowCount );
1437 if (bShow)
1439 if (++CURSOR_ShowCount == 0) /* Show it */
1441 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1442 GlobalUnlock16( hActiveCursor );
1445 else
1447 if (--CURSOR_ShowCount == -1) /* Hide it */
1448 DISPLAY_SetCursor( NULL );
1450 return CURSOR_ShowCount;
1454 /***********************************************************************
1455 * GetCursor16 (USER.247)
1457 HCURSOR16 WINAPI GetCursor16(void)
1459 return hActiveCursor;
1463 /***********************************************************************
1464 * GetCursor (USER32.227)
1466 HCURSOR WINAPI GetCursor(void)
1468 return hActiveCursor;
1472 /***********************************************************************
1473 * ClipCursor16 (USER.16)
1475 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1477 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1478 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1479 return TRUE;
1483 /***********************************************************************
1484 * ClipCursor (USER32.53)
1486 BOOL WINAPI ClipCursor( const RECT *rect )
1488 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1489 else CopyRect( &CURSOR_ClipRect, rect );
1490 return TRUE;
1494 /***********************************************************************
1495 * GetCursorPos16 (USER.17)
1497 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1499 if (!pt) return 0;
1501 pt->x = PosX;
1502 pt->y = PosY;
1504 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1505 return 1;
1509 /***********************************************************************
1510 * GetCursorPos (USER32.229)
1512 BOOL WINAPI GetCursorPos( POINT *pt )
1514 BOOL ret;
1516 POINT16 pt16;
1517 ret = GetCursorPos16( &pt16 );
1518 if (pt) CONV_POINT16TO32( &pt16, pt );
1519 return ((pt) ? ret : 0);
1523 /***********************************************************************
1524 * GetClipCursor16 (USER.309)
1526 void WINAPI GetClipCursor16( RECT16 *rect )
1528 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1532 /***********************************************************************
1533 * GetClipCursor (USER32.221)
1535 BOOL WINAPI GetClipCursor( RECT *rect )
1537 if (rect)
1539 CopyRect( rect, &CURSOR_ClipRect );
1540 return TRUE;
1542 return FALSE;
1545 /**********************************************************************
1546 * LookupIconIdFromDirectoryEx16 (USER.364)
1548 * FIXME: exact parameter sizes
1550 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1551 INT16 width, INT16 height, UINT16 cFlag )
1553 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1554 UINT16 retVal = 0;
1555 if( dir && !dir->idReserved && (dir->idType & 3) )
1557 CURSORICONDIRENTRY* entry;
1558 HDC hdc;
1559 UINT palEnts;
1560 int colors;
1561 hdc = GetDC(0);
1562 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1563 if (palEnts == 0)
1564 palEnts = 256;
1565 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1567 ReleaseDC(0, hdc);
1569 if( bIcon )
1570 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1571 else
1572 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1574 if( entry ) retVal = entry->wResId;
1576 else WARN_(cursor)("invalid resource directory\n");
1577 return retVal;
1580 /**********************************************************************
1581 * LookupIconIdFromDirectoryEx (USER32.380)
1583 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1584 INT width, INT height, UINT cFlag )
1586 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1589 /**********************************************************************
1590 * LookupIconIdFromDirectory (USER.???)
1592 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1594 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1595 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1596 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1599 /**********************************************************************
1600 * LookupIconIdFromDirectory (USER32.379)
1602 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1604 return LookupIconIdFromDirectoryEx( dir, bIcon,
1605 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1606 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1609 /**********************************************************************
1610 * GetIconID (USER.455)
1612 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1614 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1616 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1617 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1619 switch(resType)
1621 case RT_CURSOR16:
1622 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1623 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1624 case RT_ICON16:
1625 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1626 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1627 default:
1628 WARN_(cursor)("invalid res type %ld\n", resType );
1630 return 0;
1633 /**********************************************************************
1634 * LoadCursorIconHandler (USER.336)
1636 * Supposed to load resources of Windows 2.x applications.
1638 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1640 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1641 hResource, hModule, hRsrc);
1642 return (HGLOBAL16)0;
1645 /**********************************************************************
1646 * LoadDIBIconHandler (USER.357)
1648 * RT_ICON resource loader, installed by USER_SignalProc when module
1649 * is initialized.
1651 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1653 /* If hResource is zero we must allocate a new memory block, if it's
1654 * non-zero but GlobalLock() returns NULL then it was discarded and
1655 * we have to recommit some memory, otherwise we just need to check
1656 * the block size. See LoadProc() in 16-bit SDK for more.
1659 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1660 if( hMemObj )
1662 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1663 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1664 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1665 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1667 return hMemObj;
1670 /**********************************************************************
1671 * LoadDIBCursorHandler (USER.356)
1673 * RT_CURSOR resource loader. Same as above.
1675 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1677 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1678 if( hMemObj )
1680 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1681 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1682 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1683 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1685 return hMemObj;
1688 /**********************************************************************
1689 * LoadIconHandler (USER.456)
1691 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1693 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1695 TRACE_(cursor)("hRes=%04x\n",hResource);
1697 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1698 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1701 /***********************************************************************
1702 * LoadCursorW (USER32.362)
1704 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1706 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1707 LR_SHARED | LR_DEFAULTSIZE );
1710 /***********************************************************************
1711 * LoadCursorA (USER32.359)
1713 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1715 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1716 LR_SHARED | LR_DEFAULTSIZE );
1719 /***********************************************************************
1720 * LoadCursorFromFileW (USER32.361)
1722 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1724 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1725 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1728 /***********************************************************************
1729 * LoadCursorFromFileA (USER32.360)
1731 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1733 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1734 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1737 /***********************************************************************
1738 * LoadIconW (USER32.364)
1740 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1742 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1743 LR_SHARED | LR_DEFAULTSIZE );
1746 /***********************************************************************
1747 * LoadIconA (USER32.363)
1749 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1751 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1752 LR_SHARED | LR_DEFAULTSIZE );
1755 /**********************************************************************
1756 * GetIconInfo16 (USER.395)
1758 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1760 ICONINFO ii32;
1761 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1763 iconinfo->fIcon = ii32.fIcon;
1764 iconinfo->xHotspot = ii32.xHotspot;
1765 iconinfo->yHotspot = ii32.yHotspot;
1766 iconinfo->hbmMask = ii32.hbmMask;
1767 iconinfo->hbmColor = ii32.hbmColor;
1768 return ret;
1771 /**********************************************************************
1772 * GetIconInfo (USER32.242)
1774 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1775 CURSORICONINFO *ciconinfo;
1777 ciconinfo = GlobalLock16(hIcon);
1778 if (!ciconinfo)
1779 return FALSE;
1781 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1782 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1784 iconinfo->fIcon = TRUE;
1785 iconinfo->xHotspot = 0;
1786 iconinfo->yHotspot = 0;
1788 else
1790 iconinfo->fIcon = FALSE;
1791 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1792 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1795 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1796 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1797 (char *)(ciconinfo + 1)
1798 + ciconinfo->nHeight *
1799 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1800 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1801 1, 1, (char *)(ciconinfo + 1));
1803 GlobalUnlock16(hIcon);
1805 return TRUE;
1808 /**********************************************************************
1809 * CreateIconIndirect (USER32.78)
1811 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1812 BITMAPOBJ *bmpXor,*bmpAnd;
1813 HICON hObj;
1814 int sizeXor,sizeAnd;
1816 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1817 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1819 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1820 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1822 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1823 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1824 if (hObj)
1826 CURSORICONINFO *info;
1828 info = (CURSORICONINFO *)GlobalLock16( hObj );
1830 /* If we are creating an icon, the hotspot is unused */
1831 if (iconinfo->fIcon)
1833 info->ptHotSpot.x = ICON_HOTSPOT;
1834 info->ptHotSpot.y = ICON_HOTSPOT;
1836 else
1838 info->ptHotSpot.x = iconinfo->xHotspot;
1839 info->ptHotSpot.y = iconinfo->yHotspot;
1842 info->nWidth = bmpXor->bitmap.bmWidth;
1843 info->nHeight = bmpXor->bitmap.bmHeight;
1844 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1845 info->bPlanes = bmpXor->bitmap.bmPlanes;
1846 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1848 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1850 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1851 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1852 GlobalUnlock16( hObj );
1854 return hObj;
1858 /**********************************************************************
1860 DrawIconEx16 (USER.394)
1862 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1863 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1864 HBRUSH16 hbr, UINT16 flags)
1866 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1867 istep, hbr, flags);
1871 /******************************************************************************
1872 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1874 * NOTES
1875 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1877 * PARAMS
1878 * hdc [I] Handle to device context
1879 * x0 [I] X coordinate of upper left corner
1880 * y0 [I] Y coordinate of upper left corner
1881 * hIcon [I] Handle to icon to draw
1882 * cxWidth [I] Width of icon
1883 * cyWidth [I] Height of icon
1884 * istep [I] Index of frame in animated cursor
1885 * hbr [I] Handle to background brush
1886 * flags [I] Icon-drawing flags
1888 * RETURNS
1889 * Success: TRUE
1890 * Failure: FALSE
1892 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1893 INT cxWidth, INT cyWidth, UINT istep,
1894 HBRUSH hbr, UINT flags )
1896 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1897 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1898 BOOL result = FALSE, DoOffscreen = FALSE;
1899 HBITMAP hB_off = 0, hOld = 0;
1901 if (!ptr) return FALSE;
1903 if (istep)
1904 FIXME_(icon)("Ignoring istep=%d\n", istep);
1905 if (flags & DI_COMPAT)
1906 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1908 /* Calculate the size of the destination image. */
1909 if (cxWidth == 0)
1911 if (flags & DI_DEFAULTSIZE)
1912 cxWidth = GetSystemMetrics (SM_CXICON);
1913 else
1914 cxWidth = ptr->nWidth;
1916 if (cyWidth == 0)
1918 if (flags & DI_DEFAULTSIZE)
1919 cyWidth = GetSystemMetrics (SM_CYICON);
1920 else
1921 cyWidth = ptr->nHeight;
1924 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1925 STOCK_HOLLOW_BRUSH)))
1927 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1928 if (object)
1930 UINT16 magic = object->wMagic;
1931 GDI_HEAP_UNLOCK(hbr);
1932 DoOffscreen = magic == BRUSH_MAGIC;
1935 if (DoOffscreen) {
1936 RECT r;
1938 r.left = 0;
1939 r.top = 0;
1940 r.right = cxWidth;
1941 r.bottom = cxWidth;
1943 hDC_off = CreateCompatibleDC(hdc);
1944 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1945 if (hDC_off && hB_off) {
1946 hOld = SelectObject(hDC_off, hB_off);
1947 FillRect(hDC_off, &r, hbr);
1951 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1953 HBITMAP hXorBits, hAndBits;
1954 COLORREF oldFg, oldBg;
1955 INT nStretchMode;
1957 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1959 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1960 ptr->bPlanes, ptr->bBitsPerPixel,
1961 (char *)(ptr + 1)
1962 + ptr->nHeight *
1963 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1964 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1965 1, 1, (char *)(ptr+1) );
1966 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1967 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1969 if (hXorBits && hAndBits)
1971 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1972 if (flags & DI_MASK)
1974 if (DoOffscreen)
1975 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1976 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1977 else
1978 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1979 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1981 SelectObject( hMemDC, hXorBits );
1982 if (flags & DI_IMAGE)
1984 if (DoOffscreen)
1985 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1986 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1987 else
1988 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1989 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1991 SelectObject( hMemDC, hBitTemp );
1992 result = TRUE;
1995 SetTextColor( hdc, oldFg );
1996 SetBkColor( hdc, oldBg );
1997 if (hXorBits) DeleteObject( hXorBits );
1998 if (hAndBits) DeleteObject( hAndBits );
1999 SetStretchBltMode (hdc, nStretchMode);
2000 if (DoOffscreen) {
2001 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2002 SelectObject(hDC_off, hOld);
2005 if (hMemDC) DeleteDC( hMemDC );
2006 if (hDC_off) DeleteDC(hDC_off);
2007 if (hB_off) DeleteObject(hB_off);
2008 GlobalUnlock16( hIcon );
2009 return result;
2012 /**********************************************************************
2013 * BITMAP_Load
2015 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2017 HBITMAP hbitmap = 0;
2018 HDC hdc;
2019 HRSRC hRsrc;
2020 HGLOBAL handle;
2021 char *ptr = NULL;
2022 BITMAPINFO *info, *fix_info=NULL;
2023 HGLOBAL hFix;
2024 int size;
2026 if (!(loadflags & LR_LOADFROMFILE)) {
2027 if (!instance) /* OEM bitmap */
2029 HDC hdc;
2030 DC *dc;
2032 if (HIWORD((int)name)) return 0;
2033 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2034 dc = DC_GetDCPtr( hdc );
2035 if(dc->funcs->pLoadOEMResource)
2036 hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name),
2037 OEM_BITMAP );
2038 GDI_HEAP_UNLOCK( hdc );
2039 DeleteDC( hdc );
2040 return hbitmap;
2043 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2044 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2046 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2048 else
2050 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2051 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2053 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2054 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2055 if (fix_info) {
2056 BYTE pix;
2058 memcpy(fix_info, info, size);
2059 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2060 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2061 if ((hdc = GetDC(0)) != 0) {
2062 char *bits = (char *)info + size;
2063 if (loadflags & LR_CREATEDIBSECTION) {
2064 DIBSECTION dib;
2065 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2066 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2067 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2068 DIB_RGB_COLORS);
2070 else {
2071 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2072 bits, fix_info, DIB_RGB_COLORS );
2074 ReleaseDC( 0, hdc );
2076 GlobalUnlock(hFix);
2077 GlobalFree(hFix);
2079 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2080 return hbitmap;
2084 /***********************************************************************
2085 * LoadImage16 [USER.389]
2088 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2089 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2091 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2092 return LoadImageA( hinst, nameStr, type,
2093 desiredx, desiredy, loadflags );
2096 /**********************************************************************
2097 * LoadImageA (USER32.365)
2099 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2102 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2103 INT desiredx, INT desiredy, UINT loadflags)
2105 HANDLE res;
2106 LPWSTR u_name;
2108 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2109 else u_name=(LPWSTR)name;
2110 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2111 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2112 return res;
2116 /******************************************************************************
2117 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2119 * PARAMS
2120 * hinst [I] Handle of instance that contains image
2121 * name [I] Name of image
2122 * type [I] Type of image
2123 * desiredx [I] Desired width
2124 * desiredy [I] Desired height
2125 * loadflags [I] Load flags
2127 * RETURNS
2128 * Success: Handle to newly loaded image
2129 * Failure: NULL
2131 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2133 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2134 INT desiredx, INT desiredy, UINT loadflags )
2136 if (HIWORD(name)) {
2137 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2138 hinst,name,type,desiredx,desiredy,loadflags);
2139 } else {
2140 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2141 hinst,name,type,desiredx,desiredy,loadflags);
2143 if (loadflags & LR_DEFAULTSIZE) {
2144 if (type == IMAGE_ICON) {
2145 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2146 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2147 } else if (type == IMAGE_CURSOR) {
2148 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2149 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2152 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2153 switch (type) {
2154 case IMAGE_BITMAP:
2155 return BITMAP_Load( hinst, name, loadflags );
2157 case IMAGE_ICON:
2159 HDC hdc = GetDC(0);
2160 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2161 if (palEnts == 0)
2162 palEnts = 256;
2163 ReleaseDC(0, hdc);
2165 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2166 palEnts, FALSE, loadflags);
2169 case IMAGE_CURSOR:
2170 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2171 1, TRUE, loadflags);
2173 return 0;
2177 /******************************************************************************
2178 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2181 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2182 INT16 desiredy, UINT16 flags )
2184 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2185 (INT)desiredy, (UINT)flags);
2188 /******************************************************************************
2189 * CopyImage [USER32.61] Creates new image and copies attributes to it
2191 * PARAMS
2192 * hnd [I] Handle to image to copy
2193 * type [I] Type of image to copy
2194 * desiredx [I] Desired width of new image
2195 * desiredy [I] Desired height of new image
2196 * flags [I] Copy flags
2198 * RETURNS
2199 * Success: Handle to newly created image
2200 * Failure: NULL
2202 * FIXME: implementation still lacks nearly all features, see LR_*
2203 * defines in windows.h
2205 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2206 INT desiredy, UINT flags )
2208 switch (type)
2210 case IMAGE_BITMAP:
2211 return BITMAP_CopyBitmap(hnd);
2212 case IMAGE_ICON:
2213 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2214 case IMAGE_CURSOR:
2215 /* Should call CURSORICON_ExtCopy but more testing
2216 * needs to be done before we change this
2218 return CopyCursor(hnd);
2220 return 0;
2224 /******************************************************************************
2225 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2227 * RETURNS
2228 * Success: Handle to specified bitmap
2229 * Failure: NULL
2231 HBITMAP WINAPI LoadBitmapW(
2232 HINSTANCE instance, /* [in] Handle to application instance */
2233 LPCWSTR name) /* [in] Address of bitmap resource name */
2235 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2238 /**********************************************************************
2239 * LoadBitmapA (USER32.357)
2241 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2243 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2246 /**********************************************************************
2247 * LoadBitmap16 (USER.175)
2249 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2251 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2252 return LoadBitmapA( instance, nameStr );