2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
7 * 1998 Turchanov Sergey
13 * http://www.microsoft.com/win32dev/ui/icons.htm
15 * Cursors and icons are stored in a global heap block, with the
18 * CURSORICONINFO info;
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 ?!
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
40 #include "cursoricon.h"
43 #include "sysmetrics.h"
54 static HCURSOR hActiveCursor = 0; /* Active cursor */
55 static INT CURSOR_ShowCount = 0; /* Cursor display count */
56 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
59 /**********************************************************************
60 * ICONCACHE for cursors/icons loaded with LR_SHARED.
62 * FIXME: This should not be allocated on the system heap, but on a
63 * subsystem-global heap (i.e. one for all Win16 processes,
64 * and one each for every Win32 process).
66 typedef struct tagICONCACHE
68 struct tagICONCACHE *next;
78 static ICONCACHE *IconAnchor = NULL;
79 static CRITICAL_SECTION IconCrst;
81 /**********************************************************************
84 void CURSORICON_Init( void )
86 InitializeCriticalSection( &IconCrst );
87 MakeCriticalSectionGlobal( &IconCrst );
90 /**********************************************************************
91 * CURSORICON_FindSharedIcon
93 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
98 EnterCriticalSection( &IconCrst );
100 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
101 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
104 handle = ptr->handle;
108 LeaveCriticalSection( &IconCrst );
113 /**********************************************************************
114 * CURSORICON_AddSharedIcon
116 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
118 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
121 ptr->hModule = hModule;
123 ptr->handle = handle;
126 EnterCriticalSection( &IconCrst );
127 ptr->next = IconAnchor;
129 LeaveCriticalSection( &IconCrst );
132 /**********************************************************************
133 * CURSORICON_DelSharedIcon
135 static INT CURSORICON_DelSharedIcon( HANDLE handle )
140 EnterCriticalSection( &IconCrst );
142 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
143 if ( ptr->handle == handle )
145 if ( ptr->count > 0 ) ptr->count--;
150 LeaveCriticalSection( &IconCrst );
155 /**********************************************************************
156 * CURSORICON_FreeModuleIcons
158 void CURSORICON_FreeModuleIcons( HMODULE hModule )
160 ICONCACHE **ptr = &IconAnchor;
162 if ( HIWORD( hModule ) )
163 hModule = MapHModuleLS( hModule );
165 hModule = GetExePtr( hModule );
167 EnterCriticalSection( &IconCrst );
171 if ( (*ptr)->hModule == hModule )
173 ICONCACHE *freePtr = *ptr;
174 *ptr = freePtr->next;
176 GlobalFree16( freePtr->handle );
177 HeapFree( SystemHeap, 0, freePtr );
183 LeaveCriticalSection( &IconCrst );
186 /**********************************************************************
187 * CURSORICON_FindBestIcon
189 * Find the icon closest to the requested size and number of colors.
191 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
192 int height, int colors )
194 int i, maxcolors, maxwidth, maxheight;
195 ICONDIRENTRY *entry, *bestEntry = NULL;
197 if (dir->idCount < 1)
199 WARN(icon, "Empty directory!\n" );
202 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
204 /* First find the exact size with less colors */
207 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
208 if ((entry->bWidth == width) && (entry->bHeight == height) &&
209 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
212 maxcolors = entry->bColorCount;
214 if (bestEntry) return bestEntry;
216 /* First find the exact size with more colors */
219 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
220 if ((entry->bWidth == width) && (entry->bHeight == height) &&
221 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
224 maxcolors = entry->bColorCount;
226 if (bestEntry) return bestEntry;
228 /* Now find a smaller one with less colors */
230 maxcolors = maxwidth = maxheight = 0;
231 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
232 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
233 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
234 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
237 maxwidth = entry->bWidth;
238 maxheight = entry->bHeight;
239 maxcolors = entry->bColorCount;
241 if (bestEntry) return bestEntry;
243 /* Now find a smaller one with more colors */
246 maxwidth = maxheight = 0;
247 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
248 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
249 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
250 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
253 maxwidth = entry->bWidth;
254 maxheight = entry->bHeight;
255 maxcolors = entry->bColorCount;
257 if (bestEntry) return bestEntry;
259 /* Now find a larger one with less colors */
262 maxwidth = maxheight = 255;
263 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
264 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
265 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
268 maxwidth = entry->bWidth;
269 maxheight = entry->bHeight;
270 maxcolors = entry->bColorCount;
272 if (bestEntry) return bestEntry;
274 /* Now find a larger one with more colors */
276 maxcolors = maxwidth = maxheight = 255;
277 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
278 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
279 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
282 maxwidth = entry->bWidth;
283 maxheight = entry->bHeight;
284 maxcolors = entry->bColorCount;
291 /**********************************************************************
292 * CURSORICON_FindBestCursor
294 * Find the cursor closest to the requested size.
295 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
298 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
299 int width, int height, int color)
301 int i, maxwidth, maxheight;
302 CURSORDIRENTRY *entry, *bestEntry = NULL;
304 if (dir->idCount < 1)
306 WARN(cursor, "Empty directory!\n" );
309 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
311 /* First find the largest one smaller than or equal to the requested size*/
313 maxwidth = maxheight = 0;
314 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
315 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
316 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
317 (entry->wBitCount == 1))
320 maxwidth = entry->wWidth;
321 maxheight = entry->wHeight;
323 if (bestEntry) return bestEntry;
325 /* Now find the smallest one larger than the requested size */
327 maxwidth = maxheight = 255;
328 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
329 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
330 (entry->wBitCount == 1))
333 maxwidth = entry->wWidth;
334 maxheight = entry->wHeight;
340 /*********************************************************************
341 * The main purpose of this function is to create fake resource directory
342 * and fake resource entries. There are several reasons for this:
343 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
345 * There are some "bad" cursor files which do not have
346 * bColorCount initialized but instead one must read this info
347 * directly from corresponding DIB sections
348 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
350 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
351 CURSORICONDIR **res, LPBYTE **ptr)
354 CURSORICONFILEDIR *bits;
355 int entries, size, i;
359 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
361 /* FIXME: test for inimated icons
362 * hack to load the first icon from the *.ani file
364 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
365 { LPBYTE pos = (LPBYTE) bits;
366 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
369 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
370 { FIXME (cursor,"icon entry found! %p\n", bits);
372 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
376 FIXME (cursor,"icon size ok %p \n", bits);
380 if (pos>=(LPBYTE)bits+766) goto fail;
383 if (!(entries = bits->idCount)) goto fail;
384 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
386 for (i=0; i < entries; i++)
387 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
389 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
390 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
391 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
393 _free = (LPBYTE)(*res) + (int)_free;
394 memcpy((*res), bits, 6);
395 for (i=0; i<entries; i++)
397 ((LPBYTE*)(*ptr))[i] = _free;
399 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
400 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
401 (*res)->idEntries[i].cursor.wPlanes=1;
402 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
403 bits->idEntries[i].dwDIBOffset))->biBitCount;
404 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
405 (*res)->idEntries[i].cursor.wResId=i+1;
406 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
407 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
408 _free+=sizeof(POINT16);
410 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
411 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
412 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
413 (*res)->idEntries[i].icon.wPlanes=1;
414 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
415 bits->idEntries[i].dwDIBOffset))->biBitCount;
416 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
417 (*res)->idEntries[i].icon.wResId=i+1;
419 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
420 (*res)->idEntries[i].icon.dwBytesInRes);
421 _free += (*res)->idEntries[i].icon.dwBytesInRes;
423 UnmapViewOfFile( bits );
426 if (*res) HeapFree( GetProcessHeap(), 0, *res );
427 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
428 UnmapViewOfFile( bits );
433 /**********************************************************************
434 * CURSORICON_CreateFromResource
436 * Create a cursor or icon from in-memory resource template.
438 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
439 * with cbSize parameter as well.
441 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
442 UINT cbSize, BOOL bIcon, DWORD dwVersion,
443 INT width, INT height, UINT loadflags )
445 int sizeAnd, sizeXor;
446 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
447 BITMAPOBJ *bmpXor, *bmpAnd;
448 POINT16 hotspot = { 0 ,0 };
454 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
455 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
456 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
457 if (dwVersion == 0x00020000)
459 FIXME(cursor,"\t2.xx resources are not supported\n");
464 bmi = (BITMAPINFO *)bits;
465 else /* get the hotspot */
467 POINT16 *pt = (POINT16 *)bits;
469 bmi = (BITMAPINFO *)(pt + 1);
471 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
473 if (!width) width = bmi->bmiHeader.biWidth;
474 if (!height) height = bmi->bmiHeader.biHeight/2;
475 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
476 (bmi->bmiHeader.biWidth != width);
478 /* Check bitmap header */
480 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
481 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
482 bmi->bmiHeader.biCompression != BI_RGB) )
484 WARN(cursor,"\tinvalid resource bitmap header.\n");
488 if( (hdc = GetDC( 0 )) )
492 /* Make sure we have room for the monochrome bitmap later on.
493 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
494 * up to and including the biBitCount. In-memory icon resource
495 * format is as follows:
497 * BITMAPINFOHEADER icHeader // DIB header
498 * RGBQUAD icColors[] // Color table
499 * BYTE icXOR[] // DIB bits for XOR mask
500 * BYTE icAND[] // DIB bits for AND mask
503 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
504 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
506 memcpy( pInfo, bmi, size );
507 pInfo->bmiHeader.biHeight /= 2;
509 /* Create the XOR bitmap */
512 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
514 HDC hMem = CreateCompatibleDC(hdc);
518 hOld = SelectObject(hMem, hXorBits);
519 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
520 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
521 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
522 SelectObject(hMem, hOld);
525 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
527 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
528 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
531 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
532 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
533 bmi->bmiHeader.biBitCount) / 2;
535 pInfo->bmiHeader.biBitCount = 1;
536 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
538 RGBQUAD *rgb = pInfo->bmiColors;
540 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
541 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
542 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
543 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
547 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
549 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
550 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
553 /* Create the AND bitmap */
556 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
558 HDC hMem = CreateCompatibleDC(hdc);
562 hOld = SelectObject(hMem, hAndBits);
563 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
564 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
565 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
566 SelectObject(hMem, hOld);
569 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
571 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
572 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
574 if( !hAndBits ) DeleteObject( hXorBits );
576 HeapFree( GetProcessHeap(), 0, pInfo );
581 if( !hXorBits || !hAndBits )
583 WARN(cursor,"\tunable to create an icon bitmap.\n");
587 /* Now create the CURSORICONINFO structure */
588 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
589 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
590 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
591 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
593 if (hObj) hObj = GlobalReAlloc16( hObj,
594 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
595 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
596 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
599 CURSORICONINFO *info;
601 /* Make it owned by the module */
602 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
604 info = (CURSORICONINFO *)GlobalLock16( hObj );
605 info->ptHotSpot.x = hotspot.x;
606 info->ptHotSpot.y = hotspot.y;
607 info->nWidth = bmpXor->bitmap.bmWidth;
608 info->nHeight = bmpXor->bitmap.bmHeight;
609 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
610 info->bPlanes = bmpXor->bitmap.bmPlanes;
611 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
613 /* Transfer the bitmap bits to the CURSORICONINFO structure */
615 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
616 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
617 GlobalUnlock16( hObj );
620 DeleteObject( hXorBits );
621 DeleteObject( hAndBits );
626 /**********************************************************************
627 * CreateIconFromResourceEx16 (USER.450)
629 * FIXME: not sure about exact parameter types
631 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
632 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
634 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
635 width, height, cFlag);
639 /**********************************************************************
640 * CreateIconFromResource (USER32.76)
642 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
643 BOOL bIcon, DWORD dwVersion)
645 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
649 /**********************************************************************
650 * CreateIconFromResourceEx32 (USER32.77)
652 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
653 BOOL bIcon, DWORD dwVersion,
654 INT width, INT height,
657 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
659 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
660 width, height, cFlag );
664 /**********************************************************************
667 * Load a cursor or icon from resource or file.
669 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
670 INT width, INT height, INT colors,
671 BOOL fCursor, UINT loadflags )
673 HANDLE handle = 0, h = 0;
676 CURSORICONDIRENTRY *dirEntry;
679 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
682 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
685 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
687 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
688 bits = ptr[dirEntry->icon.wResId-1];
689 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->icon.dwBytesInRes,
690 !fCursor, 0x00030000, width, height, loadflags);
691 HeapFree( GetProcessHeap(), 0, dir );
692 HeapFree( GetProcessHeap(), 0, ptr );
695 else if ( !hInstance ) /* Load OEM cursor/icon */
703 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
704 if( ansi[0]=='#') /*Check for '#xxx' name */
706 resid = atoi(ansi+1);
707 HeapFree( GetProcessHeap(), 0, ansi );
711 HeapFree( GetProcessHeap(), 0, ansi );
715 else resid = LOWORD(name);
716 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
717 dc = DC_GetDCPtr( hdc );
718 if (dc->funcs->pLoadOEMResource)
719 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
720 OEM_CURSOR : OEM_ICON );
721 GDI_HEAP_UNLOCK( hdc );
725 else /* Load from resource */
730 /* Normalize hInstance (must be uniquely represented for icon cache) */
732 if ( HIWORD( hInstance ) )
733 hInstance = MapHModuleLS( hInstance );
735 hInstance = GetExePtr( hInstance );
737 /* Get directory resource ID */
739 if (!(hRsrc = FindResourceW( hInstance, name,
740 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
743 /* If shared icon, check whether it was already loaded */
745 if ( (loadflags & LR_SHARED)
746 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
749 /* Find the best entry in the directory */
751 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
752 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
754 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
757 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
758 width, height, colors );
759 if (!dirEntry) return 0;
760 wResId = dirEntry->icon.wResId;
761 dwBytesInRes = dirEntry->icon.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, h );
783 /***********************************************************************
786 * Make a copy of a cursor or icon.
788 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
790 char *ptrOld, *ptrNew;
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 );
806 /***********************************************************************
807 * CURSORICON_IconToCursor
809 * Converts bitmap to mono and truncates if icon is too large (should
810 * probably do StretchBlt() instead).
812 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
815 CURSORICONINFO *pIcon = NULL;
816 HTASK16 hTask = GetCurrentTask();
817 TDB* pTask = (TDB *)GlobalLock16(hTask);
820 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
821 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
822 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
827 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
828 BYTE* psPtr, *pxbPtr = pXorBits;
829 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
834 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
835 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
837 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
838 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
839 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
841 memset(pXorBits, 0, 128);
842 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
843 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
844 cI.nWidth = 32; cI.nHeight = 32;
845 cI.nWidthBytes = 4; /* 32x1bpp */
847 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
848 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
850 for( iy = 0; iy < maxy; iy++ )
852 unsigned shift = iy % 2;
854 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
855 (and_width > 4) ? 4 : and_width );
856 for( ix = 0; ix < maxx; ix++ )
858 if( bSemiTransparent && ((ix+shift)%2) )
860 /* set AND bit, XOR bit stays 0 */
862 pbc = pAndBits + iy * 4 + ix/8;
863 *pbc |= 0x80 >> (ix%8);
867 /* keep AND bit, set XOR bit */
869 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
870 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
871 if(!PALETTE_Driver->pIsDark(val))
874 *pbc |= 0x80 >> (ix%8);
882 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
884 if( !hRet ) /* fall back on default drag cursor */
885 hRet = CURSORICON_Copy( pTask->hInstance ,
886 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
887 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
894 /***********************************************************************
895 * LoadCursor16 (USER.173)
897 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
899 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
900 return LoadCursorA( hInstance, nameStr );
904 /***********************************************************************
905 * LoadIcon16 (USER.174)
907 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
909 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
910 return LoadIconA( hInstance, nameStr );
914 /***********************************************************************
915 * CreateCursor16 (USER.406)
917 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
918 INT16 xHotSpot, INT16 yHotSpot,
919 INT16 nWidth, INT16 nHeight,
920 LPCVOID lpANDbits, LPCVOID lpXORbits )
922 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
924 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
925 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
926 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
930 /***********************************************************************
931 * CreateCursor32 (USER32.67)
933 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
934 INT xHotSpot, INT yHotSpot,
935 INT nWidth, INT nHeight,
936 LPCVOID lpANDbits, LPCVOID lpXORbits )
938 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
940 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
941 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
942 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
946 /***********************************************************************
947 * CreateIcon16 (USER.407)
949 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
950 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
951 LPCVOID lpANDbits, LPCVOID lpXORbits )
953 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
955 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
956 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
957 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
961 /***********************************************************************
962 * CreateIcon32 (USER32.75)
964 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
965 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
966 LPCVOID lpANDbits, LPCVOID lpXORbits )
968 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
970 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
971 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
972 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
976 /***********************************************************************
977 * CreateCursorIconIndirect (USER.408)
979 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
980 CURSORICONINFO *info,
986 int sizeAnd, sizeXor;
988 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
989 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
990 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
991 sizeXor = info->nHeight * info->nWidthBytes;
992 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
993 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
994 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
996 if (hInstance) FarSetOwner16( handle, hInstance );
997 ptr = (char *)GlobalLock16( handle );
998 memcpy( ptr, info, sizeof(*info) );
999 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1000 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1001 GlobalUnlock16( handle );
1006 /***********************************************************************
1007 * CopyIcon16 (USER.368)
1009 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1011 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1012 return CURSORICON_Copy( hInstance, hIcon );
1016 /***********************************************************************
1017 * CopyIcon32 (USER32.60)
1019 HICON WINAPI CopyIcon( HICON hIcon )
1021 HTASK16 hTask = GetCurrentTask ();
1022 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1023 TRACE(icon, "%04x\n", hIcon );
1024 return CURSORICON_Copy( pTask->hInstance, hIcon );
1028 /***********************************************************************
1029 * CopyCursor16 (USER.369)
1031 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1033 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1034 return CURSORICON_Copy( hInstance, hCursor );
1037 /**********************************************************************
1038 * CURSORICON_Destroy (USER.610)
1040 * This routine is actually exported from Win95 USER under the name
1041 * DestroyIcon32 ... The behaviour implemented here should mimic
1042 * the Win95 one exactly, especially the return values, which
1043 * depend on the setting of various flags.
1045 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1049 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1051 /* Check whether destroying active cursor */
1053 if ( hActiveCursor == handle )
1055 ERR( cursor, "Destroying active cursor!\n" );
1059 /* Try shared cursor/icon first */
1061 if ( !(flags & CID_NONSHARED) )
1063 INT count = CURSORICON_DelSharedIcon( handle );
1066 return (flags & CID_WIN32)? TRUE : (count == 0);
1068 /* FIXME: OEM cursors/icons should be recognized */
1071 /* Now assume non-shared cursor/icon */
1073 retv = GlobalFree16( handle );
1074 return (flags & CID_RESOURCE)? retv : TRUE;
1077 /***********************************************************************
1078 * DestroyIcon16 (USER.457)
1080 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1082 return CURSORICON_Destroy( hIcon, 0 );
1085 /***********************************************************************
1086 * DestroyIcon (USER32.133)
1088 BOOL WINAPI DestroyIcon( HICON hIcon )
1090 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1093 /***********************************************************************
1094 * DestroyCursor16 (USER.458)
1096 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1098 return CURSORICON_Destroy( hCursor, 0 );
1101 /***********************************************************************
1102 * DestroyCursor (USER32.132)
1104 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1106 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1110 /***********************************************************************
1111 * DrawIcon16 (USER.84)
1113 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1115 return DrawIcon( hdc, x, y, hIcon );
1119 /***********************************************************************
1120 * DrawIcon32 (USER32.159)
1122 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1124 CURSORICONINFO *ptr;
1126 HBITMAP hXorBits, hAndBits;
1127 COLORREF oldFg, oldBg;
1129 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1130 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1131 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1133 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1134 ptr->bBitsPerPixel, (char *)(ptr + 1)
1135 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1136 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1137 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1139 if (hXorBits && hAndBits)
1141 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1142 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1143 SelectObject( hMemDC, hXorBits );
1144 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1145 SelectObject( hMemDC, hBitTemp );
1148 if (hXorBits) DeleteObject( hXorBits );
1149 if (hAndBits) DeleteObject( hAndBits );
1150 GlobalUnlock16( hIcon );
1151 SetTextColor( hdc, oldFg );
1152 SetBkColor( hdc, oldBg );
1157 /***********************************************************************
1158 * DumpIcon (USER.459)
1160 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1161 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1163 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1164 int sizeAnd, sizeXor;
1166 if (!info) return 0;
1167 sizeXor = info->nHeight * info->nWidthBytes;
1168 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1169 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1170 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1171 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1172 return MAKELONG( sizeXor, sizeXor );
1176 /***********************************************************************
1177 * SetCursor16 (USER.69)
1179 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1181 return (HCURSOR16)SetCursor( hCursor );
1185 /***********************************************************************
1186 * SetCursor32 (USER32.472)
1188 * A handle to the previous cursor shape.
1190 HCURSOR WINAPI SetCursor(
1191 HCURSOR hCursor /* Handle of cursor to show */
1195 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1196 TRACE(cursor, "%04x\n", hCursor );
1197 hOldCursor = hActiveCursor;
1198 hActiveCursor = hCursor;
1199 /* Change the cursor shape only if it is visible */
1200 if (CURSOR_ShowCount >= 0)
1202 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1203 GlobalUnlock16( hActiveCursor );
1209 /***********************************************************************
1210 * SetCursorPos16 (USER.70)
1212 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1214 SetCursorPos( x, y );
1218 /***********************************************************************
1219 * SetCursorPos32 (USER32.474)
1221 BOOL WINAPI SetCursorPos( INT x, INT y )
1223 DISPLAY_MoveCursor( x, y );
1228 /***********************************************************************
1229 * ShowCursor16 (USER.71)
1231 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1233 return ShowCursor( bShow );
1237 /***********************************************************************
1238 * ShowCursor32 (USER32.530)
1240 INT WINAPI ShowCursor( BOOL bShow )
1242 TRACE(cursor, "%d, count=%d\n",
1243 bShow, CURSOR_ShowCount );
1247 if (++CURSOR_ShowCount == 0) /* Show it */
1249 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1250 GlobalUnlock16( hActiveCursor );
1255 if (--CURSOR_ShowCount == -1) /* Hide it */
1256 DISPLAY_SetCursor( NULL );
1258 return CURSOR_ShowCount;
1262 /***********************************************************************
1263 * GetCursor16 (USER.247)
1265 HCURSOR16 WINAPI GetCursor16(void)
1267 return hActiveCursor;
1271 /***********************************************************************
1272 * GetCursor32 (USER32.227)
1274 HCURSOR WINAPI GetCursor(void)
1276 return hActiveCursor;
1280 /***********************************************************************
1281 * ClipCursor16 (USER.16)
1283 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1285 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1286 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1291 /***********************************************************************
1292 * ClipCursor32 (USER32.53)
1294 BOOL WINAPI ClipCursor( const RECT *rect )
1296 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1297 else CopyRect( &CURSOR_ClipRect, rect );
1302 /***********************************************************************
1303 * GetCursorPos16 (USER.17)
1305 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1307 DWORD posX, posY, state;
1310 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1316 if (state & MK_LBUTTON)
1317 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1319 MouseButtonsStates[0] = FALSE;
1320 if (state & MK_MBUTTON)
1321 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1323 MouseButtonsStates[1] = FALSE;
1324 if (state & MK_RBUTTON)
1325 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1327 MouseButtonsStates[2] = FALSE;
1329 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1334 /***********************************************************************
1335 * GetCursorPos32 (USER32.229)
1337 BOOL WINAPI GetCursorPos( POINT *pt )
1342 ret = GetCursorPos16( &pt16 );
1343 if (pt) CONV_POINT16TO32( &pt16, pt );
1344 return ((pt) ? ret : 0);
1348 /***********************************************************************
1349 * GetClipCursor16 (USER.309)
1351 void WINAPI GetClipCursor16( RECT16 *rect )
1353 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1357 /***********************************************************************
1358 * GetClipCursor32 (USER32.221)
1360 BOOL WINAPI GetClipCursor( RECT *rect )
1364 CopyRect( rect, &CURSOR_ClipRect );
1370 /**********************************************************************
1371 * LookupIconIdFromDirectoryEx16 (USER.364)
1373 * FIXME: exact parameter sizes
1375 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1376 INT16 width, INT16 height, UINT16 cFlag )
1378 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1380 if( dir && !dir->idReserved && (dir->idType & 3) )
1383 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1384 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1389 ICONDIRENTRY* entry;
1390 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1391 if( entry ) retVal = entry->wResId;
1395 CURSORDIRENTRY* entry;
1396 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1397 if( entry ) retVal = entry->wResId;
1400 else WARN(cursor, "invalid resource directory\n");
1404 /**********************************************************************
1405 * LookupIconIdFromDirectoryEx32 (USER32.380)
1407 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1408 INT width, INT height, UINT cFlag )
1410 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1413 /**********************************************************************
1414 * LookupIconIdFromDirectory (USER.???)
1416 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1418 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1419 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1420 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1423 /**********************************************************************
1424 * LookupIconIdFromDirectory (USER32.379)
1426 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1428 return LookupIconIdFromDirectoryEx( dir, bIcon,
1429 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1430 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1433 /**********************************************************************
1434 * GetIconID (USER.455)
1436 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1438 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1440 TRACE(cursor, "hRes=%04x, entries=%i\n",
1441 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1446 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1447 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1449 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1450 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1452 WARN(cursor, "invalid res type %ld\n", resType );
1457 /**********************************************************************
1458 * LoadCursorIconHandler (USER.336)
1460 * Supposed to load resources of Windows 2.x applications.
1462 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1464 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1465 hResource, hModule, hRsrc);
1466 return (HGLOBAL16)0;
1469 /**********************************************************************
1470 * LoadDIBIconHandler (USER.357)
1472 * RT_ICON resource loader, installed by USER_SignalProc when module
1475 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1477 /* If hResource is zero we must allocate a new memory block, if it's
1478 * non-zero but GlobalLock() returns NULL then it was discarded and
1479 * we have to recommit some memory, otherwise we just need to check
1480 * the block size. See LoadProc() in 16-bit SDK for more.
1483 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1486 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1487 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1488 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1489 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1494 /**********************************************************************
1495 * LoadDIBCursorHandler (USER.356)
1497 * RT_CURSOR resource loader. Same as above.
1499 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1501 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1504 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1505 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1506 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1507 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1512 /**********************************************************************
1513 * LoadIconHandler (USER.456)
1515 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1517 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1519 TRACE(cursor,"hRes=%04x\n",hResource);
1521 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1522 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1525 /***********************************************************************
1526 * LoadCursorW (USER32.362)
1528 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1530 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1531 LR_SHARED | LR_DEFAULTSIZE );
1534 /***********************************************************************
1535 * LoadCursorA (USER32.359)
1537 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1539 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1540 LR_SHARED | LR_DEFAULTSIZE );
1543 /***********************************************************************
1544 * LoadCursorFromFileW (USER32.361)
1546 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1548 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1549 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1552 /***********************************************************************
1553 * LoadCursorFromFileA (USER32.360)
1555 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1557 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1558 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1561 /***********************************************************************
1562 * LoadIconW (USER32.364)
1564 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1566 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1567 LR_SHARED | LR_DEFAULTSIZE );
1570 /***********************************************************************
1571 * LoadIconA (USER32.363)
1573 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1575 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1576 LR_SHARED | LR_DEFAULTSIZE );
1579 /**********************************************************************
1580 * GetIconInfo16 (USER.395)
1582 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1585 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1587 iconinfo->fIcon = ii32.fIcon;
1588 iconinfo->xHotspot = ii32.xHotspot;
1589 iconinfo->yHotspot = ii32.yHotspot;
1590 iconinfo->hbmMask = ii32.hbmMask;
1591 iconinfo->hbmColor = ii32.hbmColor;
1595 /**********************************************************************
1596 * GetIconInfo32 (USER32.242)
1598 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1599 CURSORICONINFO *ciconinfo;
1601 ciconinfo = GlobalLock16(hIcon);
1604 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1605 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1606 iconinfo->fIcon = TRUE; /* hmm */
1608 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1609 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1610 (char *)(ciconinfo + 1)
1611 + ciconinfo->nHeight *
1612 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1613 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1614 1, 1, (char *)(ciconinfo + 1));
1616 GlobalUnlock16(hIcon);
1621 /**********************************************************************
1622 * CreateIconIndirect (USER32.78)
1624 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1625 BITMAPOBJ *bmpXor,*bmpAnd;
1627 int sizeXor,sizeAnd;
1629 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1630 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1632 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1633 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1635 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1636 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1639 CURSORICONINFO *info;
1641 info = (CURSORICONINFO *)GlobalLock16( hObj );
1642 info->ptHotSpot.x = iconinfo->xHotspot;
1643 info->ptHotSpot.y = iconinfo->yHotspot;
1644 info->nWidth = bmpXor->bitmap.bmWidth;
1645 info->nHeight = bmpXor->bitmap.bmHeight;
1646 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1647 info->bPlanes = bmpXor->bitmap.bmPlanes;
1648 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1650 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1652 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1653 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1654 GlobalUnlock16( hObj );
1660 /**********************************************************************
1662 DrawIconEx16 (USER.394)
1664 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1665 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1666 HBRUSH16 hbr, UINT16 flags)
1668 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1673 /******************************************************************************
1674 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1677 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1680 * hdc [I] Handle to device context
1681 * x0 [I] X coordinate of upper left corner
1682 * y0 [I] Y coordinate of upper left corner
1683 * hIcon [I] Handle to icon to draw
1684 * cxWidth [I] Width of icon
1685 * cyWidth [I] Height of icon
1686 * istep [I] Index of frame in animated cursor
1687 * hbr [I] Handle to background brush
1688 * flags [I] Icon-drawing flags
1694 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1695 INT cxWidth, INT cyWidth, UINT istep,
1696 HBRUSH hbr, UINT flags )
1698 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1699 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1700 BOOL result = FALSE, DoOffscreen = FALSE;
1701 HBITMAP hB_off = 0, hOld = 0;
1703 if (!ptr) return FALSE;
1706 FIXME(icon, "Ignoring istep=%d\n", istep);
1707 if (flags & DI_COMPAT)
1708 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1710 /* Calculate the size of the destination image. */
1713 if (flags & DI_DEFAULTSIZE)
1714 cxWidth = GetSystemMetrics (SM_CXICON);
1716 cxWidth = ptr->nWidth;
1720 if (flags & DI_DEFAULTSIZE)
1721 cyWidth = GetSystemMetrics (SM_CYICON);
1723 cyWidth = ptr->nHeight;
1726 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1727 STOCK_HOLLOW_BRUSH)))
1729 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1732 UINT16 magic = object->wMagic;
1733 GDI_HEAP_UNLOCK(hbr);
1734 DoOffscreen = magic == BRUSH_MAGIC;
1738 RECT r = {0, 0, cxWidth, cxWidth};
1740 hDC_off = CreateCompatibleDC(hdc);
1741 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1742 if (hDC_off && hB_off) {
1743 hOld = SelectObject(hDC_off, hB_off);
1744 FillRect(hDC_off, &r, hbr);
1748 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1750 HBITMAP hXorBits, hAndBits;
1751 COLORREF oldFg, oldBg;
1754 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1756 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1757 ptr->bPlanes, ptr->bBitsPerPixel,
1760 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1761 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1762 1, 1, (char *)(ptr+1) );
1763 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1764 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1766 if (hXorBits && hAndBits)
1768 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1769 if (flags & DI_MASK)
1772 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1773 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1775 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1776 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1778 SelectObject( hMemDC, hXorBits );
1779 if (flags & DI_IMAGE)
1782 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1783 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1785 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1786 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1788 SelectObject( hMemDC, hBitTemp );
1792 SetTextColor( hdc, oldFg );
1793 SetBkColor( hdc, oldBg );
1794 if (hXorBits) DeleteObject( hXorBits );
1795 if (hAndBits) DeleteObject( hAndBits );
1796 SetStretchBltMode (hdc, nStretchMode);
1798 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1799 SelectObject(hDC_off, hOld);
1802 if (hMemDC) DeleteDC( hMemDC );
1803 if (hDC_off) DeleteDC(hDC_off);
1804 if (hB_off) DeleteObject(hB_off);
1805 GlobalUnlock16( hIcon );