diff --git a/reactos/dll/win32/user32/user32.rbuild b/reactos/dll/win32/user32/user32.rbuild index 21ee5444b6b..6a08d960d73 100644 --- a/reactos/dll/win32/user32/user32.rbuild +++ b/reactos/dll/win32/user32/user32.rbuild @@ -48,18 +48,16 @@ accel.c - bitmap.c caret.c class.c clipboard.c - cursor.c + cursoricon.c dc.c defwnd.c dialog.c draw.c font.c hook.c - icon.c input.c mdi.c menu.c diff --git a/reactos/dll/win32/user32/windows/bitmap.c b/reactos/dll/win32/user32/windows/bitmap.c deleted file mode 100644 index 41486c565f8..00000000000 --- a/reactos/dll/win32/user32/windows/bitmap.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* $Id$ - * - * PROJECT: ReactOS user32.dll - * FILE: lib/user32/windows/input.c - * PURPOSE: Input - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 09-05-2001 CSH Created - */ - -/* INCLUDES ******************************************************************/ - -#include - -#include -WINE_DEFAULT_DEBUG_CHANNEL(user32); - -#include "pshpack1.h" - -typedef struct { - BYTE bWidth; - BYTE bHeight; - BYTE bColorCount; - BYTE bReserved; - WORD xHotspot; - WORD yHotspot; - DWORD dwDIBSize; - DWORD dwDIBOffset; -} CURSORICONFILEDIRENTRY; - -typedef struct -{ - WORD idReserved; - WORD idType; - WORD idCount; - CURSORICONFILEDIRENTRY idEntries[1]; -} CURSORICONFILEDIR; - -#include "poppack.h" - -/* forward declarations... actually in user32\windows\icon.c but useful here */ -HICON CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon); -CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors); -CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors); - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -HANDLE WINAPI -LoadImageA(HINSTANCE hinst, - LPCSTR lpszName, - UINT uType, - int cxDesired, - int cyDesired, - UINT fuLoad) -{ - LPWSTR lpszWName; - HANDLE Handle; - UNICODE_STRING NameString; - - if (HIWORD(lpszName)) - { - RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName); - lpszWName = NameString.Buffer; - Handle = LoadImageW(hinst, lpszWName, uType, cxDesired, - cyDesired, fuLoad); - RtlFreeUnicodeString(&NameString); - } - else - { - Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired, - cyDesired, fuLoad); - } - - return Handle; -} - - -/* - * The following macro functions account for the irregularities of - * accessing cursor and icon resources in files and resource entries. - */ -typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n, - int *width, int *height, int *bits ); - -/********************************************************************** - * CURSORICON_FindBestCursor2 - * - * Find the cursor closest to the requested size. - * FIXME: parameter 'color' ignored and entries with more than 1 bpp - * ignored too - */ -static int CURSORICON_FindBestCursor2( LPVOID dir, fnGetCIEntry get_entry, - int width, int height, int color ) -{ - int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1; - - /* Double height to account for AND and XOR masks */ - - height *= 2; - - /* First find the largest one smaller than or equal to the requested size*/ - - maxwidth = maxheight = 0; - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) - { - if ((cx <= width) && (cy <= height) && - (cx > maxwidth) && (cy > maxheight) && - (bits == 1)) - { - bestEntry = i; - maxwidth = cx; - maxheight = cy; - } - } - if (bestEntry != -1) return bestEntry; - - /* Now find the smallest one larger than the requested size */ - - maxwidth = maxheight = 255; - for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) - { - if (((cx < maxwidth) && (cy < maxheight) && (bits == 1)) || - (bestEntry==-1)) - { - bestEntry = i; - maxwidth = cx; - maxheight = cy; - } - } - - return bestEntry; -} - -static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n, - int *width, int *height, int *bits ) -{ - CURSORICONFILEDIR *filedir = dir; - CURSORICONFILEDIRENTRY *entry; - - if ( filedir->idCount <= n ) - return FALSE; - entry = &filedir->idEntries[n]; - *width = entry->bWidth; - *height = entry->bHeight; - *bits = entry->bColorCount; - return TRUE; -} - -static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, - int width, int height, int color ) -{ - int n = CURSORICON_FindBestCursor2( dir, CURSORICON_GetFileEntry, - width, height, color ); - if ( n < 0 ) - return NULL; - return &dir->idEntries[n]; -} - -static HANDLE -LoadCursorIconImage( - HINSTANCE hinst, - LPCWSTR lpszName, - INT width, - INT height, - UINT fuLoad, - ULONG uType) -{ - HRSRC hResInfo; - HANDLE hResource; - HANDLE hFile; - HANDLE hSection; - CURSORICONFILEDIR *IconDIR; - HDC hScreenDc; - HICON hIcon; - ULONG HeaderSize; - ULONG ColorCount; - ULONG ColorBits; - PVOID Data; - CURSORICONFILEDIRENTRY* dirEntry; - ICONIMAGE* SafeIconImage = NULL; - GRPCURSORICONDIR* IconResDir; - INT id; - ICONIMAGE *ResIcon; - BOOL Icon = (uType == IMAGE_ICON); - DWORD filesize = 0; - - if (!(fuLoad & LR_LOADFROMFILE)) - { - if (hinst == NULL) - hinst = User32Instance; - - hResInfo = FindResourceW(hinst, lpszName, - Icon ? RT_GROUP_ICON : RT_GROUP_CURSOR); - if (hResInfo == NULL) - return NULL; - - hResource = LoadResource(hinst, hResInfo); - if (hResource == NULL) - return NULL; - - IconResDir = LockResource(hResource); - if (IconResDir == NULL) - { - return NULL; - } - - /* Find the best fitting in the IconResDir for this resolution */ - id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, Icon, width, height, - fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); - - hResInfo = FindResourceW(hinst, MAKEINTRESOURCEW(id), - Icon ? (LPCWSTR) RT_ICON : - (LPCWSTR) RT_CURSOR); - if (hResInfo == NULL) - { - return NULL; - } - - /* Now we have found the icon we want to load. - * Let's see if we already loaded it */ - if (fuLoad & LR_SHARED) - { - hIcon = NtUserFindExistingCursorIcon(hinst, hResInfo, 0, 0); - if (hIcon) - { - return hIcon; - } - else - TRACE("Didn't find the shared icon!!\n"); - } - - hResource = LoadResource(hinst, hResInfo); - if (hResource == NULL) - { - return NULL; - } - - ResIcon = LockResource(hResource); - if (ResIcon == NULL) - { - return NULL; - } - - hIcon = CreateIconFromResourceEx((PBYTE)ResIcon, - SizeofResource(hinst, hResInfo), - Icon, 0x00030000, width, height, - (fuLoad & (LR_DEFAULTSIZE | LR_SHARED)) | LR_DEFAULTCOLOR); - - if (hIcon && 0 != (fuLoad & LR_SHARED)) - { -#if 1 - NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, hResInfo, - (HRSRC)NULL); -#else - ICONINFO iconInfo; - - if(NtUserGetIconInfo(ResIcon, &iconInfo, NULL, NULL, NULL, FALSE)) - NtUserSetCursorIconData((HICON)hIcon, hinst, NULL, &iconInfo); -#endif - } - - return hIcon; - } - - if (fuLoad & LR_SHARED) - { - FIXME("Need LR_SHARED support for loading icon images from files\n"); - } - - hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return NULL; - - hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - filesize = GetFileSize( hFile, NULL ); - CloseHandle(hFile); - if (hSection == NULL) - return NULL; - - IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hSection); - if (IconDIR == NULL) - return NULL; - - if (0 != IconDIR->idReserved || - (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType)) - { - UnmapViewOfFile(IconDIR); - return NULL; - } - - /* Get a handle to the screen dc, the icon we create is going to be - * compatable with this. */ - hScreenDc = CreateDCW(NULL, NULL, NULL, NULL); - if (hScreenDc == NULL) - { - UnmapViewOfFile(IconDIR); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return NULL; - } - - if (fuLoad & LR_MONOCHROME) - { - ColorBits = 1; - } - else - { - ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL); - } - - /* Pick the best size. */ - dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits ); - if (!dirEntry) - { - DeleteDC(hScreenDc); - UnmapViewOfFile(IconDIR); - return NULL; - } - - if ( dirEntry->dwDIBOffset > filesize ) - { - DeleteDC(hScreenDc); - UnmapViewOfFile(IconDIR); - return NULL; - } - - if ( dirEntry->dwDIBOffset + dirEntry->dwDIBSize > filesize ){ - DeleteDC(hScreenDc); - UnmapViewOfFile(IconDIR); - return NULL; - } - - SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize); - if (SafeIconImage == NULL) - { - DeleteDC(hScreenDc); - UnmapViewOfFile(IconDIR); - return NULL; - } - - memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwDIBOffset, dirEntry->dwDIBSize); - UnmapViewOfFile(IconDIR); - - /* At this point we have a copy of the icon image to play with. */ - - SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; - - if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) - { - BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage; - ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; - HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE); - } - else - { - ColorCount = SafeIconImage->icHeader.biClrUsed; - if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8) - ColorCount = 1 << SafeIconImage->icHeader.biBitCount; - HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD); - } - - /* Make data point to the start of the XOR image data. */ - Data = (PBYTE)SafeIconImage + HeaderSize; - - hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2, Icon); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - DeleteDC(hScreenDc); - - return hIcon; -} - - -static HANDLE -LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad) -{ - HANDLE hResource; - HANDLE hFile; - HANDLE hSection; - LPBITMAPINFO BitmapInfo; - LPBITMAPINFO PrivateInfo; - HDC hScreenDc; - HANDLE hBitmap; - ULONG HeaderSize; - ULONG ColorCount; - PVOID Data; - BOOL Hit = FALSE; - - if (!(fuLoad & LR_LOADFROMFILE)) - { - if (hInstance == NULL) - hInstance = User32Instance; - - hResource = FindResourceW(hInstance, lpszName, RT_BITMAP); - if (hResource == NULL) - return NULL; - hResource = LoadResource(hInstance, hResource); - if (hResource == NULL) - return NULL; - BitmapInfo = LockResource(hResource); - if (BitmapInfo == NULL) - return NULL; - } - else - { - hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return NULL; - - hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - if (hSection == NULL) - return NULL; - - BitmapInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hSection); - if (BitmapInfo == NULL) - return NULL; - - BitmapInfo = (LPBITMAPINFO)((ULONG_PTR)BitmapInfo + sizeof(BITMAPFILEHEADER)); - } - - HeaderSize = BitmapInfo->bmiHeader.biSize; - if (HeaderSize == sizeof(BITMAPCOREHEADER)) - { - BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo; - ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; - HeaderSize += ColorCount * sizeof(RGBTRIPLE); - } - else - { - if (BitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) - { - HeaderSize += 3 * sizeof(RGBQUAD); - } - else - { - ColorCount = BitmapInfo->bmiHeader.biClrUsed; - if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8) - ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount; - HeaderSize += ColorCount * sizeof(RGBQUAD); - } - } - Data = (PVOID)((ULONG_PTR)BitmapInfo + HeaderSize); - - PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize); - if (PrivateInfo == NULL) - { - if (fuLoad & LR_LOADFROMFILE) - UnmapViewOfFile(BitmapInfo); - return NULL; - } - - _SEH2_TRY - { - memcpy(PrivateInfo, BitmapInfo, HeaderSize); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Hit = TRUE; - } - _SEH2_END; - - if (Hit) - { - ERR("We have a thread overrun, these are already freed! pi -> %d, bi -> %d\n", PrivateInfo, BitmapInfo); - RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo); - if (fuLoad & LR_LOADFROMFILE) - UnmapViewOfFile(BitmapInfo); - return NULL; - } - - /* FIXME: Handle color conversion and transparency. */ - - hScreenDc = CreateCompatibleDC(NULL); - if (hScreenDc == NULL) - { - RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo); - if (fuLoad & LR_LOADFROMFILE) - UnmapViewOfFile(BitmapInfo); - return NULL; - } - - if (fuLoad & LR_CREATEDIBSECTION) - { - DIBSECTION Dib; - - hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL, - 0, 0); - GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib); - SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo, - DIB_RGB_COLORS); - } - else - { - hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT, - Data, PrivateInfo, DIB_RGB_COLORS); - } - - RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo); - DeleteDC(hScreenDc); - if (fuLoad & LR_LOADFROMFILE) - UnmapViewOfFile(BitmapInfo); - - return hBitmap; -} - -HANDLE WINAPI -LoadImageW( - IN HINSTANCE hinst, - IN LPCWSTR lpszName, - IN UINT uType, - IN INT cxDesired, - IN INT cyDesired, - IN UINT fuLoad) -{ - if (fuLoad & LR_DEFAULTSIZE) - { - if (uType == IMAGE_ICON) - { - if (cxDesired == 0) - cxDesired = GetSystemMetrics(SM_CXICON); - if (cyDesired == 0) - cyDesired = GetSystemMetrics(SM_CYICON); - } - else if (uType == IMAGE_CURSOR) - { - if (cxDesired == 0) - cxDesired = GetSystemMetrics(SM_CXCURSOR); - if (cyDesired == 0) - cyDesired = GetSystemMetrics(SM_CYCURSOR); - } - } - - switch (uType) - { - case IMAGE_BITMAP: - return LoadBitmapImage(hinst, lpszName, fuLoad); - case IMAGE_CURSOR: - case IMAGE_ICON: - return LoadCursorIconImage(hinst, lpszName, cxDesired, cyDesired, - fuLoad, uType); - default: - break; - } - - return NULL; -} - - -/* - * @implemented - */ -HBITMAP WINAPI -LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName) -{ - return LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0); -} - - -/* - * @implemented - */ -HBITMAP WINAPI -LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName) -{ - return LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0); -} - - -static HANDLE -CopyBmp(HANDLE hnd, - UINT type, - INT desiredx, - INT desiredy, - UINT flags) -{ - HBITMAP res = NULL; - DIBSECTION ds; - int objSize; - BITMAPINFO * bi; - - objSize = GetObjectW( hnd, sizeof(ds), &ds ); - if (!objSize) return 0; - if ((desiredx < 0) || (desiredy < 0)) return 0; - - if (flags & LR_COPYFROMRESOURCE) - { - FIXME("FIXME: The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n"); - } - - if (desiredx == 0) desiredx = ds.dsBm.bmWidth; - if (desiredy == 0) desiredy = ds.dsBm.bmHeight; - - /* Allocate memory for a BITMAPINFOHEADER structure and a - color table. The maximum number of colors in a color table - is 256 which corresponds to a bitmap with depth 8. - Bitmaps with higher depths don't have color tables. */ - bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - if (!bi) return 0; - - bi->bmiHeader.biSize = sizeof(bi->bmiHeader); - bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes; - bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; - bi->bmiHeader.biCompression = BI_RGB; - - if (flags & LR_CREATEDIBSECTION) - { - /* Create a DIB section. LR_MONOCHROME is ignored */ - void * bits; - HDC dc = CreateCompatibleDC(NULL); - - if (objSize == sizeof(DIBSECTION)) - { - /* The source bitmap is a DIB. - Get its attributes to create an exact copy */ - memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); - } - - /* Get the color table or the color masks */ - GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); - - bi->bmiHeader.biWidth = desiredx; - bi->bmiHeader.biHeight = desiredy; - bi->bmiHeader.biSizeImage = 0; - - res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0); - DeleteDC(dc); - } - else - { - /* Create a device-dependent bitmap */ - - BOOL monochrome = (flags & LR_MONOCHROME); - - if (objSize == sizeof(DIBSECTION)) - { - /* The source bitmap is a DIB section. - Get its attributes */ - HDC dc = CreateCompatibleDC(NULL); - bi->bmiHeader.biSize = sizeof(bi->bmiHeader); - bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; - GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); - DeleteDC(dc); - - if (!monochrome && ds.dsBm.bmBitsPixel == 1) - { - /* Look if the colors of the DIB are black and white */ - - monochrome = - (bi->bmiColors[0].rgbRed == 0xff - && bi->bmiColors[0].rgbGreen == 0xff - && bi->bmiColors[0].rgbBlue == 0xff - && bi->bmiColors[0].rgbReserved == 0 - && bi->bmiColors[1].rgbRed == 0 - && bi->bmiColors[1].rgbGreen == 0 - && bi->bmiColors[1].rgbBlue == 0 - && bi->bmiColors[1].rgbReserved == 0) - || - (bi->bmiColors[0].rgbRed == 0 - && bi->bmiColors[0].rgbGreen == 0 - && bi->bmiColors[0].rgbBlue == 0 - && bi->bmiColors[0].rgbReserved == 0 - && bi->bmiColors[1].rgbRed == 0xff - && bi->bmiColors[1].rgbGreen == 0xff - && bi->bmiColors[1].rgbBlue == 0xff - && bi->bmiColors[1].rgbReserved == 0); - } - } - else if (!monochrome) - { - monochrome = ds.dsBm.bmBitsPixel == 1; - } - - if (monochrome) - { - res = CreateBitmap(desiredx, desiredy, 1, 1, NULL); - } - else - { - HDC screenDC = GetDC(NULL); - res = CreateCompatibleBitmap(screenDC, desiredx, desiredy); - ReleaseDC(NULL, screenDC); - } - } - - if (res) - { - /* Only copy the bitmap if it's a DIB section or if it's - compatible to the screen */ - BOOL copyContents; - - if (objSize == sizeof(DIBSECTION)) - { - copyContents = TRUE; - } - else - { - HDC screenDC = GetDC(NULL); - int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL); - ReleaseDC(NULL, screenDC); - - copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth); - } - - if (copyContents) - { - /* The source bitmap may already be selected in a device context, - use GetDIBits/StretchDIBits and not StretchBlt */ - - HDC dc; - void * bits; - - dc = CreateCompatibleDC(NULL); - - bi->bmiHeader.biWidth = ds.dsBm.bmWidth; - bi->bmiHeader.biHeight = ds.dsBm.bmHeight; - bi->bmiHeader.biSizeImage = 0; - bi->bmiHeader.biClrUsed = 0; - bi->bmiHeader.biClrImportant = 0; - - /* Fill in biSizeImage */ - GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); - bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage); - - if (bits) - { - HBITMAP oldBmp; - - /* Get the image bits of the source bitmap */ - GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS); - - /* Copy it to the destination bitmap */ - oldBmp = SelectObject(dc, res); - StretchDIBits(dc, 0, 0, desiredx, desiredy, - 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, - bits, bi, DIB_RGB_COLORS, SRCCOPY); - SelectObject(dc, oldBmp); - - HeapFree(GetProcessHeap(), 0, bits); - } - - DeleteDC(dc); - } - - if (flags & LR_COPYDELETEORG) - { - DeleteObject(hnd); - } - } - HeapFree(GetProcessHeap(), 0, bi); - return res; -} - - -INT -GetIconCurBpp(PICONINFO pIconInfo) -{ - PBITMAPINFO pbi; - - pbi = (PBITMAPINFO)pIconInfo->hbmColor; - return pbi->bmiHeader.biBitCount; -} - -#if 0 -static BOOL -SetCursorIconData( - HANDLE Handle, - HINSTANCE hMod, - LPWSTR lpResName, - PICONINFO pIconInfo) -{ - - UNICODE_STRING Res; - - if (!Handle || !pIconInfo) - return FALSE; - - RtlInitUnicodeString(&Res, lpResName); - - return NtUserSetCursorIconData(Handle, hMod, &Res, pIconInfo); - -} - - -/* bare bones icon copy implementation */ -static HANDLE -CopyIcoCur(HANDLE hIconCur, - UINT type, - INT desiredx, - INT desiredy, - UINT flags) -{ - HANDLE hNewIcon = NULL; - ICONINFO origIconInfo, newIconInfo; - SIZE origSize; - DWORD origBpp; - - if (!hIconCur) - return NULL; - - if (flags & LR_COPYFROMRESOURCE) - { - TRACE("FIXME: LR_COPYFROMRESOURCE is yet not implemented for icons\n"); - } - - if (NtUserGetIconSize(hIconCur, 0, &origSize.cx, &origSize.cy)) - { - if (desiredx == 0) desiredx = origSize.cx; - if (desiredx == 0) desiredy = origSize.cy; - - if (NtUserGetIconInfo(hIconCur, &origIconInfo, NULL, NULL, &origBpp, TRUE)) - { - hNewIcon = (HANDLE)NtUserCallOneParam(0, ONEPARAM_ROUTINE_CREATECURICONHANDLE); - - if (hNewIcon) - { - /* the bitmaps returned from the NtUserGetIconInfo are copies of the original, - * so we can use these directly to build up our icon/cursor copy */ - RtlCopyMemory(&newIconInfo, &origIconInfo, sizeof(ICONINFO)); - - if (!SetCursorIconData(hNewIcon, NULL, NULL, &newIconInfo)) - { - if (newIconInfo.fIcon) - DestroyIcon(hNewIcon); - else - DestroyCursor(hNewIcon); - - hNewIcon = NULL; - } - } - - DeleteObject(origIconInfo.hbmMask); - DeleteObject(origIconInfo.hbmColor); - } - } - - if (hNewIcon && (flags & LR_COPYDELETEORG)) - { - DestroyCursor((HCURSOR)hIconCur); - } - - return hNewIcon; -} -#endif - -/* - * @unimplemented - */ -HANDLE WINAPI -CopyImage( - IN HANDLE hnd, - IN UINT type, - IN INT desiredx, - IN INT desiredy, - IN UINT flags) -{ -/* - * BUGS - * Only Windows NT 4.0 supports the LR_COPYRETURNORG flag for bitmaps, - * all other versions (95/2000/XP have been tested) ignore it. - * - * NOTES - * If LR_CREATEDIBSECTION is absent, the copy will be monochrome for - * a monochrome source bitmap or if LR_MONOCHROME is present, otherwise - * the copy will have the same depth as the screen. - * The content of the image will only be copied if the bit depth of the - * original image is compatible with the bit depth of the screen, or - * if the source is a DIB section. - * The LR_MONOCHROME flag is ignored if LR_CREATEDIBSECTION is present. - */ - switch (type) - { - case IMAGE_BITMAP: - return CopyBmp(hnd, type, desiredx, desiredy, flags); - - case IMAGE_ICON: - //return CopyIcoCur(hnd, type, desiredx, desiredy, flags); - return CopyIcon(hnd); - - case IMAGE_CURSOR: - { - static BOOL IconMsgDisplayed = FALSE; - /* FIXME: support loading the image as shared from an instance */ - if (!IconMsgDisplayed) - { - FIXME("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n"); - IconMsgDisplayed = TRUE; - } - /* Should call CURSORICON_ExtCopy but more testing - * needs to be done before we change this - */ - if (flags) FIXME("FIXME: Flags are ignored\n"); - return CopyCursor(hnd); - } - } - - return NULL; -} diff --git a/reactos/dll/win32/user32/windows/cursor.c b/reactos/dll/win32/user32/windows/cursor.c deleted file mode 100644 index 1119ef1cd9a..00000000000 --- a/reactos/dll/win32/user32/windows/cursor.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* $Id$ - * - * PROJECT: ReactOS user32.dll - * FILE: lib/user32/windows/cursor.c - * PURPOSE: Cursor - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 09-05-2001 CSH Created - */ - -/* INCLUDES ******************************************************************/ - -#include - -#include - -WINE_DEFAULT_DEBUG_CHANNEL(user32); - -#undef CopyCursor - -HBITMAP -CopyBitmap(HBITMAP bmp); - -/* INTERNAL ******************************************************************/ - -/* This callback routine is called directly after switching to gui mode */ -NTSTATUS -WINAPI -User32SetupDefaultCursors(PVOID Arguments, - ULONG ArgumentLength) -{ - BOOL *DefaultCursor = (BOOL*)Arguments; - LRESULT Result = TRUE; - - if(*DefaultCursor) - { - /* set default cursor */ - SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); - } - else - { - /* FIXME load system cursor scheme */ - SetCursor(0); - SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); - } - - return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); -} - -/* FUNCTIONS *****************************************************************/ - - -/* - * @implemented - */ -HCURSOR -WINAPI -CopyCursor(HCURSOR pcur) -{ - ICONINFO IconInfo; - - if(GetIconInfo((HANDLE)pcur, &IconInfo)) - { - return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE); - } - return (HCURSOR)0; -} - -/* - * @implemented - */ -HCURSOR -WINAPI -CreateCursor(HINSTANCE hInst, - int xHotSpot, - int yHotSpot, - int nWidth, - int nHeight, - CONST VOID *pvANDPlane, - CONST VOID *pvXORPlane) -{ - ICONINFO IconInfo; - BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)]; - BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer; - HDC hScreenDc; - - hScreenDc = CreateCompatibleDC(NULL); - if (hScreenDc == NULL) - return NULL; - - bwBIH->bmiHeader.biBitCount = 1; - bwBIH->bmiHeader.biWidth = nWidth; - bwBIH->bmiHeader.biHeight = -nHeight * 2; - bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bwBIH->bmiHeader.biPlanes = 1; - bwBIH->bmiHeader.biSizeImage = 0; - bwBIH->bmiHeader.biCompression = BI_RGB; - bwBIH->bmiHeader.biClrImportant = 0; - bwBIH->bmiHeader.biClrUsed = 0; - bwBIH->bmiHeader.biXPelsPerMeter = 0; - bwBIH->bmiHeader.biYPelsPerMeter = 0; - - bwBIH->bmiColors[0].rgbBlue = 0; - bwBIH->bmiColors[0].rgbGreen = 0; - bwBIH->bmiColors[0].rgbRed = 0; - bwBIH->bmiColors[0].rgbReserved = 0; - - bwBIH->bmiColors[1].rgbBlue = 0xff; - bwBIH->bmiColors[1].rgbGreen = 0xff; - bwBIH->bmiColors[1].rgbRed = 0xff; - bwBIH->bmiColors[1].rgbReserved = 0; - - IconInfo.hbmMask = CreateDIBitmap(hScreenDc, &bwBIH->bmiHeader, 0, - NULL, bwBIH, DIB_RGB_COLORS); - if (IconInfo.hbmMask) - { - SetDIBits(hScreenDc, IconInfo.hbmMask, 0, nHeight, - pvXORPlane, bwBIH, DIB_RGB_COLORS); - SetDIBits(hScreenDc, IconInfo.hbmMask, nHeight, nHeight, - pvANDPlane, bwBIH, DIB_RGB_COLORS); - } - else - { - return NULL; - } - - DeleteDC(hScreenDc); - - IconInfo.fIcon = FALSE; - IconInfo.xHotspot = xHotSpot; - IconInfo.yHotspot = yHotSpot; - IconInfo.hbmColor = 0; - - return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE); -} - - -/* - * @implemented - */ -BOOL -WINAPI -DestroyCursor(HCURSOR hCursor) -{ - return (BOOL)NtUserDestroyCursor((HANDLE)hCursor, 0); -} - - -/* - * @implemented - */ -HCURSOR -WINAPI -GetCursor(VOID) -{ - CURSORINFO ci; - ci.cbSize = sizeof(CURSORINFO); - if(NtUserGetCursorInfo(&ci)) - return ci.hCursor; - else - return (HCURSOR)0; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetCursorPos(LPPOINT lpPoint) -{ - BOOL res; - /* Windows doesn't check if lpPoint == NULL, we do */ - if(!lpPoint) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - res = NtUserGetCursorPos(lpPoint); - - return res; -} - - -/* - * @implemented - */ -HCURSOR -WINAPI -LoadCursorA(HINSTANCE hInstance, - LPCSTR lpCursorName) -{ - return(LoadImageA(hInstance, - lpCursorName, - IMAGE_CURSOR, - 0, - 0, - LR_SHARED | LR_DEFAULTSIZE)); -} - - -/* - * @implemented - */ -HCURSOR -WINAPI -LoadCursorFromFileA(LPCSTR lpFileName) -{ - UNICODE_STRING FileName; - HCURSOR Result; - RtlCreateUnicodeStringFromAsciiz(&FileName, (LPSTR)lpFileName); - Result = LoadImageW(0, - FileName.Buffer, - IMAGE_CURSOR, - 0, - 0, - LR_LOADFROMFILE | LR_DEFAULTSIZE); - RtlFreeUnicodeString(&FileName); - return(Result); -} - - -/* - * @implemented - */ -HCURSOR -WINAPI -LoadCursorFromFileW(LPCWSTR lpFileName) -{ - return(LoadImageW(0, - lpFileName, - IMAGE_CURSOR, - 0, - 0, - LR_LOADFROMFILE | LR_DEFAULTSIZE)); -} - - -/* - * @implemented - */ -HCURSOR -WINAPI -LoadCursorW(HINSTANCE hInstance, - LPCWSTR lpCursorName) -{ - return(LoadImageW(hInstance, - lpCursorName, - IMAGE_CURSOR, - 0, - 0, - LR_SHARED | LR_DEFAULTSIZE)); -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetCursorPos(int X, - int Y) -{ - return NtUserSetCursorPos(X,Y); -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetSystemCursor(HCURSOR hcur, - DWORD id) -{ - UNIMPLEMENTED; - return FALSE; -} - - -/* - * @implemented - */ -int -WINAPI -ShowCursor(BOOL bShow) -{ - return NtUserShowCursor(bShow); -} - -HCURSOR -CursorIconToCursor(HICON hIcon, - BOOL SemiTransparent) -{ - UNIMPLEMENTED; - return 0; -} diff --git a/reactos/dll/win32/user32/windows/cursoricon.c b/reactos/dll/win32/user32/windows/cursoricon.c new file mode 100644 index 00000000000..3729adbf852 --- /dev/null +++ b/reactos/dll/win32/user32/windows/cursoricon.c @@ -0,0 +1,2074 @@ +/* + * Cursor and icon support + * + * Copyright 1995 Alexandre Julliard + * 1996 Martin Von Loewis + * 1997 Alex Korobka + * 1998 Turchanov Sergey + * 2007 Henri Verbeet + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(cursor); +WINE_DECLARE_DEBUG_CHANNEL(icon); +WINE_DECLARE_DEBUG_CHANNEL(resource); + +#include "pshpack1.h" + +typedef struct { + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD xHotspot; + WORD yHotspot; + DWORD dwDIBSize; + DWORD dwDIBOffset; +} CURSORICONFILEDIRENTRY; + +typedef struct +{ + WORD idReserved; + WORD idType; + WORD idCount; + CURSORICONFILEDIRENTRY idEntries[1]; +} CURSORICONFILEDIR; + +#include "poppack.h" + +static HDC screen_dc; + +static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0}; + + +static CRITICAL_SECTION IconCrst; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &IconCrst, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": IconCrst") } +}; +static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 }; + + +/*********************************************************************** + * map_fileW + * + * Helper function to map a file to memory: + * name - file name + * [RETURN] ptr - pointer to mapped file + * [RETURN] filesize - pointer size of file to be stored if not NULL + */ +static void *map_fileW( LPCWSTR name, LPDWORD filesize ) +{ + HANDLE hFile, hMapping; + LPVOID ptr = NULL; + + hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 ); + if (hFile != INVALID_HANDLE_VALUE) + { + hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); + if (hMapping) + { + ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); + CloseHandle( hMapping ); + if (filesize) + *filesize = GetFileSize( hFile, NULL ); + } + CloseHandle( hFile ); + } + return ptr; +} + + +/*********************************************************************** + * get_dib_width_bytes + * + * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. + */ +static int get_dib_width_bytes( int width, int depth ) +{ + int words; + + switch(depth) + { + case 1: words = (width + 31) / 32; break; + case 4: words = (width + 7) / 8; break; + case 8: words = (width + 3) / 4; break; + case 15: + case 16: words = (width + 1) / 2; break; + case 24: words = (width * 3 + 3)/4; break; + default: + WARN("(%d): Unsupported depth\n", depth ); + /* fall through */ + case 32: + words = width; + } + return 4 * words; +} + + +/*********************************************************************** + * bitmap_info_size + * + * Return the size of the bitmap info structure including color table. + */ +static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) +{ + unsigned int colors, size, masks = 0; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info; + colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0; + return sizeof(BITMAPCOREHEADER) + colors * + ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD)); + } + else /* assume BITMAPINFOHEADER */ + { + colors = info->bmiHeader.biClrUsed; + if (colors > 256) /* buffer overflow otherwise */ + colors = 256; + if (!colors && (info->bmiHeader.biBitCount <= 8)) + colors = 1 << info->bmiHeader.biBitCount; + if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; + size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); + return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); + } +} + + +/*********************************************************************** + * is_dib_monochrome + * + * Returns whether a DIB can be converted to a monochrome DDB. + * + * A DIB can be converted if its color table contains only black and + * white. Black must be the first color in the color table. + * + * Note : If the first color in the color table is white followed by + * black, we can't convert it to a monochrome DDB with + * SetDIBits, because black and white would be inverted. + */ +static BOOL is_dib_monochrome( const BITMAPINFO* info ) +{ + if (info->bmiHeader.biBitCount != 1) return FALSE; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + const RGBTRIPLE *rgb = ((const BITMAPCOREINFO*)info)->bmciColors; + + /* Check if the first color is black */ + if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0)) + { + rgb++; + + /* Check if the second color is white */ + return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff) + && (rgb->rgbtBlue == 0xff)); + } + else return FALSE; + } + else /* assume BITMAPINFOHEADER */ + { + const RGBQUAD *rgb = info->bmiColors; + + /* Check if the first color is black */ + if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && + (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0)) + { + rgb++; + + /* Check if the second color is white */ + return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff) + && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0)); + } + else return FALSE; + } +} + +/*********************************************************************** + * DIB_GetBitmapInfo + * + * Get the info from a bitmap header. + * Return 1 for INFOHEADER, 0 for COREHEADER, + */ +static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, + LONG *height, WORD *bpp, DWORD *compr ) +{ + if (header->biSize == sizeof(BITMAPCOREHEADER)) + { + const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header; + *width = core->bcWidth; + *height = core->bcHeight; + *bpp = core->bcBitCount; + *compr = 0; + return 0; + } + else if (header->biSize >= sizeof(BITMAPINFOHEADER)) + { + *width = header->biWidth; + *height = header->biHeight; + *bpp = header->biBitCount; + *compr = header->biCompression; + return 1; + } + ERR("(%d): unknown/wrong size for header\n", header->biSize ); + return -1; +} + + +/* + * The following macro functions account for the irregularities of + * accessing cursor and icon resources in files and resource entries. + */ +typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n, + int *width, int *height, int *bits ); + +/********************************************************************** + * CURSORICON_FindBestIcon + * + * Find the icon closest to the requested size and bit depth. + */ +static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, + int width, int height, int depth ) +{ + int i, cx, cy, bits, bestEntry = -1; + UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff; + UINT iTempXDiff, iTempYDiff, iTempColorDiff; + + /* Find Best Fit */ + iTotalDiff = 0xFFFFFFFF; + iColorDiff = 0xFFFFFFFF; + for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + { + iTempXDiff = abs(width - cx); + iTempYDiff = abs(height - cy); + + if(iTotalDiff > (iTempXDiff + iTempYDiff)) + { + iXDiff = iTempXDiff; + iYDiff = iTempYDiff; + iTotalDiff = iXDiff + iYDiff; + } + } + + /* Find Best Colors for Best Fit */ + for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + { + if(abs(width - cx) == iXDiff && abs(height - cy) == iYDiff) + { + iTempColorDiff = abs(depth - bits); + if(iColorDiff > iTempColorDiff) + { + bestEntry = i; + iColorDiff = iTempColorDiff; + } + } + } + + return bestEntry; +} + +static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n, + int *width, int *height, int *bits ) +{ + CURSORICONDIR *resdir = dir; + ICONRESDIR *icon; + + if ( resdir->idCount <= n ) + return FALSE; + icon = &resdir->idEntries[n].ResInfo.icon; + *width = icon->bWidth; + *height = icon->bHeight; + *bits = resdir->idEntries[n].wBitCount; + return TRUE; +} + +/********************************************************************** + * CURSORICON_FindBestCursor + * + * Find the cursor closest to the requested size. + * + * FIXME: parameter 'color' ignored. + */ +static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, + int width, int height, int depth ) +{ + int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1; + + /* Double height to account for AND and XOR masks */ + + height *= 2; + + /* First find the largest one smaller than or equal to the requested size*/ + + maxwidth = maxheight = 0; + for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + { + if ((cx <= width) && (cy <= height) && + (cx > maxwidth) && (cy > maxheight)) + { + bestEntry = i; + maxwidth = cx; + maxheight = cy; + } + } + if (bestEntry != -1) return bestEntry; + + /* Now find the smallest one larger than the requested size */ + + maxwidth = maxheight = 255; + for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) + { + if (((cx < maxwidth) && (cy < maxheight)) || (bestEntry == -1)) + { + bestEntry = i; + maxwidth = cx; + maxheight = cy; + } + } + + return bestEntry; +} + +static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n, + int *width, int *height, int *bits ) +{ + CURSORICONDIR *resdir = dir; + CURSORDIR *cursor; + + if ( resdir->idCount <= n ) + return FALSE; + cursor = &resdir->idEntries[n].ResInfo.cursor; + *width = cursor->wWidth; + *height = cursor->wHeight; + *bits = resdir->idEntries[n].wBitCount; + return TRUE; +} + +static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir, + int width, int height, int depth ) +{ + int n; + + n = CURSORICON_FindBestIcon( dir, CURSORICON_GetResIconEntry, + width, height, depth ); + if ( n < 0 ) + return NULL; + return &dir->idEntries[n]; +} + +static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir, + int width, int height, int depth ) +{ + int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetResCursorEntry, + width, height, depth ); + if ( n < 0 ) + return NULL; + return &dir->idEntries[n]; +} + +static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n, + int *width, int *height, int *bits ) +{ + CURSORICONFILEDIR *filedir = dir; + CURSORICONFILEDIRENTRY *entry; + BITMAPINFOHEADER *info; + + if ( filedir->idCount <= n ) + return FALSE; + entry = &filedir->idEntries[n]; + /* FIXME: check against file size */ + info = (BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset); + *width = entry->bWidth; + *height = entry->bHeight; + *bits = info->biBitCount; + return TRUE; +} + +static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, + int width, int height, int depth ) +{ + int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetFileEntry, + width, height, depth ); + if ( n < 0 ) + return NULL; + return &dir->idEntries[n]; +} + +static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *dir, + int width, int height, int depth ) +{ + int n = CURSORICON_FindBestIcon( dir, CURSORICON_GetFileEntry, + width, height, depth ); + if ( n < 0 ) + return NULL; + return &dir->idEntries[n]; +} + +/*********************************************************************** + * create_icon_bitmaps + * + * Create the color, mask and alpha bitmaps from the DIB info. + */ +static BOOL create_icon_bitmaps( const BITMAPINFO *bmi, int width, int height, + HBITMAP *color, HBITMAP *mask ) +{ + BOOL monochrome = is_dib_monochrome( bmi ); + unsigned int size = bitmap_info_size( bmi, DIB_RGB_COLORS ); + BITMAPINFO *info; + void *color_bits, *mask_bits; + BOOL ret = FALSE; + HDC hdc = 0; + + if (!(info = HeapAlloc( GetProcessHeap(), 0, max( size, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))) + return FALSE; + if (!(hdc = CreateCompatibleDC( 0 ))) goto done; + + memcpy( info, bmi, size ); + info->bmiHeader.biHeight /= 2; + + color_bits = (char *)bmi + size; + mask_bits = (char *)color_bits + + get_dib_width_bytes( bmi->bmiHeader.biWidth, + bmi->bmiHeader.biBitCount ) * abs(info->bmiHeader.biHeight); + + if (monochrome) + { + if (!(*mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; + *color = 0; + + /* copy color data into second half of mask bitmap */ + SelectObject( hdc, *mask ); + StretchDIBits( hdc, 0, height, width, height, + 0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight, + color_bits, info, DIB_RGB_COLORS, SRCCOPY ); + } + else + { + if (!(*mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done; + if (!(*color = CreateBitmap( width, height, GetDeviceCaps( screen_dc, PLANES ), + GetDeviceCaps( screen_dc, BITSPIXEL ), NULL ))) + { + DeleteObject( *mask ); + goto done; + } + SelectObject( hdc, *color ); + StretchDIBits( hdc, 0, 0, width, height, + 0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight, + color_bits, info, DIB_RGB_COLORS, SRCCOPY ); + + /* convert info to monochrome to copy the mask */ + info->bmiHeader.biBitCount = 1; + if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) + { + RGBQUAD *rgb = info->bmiColors; + + info->bmiHeader.biClrUsed = info->bmiHeader.biClrImportant = 2; + rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; + rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; + rgb[0].rgbReserved = rgb[1].rgbReserved = 0; + } + else + { + RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)info) + 1); + + rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; + rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; + } + } + + SelectObject( hdc, *mask ); + StretchDIBits( hdc, 0, 0, width, height, + 0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight, + mask_bits, info, DIB_RGB_COLORS, SRCCOPY ); + ret = TRUE; + +done: + DeleteDC( hdc ); + HeapFree( GetProcessHeap(), 0, info ); + return ret; +} + +static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, + POINT hotspot, BOOL bIcon, + DWORD dwVersion, + INT width, INT height, + UINT cFlag ) +{ + HBITMAP color = 0, mask = 0; + BOOL do_stretch; + ICONINFO IconInfo; + + if (dwVersion == 0x00020000) + { + FIXME_(cursor)("\t2.xx resources are not supported\n"); + return 0; + } + + /* Check bitmap header */ + + if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && + (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || + bmi->bmiHeader.biCompression != BI_RGB) ) + { + WARN_(cursor)("\tinvalid resource bitmap header.\n"); + return 0; + } + + if (!width) width = bmi->bmiHeader.biWidth; + if (!height) height = bmi->bmiHeader.biHeight/2; + do_stretch = (bmi->bmiHeader.biHeight/2 != height) || + (bmi->bmiHeader.biWidth != width); + + /* Scale the hotspot */ + if (bIcon) + { + hotspot.x = width / 2; + hotspot.y = height / 2; + } + else if (do_stretch) + { + hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth; + hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biHeight / 2); + } + + if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); + if (!screen_dc) return 0; + + if (!create_icon_bitmaps( bmi, width, height, &color, &mask )) return 0; + + IconInfo.xHotspot = hotspot.x; + IconInfo.yHotspot = hotspot.y; + IconInfo.fIcon = bIcon; + IconInfo.hbmColor = color; + IconInfo.hbmMask = mask; + + return NtUserCreateCursorIconHandle(&IconInfo, FALSE); +} + + +/********************************************************************** + * .ANI cursor support + */ +#define RIFF_FOURCC( c0, c1, c2, c3 ) \ + ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \ + ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) ) + +#define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F') +#define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T') +#define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N') +#define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h') +#define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ') +#define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm') + +#define ANI_FLAG_ICON 0x1 +#define ANI_FLAG_SEQUENCE 0x2 + +typedef struct { + DWORD header_size; + DWORD num_frames; + DWORD num_steps; + DWORD width; + DWORD height; + DWORD bpp; + DWORD num_planes; + DWORD display_rate; + DWORD flags; +} ani_header; + +typedef struct { + DWORD data_size; + const unsigned char *data; +} riff_chunk_t; + +static void dump_ani_header( const ani_header *header ) +{ + TRACE(" header size: %d\n", header->header_size); + TRACE(" frames: %d\n", header->num_frames); + TRACE(" steps: %d\n", header->num_steps); + TRACE(" width: %d\n", header->width); + TRACE(" height: %d\n", header->height); + TRACE(" bpp: %d\n", header->bpp); + TRACE(" planes: %d\n", header->num_planes); + TRACE(" display rate: %d\n", header->display_rate); + TRACE(" flags: 0x%08x\n", header->flags); +} + + +/* + * RIFF: + * DWORD "RIFF" + * DWORD size + * DWORD riff_id + * BYTE[] data + * + * LIST: + * DWORD "LIST" + * DWORD size + * DWORD list_id + * BYTE[] data + * + * CHUNK: + * DWORD chunk_id + * DWORD size + * BYTE[] data + */ +static void riff_find_chunk( DWORD chunk_id, DWORD chunk_type, const riff_chunk_t *parent_chunk, riff_chunk_t *chunk ) +{ + const unsigned char *ptr = parent_chunk->data; + const unsigned char *end = parent_chunk->data + (parent_chunk->data_size - (2 * sizeof(DWORD))); + + if (chunk_type == ANI_LIST_ID || chunk_type == ANI_RIFF_ID) end -= sizeof(DWORD); + + while (ptr < end) + { + if ((!chunk_type && *(const DWORD *)ptr == chunk_id ) + || (chunk_type && *(const DWORD *)ptr == chunk_type && *((const DWORD *)ptr + 2) == chunk_id )) + { + ptr += sizeof(DWORD); + chunk->data_size = (*(const DWORD *)ptr + 1) & ~1; + ptr += sizeof(DWORD); + if (chunk_type == ANI_LIST_ID || chunk_type == ANI_RIFF_ID) ptr += sizeof(DWORD); + chunk->data = ptr; + + return; + } + + ptr += sizeof(DWORD); + ptr += (*(const DWORD *)ptr + 1) & ~1; + ptr += sizeof(DWORD); + } +} + + +/* + * .ANI layout: + * + * RIFF:'ACON' RIFF chunk + * |- CHUNK:'anih' Header + * |- CHUNK:'seq ' Sequence information (optional) + * \- LIST:'fram' Frame list + * |- CHUNK:icon Cursor frames + * |- CHUNK:icon + * |- ... + * \- CHUNK:icon + */ +static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size, + INT width, INT height, INT depth ) +{ + HCURSOR cursor; + ani_header header = {0}; + LPBYTE frame_bits = 0; + POINT hotspot; + CURSORICONFILEDIRENTRY *entry; + + riff_chunk_t root_chunk = { bits_size, bits }; + riff_chunk_t ACON_chunk = {0}; + riff_chunk_t anih_chunk = {0}; + riff_chunk_t fram_chunk = {0}; + const unsigned char *icon_data; + + TRACE("bits %p, bits_size %d\n", bits, bits_size); + + if (!bits) return 0; + + riff_find_chunk( ANI_ACON_ID, ANI_RIFF_ID, &root_chunk, &ACON_chunk ); + if (!ACON_chunk.data) + { + ERR("Failed to get root chunk.\n"); + return 0; + } + + riff_find_chunk( ANI_anih_ID, 0, &ACON_chunk, &anih_chunk ); + if (!anih_chunk.data) + { + ERR("Failed to get 'anih' chunk.\n"); + return 0; + } + memcpy( &header, anih_chunk.data, sizeof(header) ); + dump_ani_header( &header ); + + riff_find_chunk( ANI_fram_ID, ANI_LIST_ID, &ACON_chunk, &fram_chunk ); + if (!fram_chunk.data) + { + ERR("Failed to get icon list.\n"); + return 0; + } + + /* FIXME: For now, just load the first frame. Before we can load all the + * frames, we need to write the needed code in wineserver, etc. to handle + * cursors. Once this code is written, we can extend it to support .ani + * cursors and then update user32 and winex11.drv to load all frames. + * + * Hopefully this will at least make some games (C&C3, etc.) more playable + * in the meantime. + */ + FIXME("Loading all frames for .ani cursors not implemented.\n"); + icon_data = fram_chunk.data + (2 * sizeof(DWORD)); + + entry = CURSORICON_FindBestIconFile( (CURSORICONFILEDIR *) icon_data, + width, height, depth ); + + frame_bits = HeapAlloc( GetProcessHeap(), 0, entry->dwDIBSize ); + memcpy( frame_bits, icon_data + entry->dwDIBOffset, entry->dwDIBSize ); + + if (!header.width || !header.height) + { + header.width = entry->bWidth; + header.height = entry->bHeight; + } + + hotspot.x = entry->xHotspot; + hotspot.y = entry->yHotspot; + + cursor = CURSORICON_CreateIconFromBMI( (BITMAPINFO *) frame_bits, hotspot, + FALSE, 0x00030000, header.width, header.height, 0 ); + + HeapFree( GetProcessHeap(), 0, frame_bits ); + + return cursor; +} + + +/********************************************************************** + * CreateIconFromResourceEx (USER32.@) + * + * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something + * with cbSize parameter as well. + */ +HICON WINAPI CreateIconFromResourceEx( PBYTE bits, DWORD cbSize, + BOOL bIcon, DWORD dwVersion, + int width, int height, + UINT cFlag ) +{ + POINT hotspot; + BITMAPINFO *bmi; + + TRACE_(cursor)("%p (%u bytes), ver %08x, %ix%i %s %s\n", + bits, cbSize, dwVersion, width, height, + bIcon ? "icon" : "cursor", (cFlag & LR_MONOCHROME) ? "mono" : "" ); + + if (bIcon) + { + hotspot.x = width / 2; + hotspot.y = height / 2; + bmi = (BITMAPINFO *)bits; + } + else /* get the hotspot */ + { + SHORT *pt = (SHORT *)bits; + hotspot.x = pt[0]; + hotspot.y = pt[1]; + bmi = (BITMAPINFO *)(pt + 2); + } + + return CURSORICON_CreateIconFromBMI( bmi, hotspot, bIcon, dwVersion, + width, height, cFlag ); +} + + +/********************************************************************** + * CreateIconFromResource (USER32.@) + */ +HICON WINAPI CreateIconFromResource( PBYTE bits, DWORD cbSize, + BOOL bIcon, DWORD dwVersion) +{ + return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0); +} + + +static HICON CURSORICON_LoadFromFile( LPCWSTR filename, + INT width, INT height, INT depth, + BOOL fCursor, UINT loadflags) +{ + CURSORICONFILEDIRENTRY *entry; + CURSORICONFILEDIR *dir; + DWORD filesize = 0; + HICON hIcon = 0; + LPBYTE bits; + POINT hotspot; + + TRACE("loading %s\n", debugstr_w( filename )); + + bits = map_fileW( filename, &filesize ); + if (!bits) + return hIcon; + + /* Check for .ani. */ + if (memcmp( bits, "RIFF", 4 ) == 0) + { + hIcon = CURSORICON_CreateIconFromANI( bits, filesize, width, height, + depth ); + goto end; + } + + dir = (CURSORICONFILEDIR*) bits; + if ( filesize < sizeof(*dir) ) + goto end; + + if ( filesize < (sizeof(*dir) + sizeof(dir->idEntries[0])*(dir->idCount-1)) ) + goto end; + + if ( fCursor ) + entry = CURSORICON_FindBestCursorFile( dir, width, height, depth ); + else + entry = CURSORICON_FindBestIconFile( dir, width, height, depth ); + + if ( !entry ) + goto end; + + /* check that we don't run off the end of the file */ + if ( entry->dwDIBOffset > filesize ) + goto end; + if ( entry->dwDIBOffset + entry->dwDIBSize > filesize ) + goto end; + + hotspot.x = entry->xHotspot; + hotspot.y = entry->yHotspot; + hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)&bits[entry->dwDIBOffset], + hotspot, !fCursor, 0x00030000, + width, height, loadflags ); +end: + TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon ); + UnmapViewOfFile( bits ); + return hIcon; +} + +/********************************************************************** + * CURSORICON_Load + * + * Load a cursor or icon from resource or file. + */ +static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, + INT width, INT height, INT depth, + BOOL fCursor, UINT loadflags) +{ + HANDLE handle = 0; + HICON hIcon = 0; + HRSRC hRsrc, hGroupRsrc; + CURSORICONDIR *dir; + CURSORICONDIRENTRY *dirEntry; + LPBYTE bits; + WORD wResId; + DWORD dwBytesInRes; + + TRACE("%p, %s, %dx%d, depth %d, fCursor %d, flags 0x%04x\n", + hInstance, debugstr_w(name), width, height, depth, fCursor, loadflags); + + if ( loadflags & LR_LOADFROMFILE ) /* Load from file */ + return CURSORICON_LoadFromFile( name, width, height, depth, fCursor, loadflags ); + + if (!hInstance) hInstance = User32Instance; /* Load OEM cursor/icon */ + + /* don't cache 16-bit instances (FIXME: should never get 16-bit instances in the first place) */ + if ((ULONG_PTR)hInstance >> 16 == 0) loadflags &= ~LR_SHARED; + + /* Get directory resource ID */ + + if (!(hRsrc = FindResourceW( hInstance, name, + (LPWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) ))) + return 0; + hGroupRsrc = hRsrc; + + /* Find the best entry in the directory */ + + if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; + if (!(dir = LockResource( handle ))) return 0; + if (fCursor) + dirEntry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); + else + dirEntry = CURSORICON_FindBestIconRes( dir, width, height, depth ); + if (!dirEntry) return 0; + wResId = dirEntry->wResId; + dwBytesInRes = dirEntry->dwBytesInRes; + FreeResource( handle ); + + /* Load the resource */ + + if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId), + (LPWSTR)(fCursor ? RT_CURSOR : RT_ICON) ))) return 0; + + /* If shared icon, check whether it was already loaded */ + if ( (loadflags & LR_SHARED) + && (hIcon = NtUserFindExistingCursorIcon( hInstance, hRsrc, 0, 0 ) ) != 0 ) + return hIcon; + + if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; + bits = LockResource( handle ); + hIcon = CreateIconFromResourceEx( bits, dwBytesInRes, + !fCursor, 0x00030000, width, height, loadflags); + FreeResource( handle ); + + /* If shared icon, add to icon cache */ + + if (hIcon && 0 != (loadflags & LR_SHARED)) + { +#if 1 + NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hInstance, hRsrc, + (HRSRC)NULL); +#else + ICONINFO iconInfo; + + if(NtUserGetIconInfo(ResIcon, &iconInfo, NULL, NULL, NULL, FALSE)) + NtUserSetCursorIconData((HICON)hIcon, hinst, NULL, &iconInfo); +#endif + } + + return hIcon; +} + + +/************************************************************************* + * CURSORICON_ExtCopy + * + * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified + * + * PARAMS + * Handle [I] handle to an Image + * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON) + * iDesiredCX [I] The Desired width of the Image + * iDesiredCY [I] The desired height of the Image + * nFlags [I] The flags from CopyImage + * + * RETURNS + * Success: The new handle of the Image + * + * NOTES + * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented. + * LR_MONOCHROME should be implemented by CreateIconFromResourceEx. + * LR_COPYFROMRESOURCE will only work if the Image is in the Cache. + * + * + */ + +static HICON CURSORICON_ExtCopy(HICON hIcon, UINT nType, + INT iDesiredCX, INT iDesiredCY, + UINT nFlags) +{ + HICON hNew=0; + + TRACE_(icon)("hIcon %p, nType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n", + hIcon, nType, iDesiredCX, iDesiredCY, nFlags); + + if(hIcon == 0) + { + return 0; + } + + /* Best Fit or Monochrome */ + if( (nFlags & LR_COPYFROMRESOURCE + && (iDesiredCX > 0 || iDesiredCY > 0)) + || nFlags & LR_MONOCHROME) + { + FIXME("Copying from resource isn't implemented yet\n"); + hNew = CopyIcon(hIcon); + +#if 0 + ICONCACHE* pIconCache = CURSORICON_FindCache(hIcon); + + /* Not Found in Cache, then do a straight copy + */ + if(pIconCache == NULL) + { + hNew = CopyIcon( hIcon ); + if(nFlags & LR_COPYFROMRESOURCE) + { + TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n"); + } + } + else + { + int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX; + LPBYTE pBits; + HANDLE hMem; + HRSRC hRsrc; + DWORD dwBytesInRes; + WORD wResId; + CURSORICONDIR *pDir; + CURSORICONDIRENTRY *pDirEntry; + BOOL bIsIcon = (nType == IMAGE_ICON); + + /* Completing iDesiredCX CY for Monochrome Bitmaps if needed + */ + if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE)) + || (iDesiredCX == 0 && iDesiredCY == 0)) + { + iDesiredCY = GetSystemMetrics(bIsIcon ? + SM_CYICON : SM_CYCURSOR); + iDesiredCX = GetSystemMetrics(bIsIcon ? + SM_CXICON : SM_CXCURSOR); + } + + /* Retrieve the CURSORICONDIRENTRY + */ + if (!(hMem = LoadResource( pIconCache->hModule , + pIconCache->hGroupRsrc))) + { + return 0; + } + if (!(pDir = LockResource( hMem ))) + { + return 0; + } + + /* Find Best Fit + */ + if(bIsIcon) + { + pDirEntry = CURSORICON_FindBestIconRes( + pDir, iDesiredCX, iDesiredCY, 256 ); + } + else + { + pDirEntry = CURSORICON_FindBestCursorRes( + pDir, iDesiredCX, iDesiredCY, 1); + } + + wResId = pDirEntry->wResId; + dwBytesInRes = pDirEntry->dwBytesInRes; + FreeResource(hMem); + + TRACE_(icon)("ResID %u, BytesInRes %u, Width %d, Height %d DX %d, DY %d\n", + wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth, + pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY); + + /* Get the Best Fit + */ + if (!(hRsrc = FindResourceW(pIconCache->hModule , + MAKEINTRESOURCEW(wResId), (LPWSTR)(bIsIcon ? RT_ICON : RT_CURSOR)))) + { + return 0; + } + if (!(hMem = LoadResource( pIconCache->hModule , hRsrc ))) + { + return 0; + } + + pBits = LockResource( hMem ); + + if(nFlags & LR_DEFAULTSIZE) + { + iTargetCY = GetSystemMetrics(SM_CYICON); + iTargetCX = GetSystemMetrics(SM_CXICON); + } + + /* Create a New Icon with the proper dimension + */ + hNew = CreateIconFromResourceEx( pBits, dwBytesInRes, + bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags); + FreeResource(hMem); + } +#endif + } + else hNew = CopyIcon( hIcon ); + return hNew; +} + + +/*********************************************************************** + * CreateCursor (USER32.@) + */ +HCURSOR WINAPI CreateCursor( HINSTANCE hInstance, + INT xHotSpot, INT yHotSpot, + INT nWidth, INT nHeight, + LPCVOID lpANDbits, LPCVOID lpXORbits ) +{ + ICONINFO info; + HCURSOR hCursor; + + TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n", + nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits); + + info.fIcon = FALSE; + info.xHotspot = xHotSpot; + info.yHotspot = yHotSpot; + info.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpANDbits ); + info.hbmColor = CreateBitmap( nWidth, nHeight, 1, 1, lpXORbits ); + hCursor = CreateIconIndirect( &info ); + DeleteObject( info.hbmMask ); + DeleteObject( info.hbmColor ); + return hCursor; +} + + +/*********************************************************************** + * CreateIcon (USER32.@) + * + * Creates an icon based on the specified bitmaps. The bitmaps must be + * provided in a device dependent format and will be resized to + * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color + * depth. The provided bitmaps must be top-down bitmaps. + * Although Windows does not support 15bpp(*) this API must support it + * for Winelib applications. + * + * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp + * format! + * + * RETURNS + * Success: handle to an icon + * Failure: NULL + * + * FIXME: Do we need to resize the bitmaps? + */ +HICON WINAPI CreateIcon( + HINSTANCE hInstance, /* [in] the application's hInstance */ + int nWidth, /* [in] the width of the provided bitmaps */ + int nHeight, /* [in] the height of the provided bitmaps */ + BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */ + BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */ + const BYTE* lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */ + const BYTE* lpXORbits) /* [in] the icon's 'color' bitmap */ +{ + ICONINFO iinfo; + HICON hIcon; + + TRACE_(icon)("%dx%d, planes %d, bpp %d, xor %p, and %p\n", + nWidth, nHeight, bPlanes, bBitsPixel, lpXORbits, lpANDbits); + + iinfo.fIcon = TRUE; + iinfo.xHotspot = nWidth / 2; + iinfo.yHotspot = nHeight / 2; + iinfo.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpANDbits ); + iinfo.hbmColor = CreateBitmap( nWidth, nHeight, bPlanes, bBitsPixel, lpXORbits ); + + hIcon = CreateIconIndirect( &iinfo ); + + DeleteObject( iinfo.hbmMask ); + DeleteObject( iinfo.hbmColor ); + + return hIcon; +} + + +/*********************************************************************** + * CopyIcon (USER32.@) + */ +HICON WINAPI CopyIcon( HICON hIcon ) +{ + HICON hRetIcon = NULL; + ICONINFO IconInfo; + + if(GetIconInfo(hIcon, &IconInfo)) + { + hRetIcon = CreateIconIndirect(&IconInfo); + DeleteObject(IconInfo.hbmColor); + DeleteObject(IconInfo.hbmMask); + } + + return hRetIcon; +} + + +/*********************************************************************** + * DestroyIcon (USER32.@) + */ +BOOL WINAPI DestroyIcon( HICON hIcon ) +{ + TRACE_(icon)("%p\n", hIcon ); + + return NtUserDestroyCursor(hIcon, 0); +} + + +/*********************************************************************** + * DestroyCursor (USER32.@) + */ +BOOL WINAPI DestroyCursor( HCURSOR hCursor ) +{ + if (GetCursor() == hCursor) + { + WARN_(cursor)("Destroying active cursor!\n" ); + return FALSE; + } + return DestroyIcon( hCursor ); +} + +/*********************************************************************** + * DrawIcon (USER32.@) + */ +BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon ) +{ + return DrawIconEx( hdc, x, y, hIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE ); +} + +/*********************************************************************** + * SetCursor (USER32.@) + * + * Set the cursor shape. + * + * RETURNS + * A handle to the previous cursor shape. + */ +HCURSOR WINAPI /*DECLSPEC_HOTPATCH*/ SetCursor( HCURSOR hCursor /* [in] Handle of cursor to show */ ) +{ + return NtUserSetCursor(hCursor); +} + +/*********************************************************************** + * ShowCursor (USER32.@) + */ +INT WINAPI /*DECLSPEC_HOTPATCH*/ ShowCursor( BOOL bShow ) +{ + return NtUserShowCursor(bShow); +} + +/*********************************************************************** + * GetCursor (USER32.@) + */ +HCURSOR WINAPI GetCursor(void) +{ + CURSORINFO ci; + ci.cbSize = sizeof(CURSORINFO); + if(NtUserGetCursorInfo(&ci)) + return ci.hCursor; + else + return (HCURSOR)0; +} + + +/*********************************************************************** + * ClipCursor (USER32.@) + */ +BOOL WINAPI /*DECLSPEC_HOTPATCH*/ ClipCursor( const RECT *rect ) +{ + return NtUserClipCursor((RECT *)rect); +} + + +/*********************************************************************** + * GetClipCursor (USER32.@) + */ +BOOL WINAPI /*DECLSPEC_HOTPATCH*/ GetClipCursor( RECT *rect ) +{ + return NtUserGetClipCursor(rect); +} + + +/*********************************************************************** + * SetSystemCursor (USER32.@) + */ +BOOL WINAPI SetSystemCursor(HCURSOR hcur, DWORD id) +{ + FIXME("(%p,%08x),stub!\n", hcur, id); + return TRUE; +} + + +/********************************************************************** + * LookupIconIdFromDirectoryEx (USER32.@) + */ +INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE xdir, BOOL bIcon, + INT width, INT height, UINT cFlag ) +{ + CURSORICONDIR *dir = (CURSORICONDIR*)xdir; + UINT retVal = 0; + if( dir && !dir->idReserved && (dir->idType & 3) ) + { + CURSORICONDIRENTRY* entry; + + const HDC hdc = GetDC(0); + const int depth = (cFlag & LR_MONOCHROME) ? + 1 : GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC(0, hdc); + + if( bIcon ) + entry = CURSORICON_FindBestIconRes( dir, width, height, depth ); + else + entry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); + + if( entry ) retVal = entry->wResId; + } + else WARN_(cursor)("invalid resource directory\n"); + return retVal; +} + +/********************************************************************** + * LookupIconIdFromDirectory (USER32.@) + */ +INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon ) +{ + return LookupIconIdFromDirectoryEx( dir, bIcon, + bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR), + bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME ); +} + +/*********************************************************************** + * LoadCursorW (USER32.@) + */ +HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name) +{ + TRACE("%p, %s\n", hInstance, debugstr_w(name)); + + return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +/*********************************************************************** + * LoadCursorA (USER32.@) + */ +HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name) +{ + TRACE("%p, %s\n", hInstance, debugstr_a(name)); + + return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +/*********************************************************************** + * LoadCursorFromFileW (USER32.@) + */ +HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name) +{ + TRACE("%s\n", debugstr_w(name)); + + return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE ); +} + +/*********************************************************************** + * LoadCursorFromFileA (USER32.@) + */ +HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name) +{ + TRACE("%s\n", debugstr_a(name)); + + return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE ); +} + +/*********************************************************************** + * LoadIconW (USER32.@) + */ +HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name) +{ + TRACE("%p, %s\n", hInstance, debugstr_w(name)); + + return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +/*********************************************************************** + * LoadIconA (USER32.@) + */ +HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name) +{ + TRACE("%p, %s\n", hInstance, debugstr_a(name)); + + return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +/********************************************************************** + * GetIconInfo (USER32.@) + */ +BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo) +{ + return NtUserGetIconInfo(hIcon, iconinfo, 0, 0, 0, 0); +} + +/********************************************************************** + * CreateIconIndirect (USER32.@) + */ +HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) +{ + BITMAP ColorBitmap; + BITMAP MaskBitmap; + + if(!iconinfo) + { + SetLastError(ERROR_INVALID_PARAMETER); + return (HICON)0; + } + + if(!GetObjectW(iconinfo->hbmMask, sizeof(BITMAP), &MaskBitmap)) + { + return (HICON)0; + } + + /* Try to get color bitmap */ + if (GetObjectW(iconinfo->hbmColor, sizeof(BITMAP), &ColorBitmap)) + { + /* Compare size of color and mask bitmap*/ + if (ColorBitmap.bmWidth != MaskBitmap.bmWidth || + ColorBitmap.bmHeight != MaskBitmap.bmHeight) + { + ERR("Color and mask size are different!"); + SetLastError(ERROR_INVALID_PARAMETER); + return (HICON)0; + } + } + return (HICON)NtUserCreateCursorIconHandle(iconinfo, TRUE); +} + +/****************************************************************************** + * DrawIconEx (USER32.@) Draws an icon or cursor on device context + * + * NOTES + * Why is this using SM_CXICON instead of SM_CXCURSOR? + * + * PARAMS + * hdc [I] Handle to device context + * x0 [I] X coordinate of upper left corner + * y0 [I] Y coordinate of upper left corner + * hIcon [I] Handle to icon to draw + * cxWidth [I] Width of icon + * cyWidth [I] Height of icon + * istep [I] Index of frame in animated cursor + * hbr [I] Handle to background brush + * flags [I] Icon-drawing flags + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DrawIconEx( HDC hdc, INT xLeft, INT yTop, HICON hIcon, + INT cxWidth, INT cyWidth, UINT istepIfAniCur, + HBRUSH hbrFlickerFreeDraw, UINT diFlags ) +{ + return NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, + istepIfAniCur, hbrFlickerFreeDraw, diFlags, + 0, 0); +} + +/*********************************************************************** + * DIB_FixColorsToLoadflags + * + * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS + * are in loadflags + */ +static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix) +{ + int colors; + COLORREF c_W, c_S, c_F, c_L, c_C; + int incr,i; + RGBQUAD *ptr; + int bitmap_type; + LONG width; + LONG height; + WORD bpp; + DWORD compr; + + if (((bitmap_type = DIB_GetBitmapInfo((BITMAPINFOHEADER*) bmi, &width, &height, &bpp, &compr)) == -1)) + { + WARN_(resource)("Invalid bitmap\n"); + return; + } + + if (bpp > 8) return; + + if (bitmap_type == 0) /* BITMAPCOREHEADER */ + { + incr = 3; + colors = 1 << bpp; + } + else + { + incr = 4; + colors = bmi->bmiHeader.biClrUsed; + if (colors > 256) colors = 256; + if (!colors && (bpp <= 8)) colors = 1 << bpp; + } + + c_W = GetSysColor(COLOR_WINDOW); + c_S = GetSysColor(COLOR_3DSHADOW); + c_F = GetSysColor(COLOR_3DFACE); + c_L = GetSysColor(COLOR_3DLIGHT); + + if (loadflags & LR_LOADTRANSPARENT) { + switch (bpp) { + case 1: pix = pix >> 7; break; + case 4: pix = pix >> 4; break; + case 8: break; + default: + WARN_(resource)("(%d): Unsupported depth\n", bpp); + return; + } + if (pix >= colors) { + WARN_(resource)("pixel has color index greater than biClrUsed!\n"); + return; + } + if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F; + ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr); + ptr->rgbBlue = GetBValue(c_W); + ptr->rgbGreen = GetGValue(c_W); + ptr->rgbRed = GetRValue(c_W); + } + if (loadflags & LR_LOADMAP3DCOLORS) + for (i=0; ibmiColors+i*incr); + c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue); + if (c_C == RGB(128, 128, 128)) { + ptr->rgbRed = GetRValue(c_S); + ptr->rgbGreen = GetGValue(c_S); + ptr->rgbBlue = GetBValue(c_S); + } else if (c_C == RGB(192, 192, 192)) { + ptr->rgbRed = GetRValue(c_F); + ptr->rgbGreen = GetGValue(c_F); + ptr->rgbBlue = GetBValue(c_F); + } else if (c_C == RGB(223, 223, 223)) { + ptr->rgbRed = GetRValue(c_L); + ptr->rgbGreen = GetGValue(c_L); + ptr->rgbBlue = GetBValue(c_L); + } + } +} + + +/********************************************************************** + * BITMAP_Load + */ +static HBITMAP BITMAP_Load( HINSTANCE instance, LPCWSTR name, + INT desiredx, INT desiredy, UINT loadflags ) +{ + HBITMAP hbitmap = 0, orig_bm; + HRSRC hRsrc; + HGLOBAL handle; + char *ptr = NULL; + BITMAPINFO *info, *fix_info = NULL, *scaled_info = NULL; + int size; + BYTE pix; + char *bits; + LONG width, height, new_width, new_height; + WORD bpp_dummy; + DWORD compr_dummy, offbits = 0; + INT bm_type; + HDC screen_mem_dc = NULL; + + if (!(loadflags & LR_LOADFROMFILE)) + { + if (!instance) + { + /* OEM bitmap: try to load the resource from user32.dll */ + instance = User32Instance; + } + + if (!(hRsrc = FindResourceW( instance, name, (LPWSTR)RT_BITMAP ))) return 0; + if (!(handle = LoadResource( instance, hRsrc ))) return 0; + + if ((info = LockResource( handle )) == NULL) return 0; + } + else + { + BITMAPFILEHEADER * bmfh; + + if (!(ptr = map_fileW( name, NULL ))) return 0; + info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER)); + bmfh = (BITMAPFILEHEADER *)ptr; + if (bmfh->bfType != 0x4d42 /* 'BM' */) + { + WARN("Invalid/unsupported bitmap format!\n"); + goto end_close; + } + if (bmfh->bfOffBits) offbits = bmfh->bfOffBits - sizeof(BITMAPFILEHEADER); + } + + size = bitmap_info_size(info, DIB_RGB_COLORS); + fix_info = HeapAlloc(GetProcessHeap(), 0, size); + scaled_info = HeapAlloc(GetProcessHeap(), 0, size); + + if (!fix_info || !scaled_info) goto end; + memcpy(fix_info, info, size); + + pix = *((LPBYTE)info + size); + DIB_FixColorsToLoadflags(fix_info, loadflags, pix); + + memcpy(scaled_info, fix_info, size); + bm_type = DIB_GetBitmapInfo( &fix_info->bmiHeader, &width, &height, + &bpp_dummy, &compr_dummy); + if(desiredx != 0) + new_width = desiredx; + else + new_width = width; + + if(desiredy != 0) + new_height = height > 0 ? desiredy : -desiredy; + else + new_height = height; + + if(bm_type == 0) + { + BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)&scaled_info->bmiHeader; + core->bcWidth = new_width; + core->bcHeight = new_height; + } + else + { + /* Some sanity checks for BITMAPINFO (not applicable to BITMAPCOREINFO) */ + if (info->bmiHeader.biHeight > 65535 || info->bmiHeader.biWidth > 65535) { + WARN("Broken BitmapInfoHeader!\n"); + goto end; + } + + scaled_info->bmiHeader.biWidth = new_width; + scaled_info->bmiHeader.biHeight = new_height; + } + + if (new_height < 0) new_height = -new_height; + + if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); + if (!(screen_mem_dc = CreateCompatibleDC( screen_dc ))) goto end; + + bits = (char *)info + (offbits ? offbits : size); + + if (loadflags & LR_CREATEDIBSECTION) + { + scaled_info->bmiHeader.biCompression = 0; /* DIBSection can't be compressed */ + hbitmap = CreateDIBSection(screen_dc, scaled_info, DIB_RGB_COLORS, NULL, 0, 0); + } + else + { + if (is_dib_monochrome(fix_info)) + hbitmap = CreateBitmap(new_width, new_height, 1, 1, NULL); + else + hbitmap = CreateCompatibleBitmap(screen_dc, new_width, new_height); + } + + orig_bm = SelectObject(screen_mem_dc, hbitmap); + StretchDIBits(screen_mem_dc, 0, 0, new_width, new_height, 0, 0, width, height, bits, fix_info, DIB_RGB_COLORS, SRCCOPY); + SelectObject(screen_mem_dc, orig_bm); + +end: + if (screen_mem_dc) DeleteDC(screen_mem_dc); + HeapFree(GetProcessHeap(), 0, scaled_info); + HeapFree(GetProcessHeap(), 0, fix_info); +end_close: + if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr ); + + return hbitmap; +} + +/********************************************************************** + * LoadImageA (USER32.@) + * + * See LoadImageW. + */ +HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type, + INT desiredx, INT desiredy, UINT loadflags) +{ + HANDLE res; + LPWSTR u_name; + + if (IS_INTRESOURCE(name)) + return LoadImageW(hinst, (LPCWSTR)name, type, desiredx, desiredy, loadflags); + + __TRY { + DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 ); + u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, name, -1, u_name, len ); + } + __EXCEPT_PAGE_FAULT { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + __ENDTRY + res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags); + HeapFree(GetProcessHeap(), 0, u_name); + return res; +} + + +/****************************************************************************** + * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap + * + * PARAMS + * hinst [I] Handle of instance that contains image + * name [I] Name of image + * type [I] Type of image + * desiredx [I] Desired width + * desiredy [I] Desired height + * loadflags [I] Load flags + * + * RETURNS + * Success: Handle to newly loaded image + * Failure: NULL + * + * FIXME: Implementation lacks some features, see LR_ defines in winuser.h + */ +HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type, + INT desiredx, INT desiredy, UINT loadflags ) +{ + TRACE_(resource)("(%p,%s,%d,%d,%d,0x%08x)\n", + hinst,debugstr_w(name),type,desiredx,desiredy,loadflags); + + if (loadflags & LR_DEFAULTSIZE) { + if (type == IMAGE_ICON) { + if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON); + if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON); + } else if (type == IMAGE_CURSOR) { + if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR); + if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR); + } + } + if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED; + switch (type) { + case IMAGE_BITMAP: + return BITMAP_Load( hinst, name, desiredx, desiredy, loadflags ); + + case IMAGE_ICON: + if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); + if (screen_dc) + { + return CURSORICON_Load(hinst, name, desiredx, desiredy, + GetDeviceCaps(screen_dc, BITSPIXEL), + FALSE, loadflags); + } + break; + + case IMAGE_CURSOR: + return CURSORICON_Load(hinst, name, desiredx, desiredy, + 1, TRUE, loadflags); + } + return 0; +} + +/****************************************************************************** + * CopyImage (USER32.@) Creates new image and copies attributes to it + * + * PARAMS + * hnd [I] Handle to image to copy + * type [I] Type of image to copy + * desiredx [I] Desired width of new image + * desiredy [I] Desired height of new image + * flags [I] Copy flags + * + * RETURNS + * Success: Handle to newly created image + * Failure: NULL + * + * BUGS + * Only Windows NT 4.0 supports the LR_COPYRETURNORG flag for bitmaps, + * all other versions (95/2000/XP have been tested) ignore it. + * + * NOTES + * If LR_CREATEDIBSECTION is absent, the copy will be monochrome for + * a monochrome source bitmap or if LR_MONOCHROME is present, otherwise + * the copy will have the same depth as the screen. + * The content of the image will only be copied if the bit depth of the + * original image is compatible with the bit depth of the screen, or + * if the source is a DIB section. + * The LR_MONOCHROME flag is ignored if LR_CREATEDIBSECTION is present. + */ +HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, + INT desiredy, UINT flags ) +{ + TRACE("hnd=%p, type=%u, desiredx=%d, desiredy=%d, flags=%x\n", + hnd, type, desiredx, desiredy, flags); + + switch (type) + { + case IMAGE_BITMAP: + { + HBITMAP res = NULL; + DIBSECTION ds; + int objSize; + BITMAPINFO * bi; + + objSize = GetObjectW( hnd, sizeof(ds), &ds ); + if (!objSize) return 0; + if ((desiredx < 0) || (desiredy < 0)) return 0; + + if (flags & LR_COPYFROMRESOURCE) + { + FIXME("The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n"); + } + + if (desiredx == 0) desiredx = ds.dsBm.bmWidth; + if (desiredy == 0) desiredy = ds.dsBm.bmHeight; + + /* Allocate memory for a BITMAPINFOHEADER structure and a + color table. The maximum number of colors in a color table + is 256 which corresponds to a bitmap with depth 8. + Bitmaps with higher depths don't have color tables. */ + bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + if (!bi) return 0; + + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes; + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + bi->bmiHeader.biCompression = BI_RGB; + + if (flags & LR_CREATEDIBSECTION) + { + /* Create a DIB section. LR_MONOCHROME is ignored */ + void * bits; + HDC dc = CreateCompatibleDC(NULL); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB. + Get its attributes to create an exact copy */ + memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); + } + + /* Get the color table or the color masks */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + + bi->bmiHeader.biWidth = desiredx; + bi->bmiHeader.biHeight = desiredy; + bi->bmiHeader.biSizeImage = 0; + + res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0); + DeleteDC(dc); + } + else + { + /* Create a device-dependent bitmap */ + + BOOL monochrome = (flags & LR_MONOCHROME); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB section. + Get its attributes */ + HDC dc = CreateCompatibleDC(NULL); + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + DeleteDC(dc); + + if (!monochrome && ds.dsBm.bmBitsPixel == 1) + { + /* Look if the colors of the DIB are black and white */ + + monochrome = + (bi->bmiColors[0].rgbRed == 0xff + && bi->bmiColors[0].rgbGreen == 0xff + && bi->bmiColors[0].rgbBlue == 0xff + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0 + && bi->bmiColors[1].rgbGreen == 0 + && bi->bmiColors[1].rgbBlue == 0 + && bi->bmiColors[1].rgbReserved == 0) + || + (bi->bmiColors[0].rgbRed == 0 + && bi->bmiColors[0].rgbGreen == 0 + && bi->bmiColors[0].rgbBlue == 0 + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0xff + && bi->bmiColors[1].rgbGreen == 0xff + && bi->bmiColors[1].rgbBlue == 0xff + && bi->bmiColors[1].rgbReserved == 0); + } + } + else if (!monochrome) + { + monochrome = ds.dsBm.bmBitsPixel == 1; + } + + if (monochrome) + { + res = CreateBitmap(desiredx, desiredy, 1, 1, NULL); + } + else + { + HDC screenDC = GetDC(NULL); + res = CreateCompatibleBitmap(screenDC, desiredx, desiredy); + ReleaseDC(NULL, screenDC); + } + } + + if (res) + { + /* Only copy the bitmap if it's a DIB section or if it's + compatible to the screen */ + BOOL copyContents; + + if (objSize == sizeof(DIBSECTION)) + { + copyContents = TRUE; + } + else + { + HDC screenDC = GetDC(NULL); + int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL); + ReleaseDC(NULL, screenDC); + + copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth); + } + + if (copyContents) + { + /* The source bitmap may already be selected in a device context, + use GetDIBits/StretchDIBits and not StretchBlt */ + + HDC dc; + void * bits; + + dc = CreateCompatibleDC(NULL); + + bi->bmiHeader.biWidth = ds.dsBm.bmWidth; + bi->bmiHeader.biHeight = ds.dsBm.bmHeight; + bi->bmiHeader.biSizeImage = 0; + bi->bmiHeader.biClrUsed = 0; + bi->bmiHeader.biClrImportant = 0; + + /* Fill in biSizeImage */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage); + + if (bits) + { + HBITMAP oldBmp; + + /* Get the image bits of the source bitmap */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS); + + /* Copy it to the destination bitmap */ + oldBmp = SelectObject(dc, res); + StretchDIBits(dc, 0, 0, desiredx, desiredy, + 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, + bits, bi, DIB_RGB_COLORS, SRCCOPY); + SelectObject(dc, oldBmp); + + HeapFree(GetProcessHeap(), 0, bits); + } + + DeleteDC(dc); + } + + if (flags & LR_COPYDELETEORG) + { + DeleteObject(hnd); + } + } + HeapFree(GetProcessHeap(), 0, bi); + return res; + } + case IMAGE_ICON: + return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags); + case IMAGE_CURSOR: + /* Should call CURSORICON_ExtCopy but more testing + * needs to be done before we change this + */ + if (flags) FIXME("Flags are ignored\n"); + return CopyCursor(hnd); + } + return 0; +} + + +/****************************************************************************** + * LoadBitmapW (USER32.@) Loads bitmap from the executable file + * + * RETURNS + * Success: Handle to specified bitmap + * Failure: NULL + */ +HBITMAP WINAPI LoadBitmapW( + HINSTANCE instance, /* [in] Handle to application instance */ + LPCWSTR name) /* [in] Address of bitmap resource name */ +{ + return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 ); +} + +/********************************************************************** + * LoadBitmapA (USER32.@) + * + * See LoadBitmapW. + */ +HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name ) +{ + return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 ); +} + +HCURSOR +CursorIconToCursor(HICON hIcon, + BOOL SemiTransparent) +{ + UNIMPLEMENTED; + return 0; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetCursorPos(int X, + int Y) +{ + return NtUserSetCursorPos(X,Y); +} + +/* + * @implemented + */ +BOOL +WINAPI +GetCursorPos(LPPOINT lpPoint) +{ + BOOL res; + /* Windows doesn't check if lpPoint == NULL, we do */ + if(!lpPoint) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + res = NtUserGetCursorPos(lpPoint); + + return res; +} + +#undef CopyCursor +/* + * @implemented + */ +HCURSOR +WINAPI +CopyCursor(HCURSOR pcur) +{ + ICONINFO IconInfo; + + if(GetIconInfo((HANDLE)pcur, &IconInfo)) + { + return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE); + } + return (HCURSOR)0; +} + +/* INTERNAL ******************************************************************/ + +/* This callback routine is called directly after switching to gui mode */ +NTSTATUS +WINAPI +User32SetupDefaultCursors(PVOID Arguments, + ULONG ArgumentLength) +{ + BOOL *DefaultCursor = (BOOL*)Arguments; + LRESULT Result = TRUE; + + if(*DefaultCursor) + { + /* set default cursor */ + SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); + } + else + { + /* FIXME load system cursor scheme */ + SetCursor(0); + SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); + } + + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} diff --git a/reactos/dll/win32/user32/windows/icon.c b/reactos/dll/win32/user32/windows/icon.c deleted file mode 100644 index b663dcc9407..00000000000 --- a/reactos/dll/win32/user32/windows/icon.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS user32.dll - * FILE: dll/win32/user32/windows/icon.c - * PURPOSE: Icon - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 09-05-2001 CSH Created - */ - -/* INCLUDES ******************************************************************/ - -#include - -#include -WINE_DEFAULT_DEBUG_CHANNEL(user32); - -/* FUNCTIONS *****************************************************************/ - - -HICON -CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon) -{ - BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)]; - BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer; - ICONINFO IconInfo; - - IconInfo.fIcon = fIcon; - IconInfo.xHotspot = xHotspot; - IconInfo.yHotspot = yHotspot; - - if (IconImage->icHeader.biBitCount == 1) - { - IconInfo.hbmColor = (HBITMAP)0; - IconImage->icHeader.biHeight *= 2; - IconInfo.hbmMask = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT, - ImageData, (BITMAPINFO*)IconImage, - DIB_RGB_COLORS); - } - else - { - /* Create the XOR bitmap */ - IconInfo.hbmColor = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT, - ImageData, (BITMAPINFO*)IconImage, - DIB_RGB_COLORS); - - /* Make ImageData point to the start of the AND image data. */ - ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth * - IconImage->icHeader.biBitCount + 31) & ~31) >> 3) * - (IconImage->icHeader.biHeight ); - - /* Create a BITMAPINFO header for the monochrome part of the icon. */ - bwBIH->bmiHeader.biBitCount = 1; - bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth; - bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight; - bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bwBIH->bmiHeader.biPlanes = 1; - bwBIH->bmiHeader.biSizeImage = 0; - bwBIH->bmiHeader.biCompression = BI_RGB; - bwBIH->bmiHeader.biClrImportant = 2; - bwBIH->bmiHeader.biClrUsed = 2; - bwBIH->bmiHeader.biXPelsPerMeter = 0; - bwBIH->bmiHeader.biYPelsPerMeter = 0; - - bwBIH->bmiColors[0].rgbBlue = 0; - bwBIH->bmiColors[0].rgbGreen = 0; - bwBIH->bmiColors[0].rgbRed = 0; - bwBIH->bmiColors[0].rgbReserved = 0; - - bwBIH->bmiColors[1].rgbBlue = 0xff; - bwBIH->bmiColors[1].rgbGreen = 0xff; - bwBIH->bmiColors[1].rgbRed = 0xff; - bwBIH->bmiColors[1].rgbReserved = 0; - - /* Create the AND bitmap. */ - IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0, - ImageData, bwBIH, DIB_RGB_COLORS); - - SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight, - ImageData, bwBIH, DIB_RGB_COLORS); - } - - - /* Create the icon based on everything we have so far */ - return NtUserCreateCursorIconHandle(&IconInfo, FALSE); -} - -/* - * @implemented - */ -HICON -WINAPI -CopyIcon(HICON hIcon) -{ - HICON hRetIcon = NULL; - ICONINFO IconInfo; - - if(GetIconInfo(hIcon, &IconInfo)) - { - hRetIcon = CreateIconIndirect(&IconInfo); - DeleteObject(IconInfo.hbmColor); - DeleteObject(IconInfo.hbmMask); - } - - return hRetIcon; -} - - -/* - * @implemented - */ -HICON -WINAPI -CreateIcon( - HINSTANCE hInstance, - int nWidth, - int nHeight, - BYTE cPlanes, - BYTE cBitsPixel, - CONST BYTE *ANDbits, - CONST BYTE *XORbits) -{ - ICONINFO IconInfo; - - IconInfo.fIcon = TRUE; - - if (cBitsPixel == 1) - { - nHeight <<= 1; - } - IconInfo.hbmMask = CreateBitmap(nWidth, nHeight, 1, 1, ANDbits); - if(!IconInfo.hbmMask) - { - return (HICON)0; - } - - if (cBitsPixel == 1) - { - IconInfo.hbmColor = (HBITMAP)0; - } - else - { - IconInfo.hbmColor = CreateBitmap(nWidth, nHeight, cPlanes, cBitsPixel, XORbits); - if(!IconInfo.hbmColor) - { - DeleteObject(IconInfo.hbmMask); - return (HICON)0; - } - } - - return NtUserCreateCursorIconHandle(&IconInfo, FALSE); -} - - -/* - * @implemented - */ -HICON -WINAPI -CreateIconFromResource( - PBYTE presbits, - DWORD dwResSize, - BOOL fIcon, - DWORD dwVer) -{ - return CreateIconFromResourceEx(presbits, dwResSize, fIcon, dwVer, 0, 0, LR_DEFAULTSIZE|LR_SHARED ); -} - - -/* - * @implemented - */ -HICON -WINAPI -CreateIconFromResourceEx( - PBYTE pbIconBits, - DWORD cbIconBits, - BOOL fIcon, - DWORD dwVersion, - int cxDesired, - int cyDesired, - UINT uFlags) -{ - ICONIMAGE* SafeIconImage; - HICON hIcon; - ULONG HeaderSize; - ULONG ColourCount; - PVOID Data; - HDC hScreenDc; - WORD wXHotspot; - WORD wYHotspot; - - /* - FIXME - does win support LR_SHARED? According to msdn it does but we don't - have useful information to identify the icon - if (uFlags & LR_SHARED) - { - DbgPrint("FIXME: need LR_SHARED support in CreateIconFromResourceEx()\n"); - } - */ - - TRACE("dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n"); - - if (! fIcon) - { - wXHotspot = *(WORD*)pbIconBits; - pbIconBits += sizeof(WORD); - wYHotspot = *(WORD*)pbIconBits; - pbIconBits += sizeof(WORD); - cbIconBits -= 2 * sizeof(WORD); - } - else - { - wXHotspot = cxDesired / 2; - wYHotspot = cyDesired / 2; - } - - /* get an safe copy of the icon data */ - SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, cbIconBits); - if (SafeIconImage == NULL) - { - return NULL; - } - memcpy(SafeIconImage, pbIconBits, cbIconBits); - - /* Take into acount the original height was for both the AND and XOR images */ - SafeIconImage->icHeader.biHeight /= 2; - - if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) - { - BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage; - ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; - HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE); - } - else - { - ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ? - (1 << SafeIconImage->icHeader.biBitCount) : 0; - HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD); - } - - /* make data point to the start of the XOR image data */ - Data = (PBYTE)SafeIconImage + HeaderSize; - - /* get a handle to the screen dc, the icon we create is going to be compatable with this */ - // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!! - //hScreenDc = CreateDCW(NULL, NULL, NULL, NULL); - hScreenDc = CreateCompatibleDC(NULL); - if (hScreenDc == NULL) - { - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return(NULL); - } - - hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot, fIcon); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - DeleteDC(hScreenDc); - - return hIcon; -} - - -/* - * @implemented - */ -HICON -WINAPI -CreateIconIndirect(PICONINFO IconInfo) -{ - BITMAP ColorBitmap; - BITMAP MaskBitmap; - HBITMAP hbmTemp; - - if(!IconInfo) - { - SetLastError(ERROR_INVALID_PARAMETER); - return (HICON)0; - } - - if(!GetObjectW(IconInfo->hbmMask, sizeof(BITMAP), &MaskBitmap)) - { - return (HICON)0; - } - - /* Try to get color bitmap */ - if (GetObjectW(IconInfo->hbmColor, sizeof(BITMAP), &ColorBitmap)) - { - /* Compare size of color and mask bitmap*/ - if (ColorBitmap.bmWidth != MaskBitmap.bmWidth || - ColorBitmap.bmHeight != MaskBitmap.bmHeight) - { - ERR("Color and mask size are different!"); - SetLastError(ERROR_INVALID_PARAMETER); - return (HICON)0; - } - /* Check if color and mask are switched and switch them back */ - if (MaskBitmap.bmBitsPixel != 1 && ColorBitmap.bmBitsPixel == 1) - { - hbmTemp = IconInfo->hbmMask; - IconInfo->hbmMask = IconInfo->hbmColor; - IconInfo->hbmColor = hbmTemp; - } - } - return (HICON)NtUserCreateCursorIconHandle(IconInfo, TRUE); -} - - -/* - * @implemented - */ -BOOL -WINAPI -DestroyIcon( - HICON hIcon) -{ - return (BOOL)NtUserDestroyCursor((HANDLE)hIcon, 0); -} - - -/* - * @implemented - */ -BOOL -WINAPI -DrawIcon( - HDC hDC, - int X, - int Y, - HICON hIcon) -{ - return DrawIconEx(hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL|DI_DEFAULTSIZE|DI_COMPAT); -} - -/* - * @implemented - */ -BOOL -WINAPI -DrawIconEx( - HDC hdc, - int xLeft, - int yTop, - HICON hIcon, - int cxWidth, - int cyWidth, - UINT istepIfAniCur, - HBRUSH hbrFlickerFreeDraw, - UINT diFlags) -{ - return (BOOL)NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, - istepIfAniCur, hbrFlickerFreeDraw, diFlags, - 0, 0); -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetIconInfo( - HICON hIcon, - PICONINFO IconInfo) -{ - return NtUserGetIconInfo((HANDLE)hIcon, IconInfo, 0, 0, 0, 0); -} - - -/* - * @implemented - */ -HICON -WINAPI -LoadIconA( - HINSTANCE hInstance, - LPCSTR lpIconName) -{ - return(LoadImageA(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE)); -} - - -/* - * @implemented - */ -HICON -WINAPI -LoadIconW( - HINSTANCE hInstance, - LPCWSTR lpIconName) -{ - return(LoadImageW(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE)); -} - - -/* - * @implemented - */ -int -WINAPI -LookupIconIdFromDirectory( - PBYTE presbits, - BOOL fIcon) -{ - return LookupIconIdFromDirectoryEx(presbits, - fIcon, - fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR), - fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), - LR_DEFAULTCOLOR); -} - - - - - -/* - * The following macro function accounts for the irregularities of - * accessing cursor and icon resources in files and resource entries. - */ -typedef BOOL -(*fnGetCIEntry)(LPVOID dir, int n, int *width, int *height, int *bits ); - -/********************************************************************** - * CURSORICON_FindBestIcon - * - * Find the icon closest to the requested size and number of colors. - */ -static int -CURSORICON_FindBestIcon(LPVOID dir, - fnGetCIEntry get_entry, - int Width, - int Height, - int ColorBits) -{ - int i, cx, cy, Bits, BestBits = 0, BestEntry = -1; - UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff; - UINT iTempXDiff, iTempYDiff, iTempColorDiff; - - /* Find Best Fit */ - iTotalDiff = 0xFFFFFFFF; - iColorDiff = 0xFFFFFFFF; - for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ ) - { - iTempXDiff = abs(Width - cx); - iTempYDiff = abs(Height - cy); - - if(iTotalDiff > (iTempXDiff + iTempYDiff)) - { - iXDiff = iTempXDiff; - iYDiff = iTempYDiff; - iTotalDiff = iXDiff + iYDiff; - } - } - - /* Find Best Colors for Best Fit */ - for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ ) - { - if(abs(Width - cx) == iXDiff && abs(Height - cy) == iYDiff) - { - iTempColorDiff = abs(ColorBits - Bits); - if(iColorDiff > iTempColorDiff) - { - BestEntry = i; - BestBits = Bits; - iColorDiff = iTempColorDiff; - } - } - } - - TRACE("Best Icon: ResId: %d, bits : %d\n", BestEntry, BestBits); - - return BestEntry; -} - - - -/********************************************************************** - * CURSORICON_FindBestCursor - * - * Find the cursor closest to the requested size. - * FIXME: parameter 'color' ignored and entries with more than 1 bpp - * ignored too - */ -static int -CURSORICON_FindBestCursor(LPVOID dir, - fnGetCIEntry get_entry, - int Width, - int Height, - int ColorBits) -{ - int i, cx, cy, Bits, BestBits = 0, BestEntry = -1; - UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff; - UINT iTempXDiff, iTempYDiff, iTempColorDiff; - - /* Find Best Fit */ - iTotalDiff = 0xFFFFFFFF; - iColorDiff = 0xFFFFFFFF; - for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ ) - { - iTempXDiff = abs(Width - cx); - iTempYDiff = abs(Height - cy); - - if(iTotalDiff > (iTempXDiff + iTempYDiff)) - { - iXDiff = iTempXDiff; - iYDiff = iTempYDiff; - iTotalDiff = iXDiff + iYDiff; - } - } - - /* Find Best Colors for Best Fit */ - for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ ) - { - if(abs(Width - cx) == iXDiff && abs(Height - cy) == iYDiff) - { - iTempColorDiff = abs(ColorBits - Bits); - if(iColorDiff > iTempColorDiff) - { - BestEntry = i; - BestBits = Bits; - iColorDiff = iTempColorDiff; - } - } - } - - TRACE("Best Cursor: ResId: %d, bits : %d\n", BestEntry, BestBits); - - return BestEntry; -} - - -static BOOL -CURSORICON_GetResIconEntry(LPVOID dir, - int n, - int *Width, - int *Height, - int *Bits) -{ - GRPCURSORICONDIR *ResDir = dir; - ICONRESDIR *Icon; - - if (ResDir->idCount <= n) - return FALSE; - - Icon = &ResDir->idEntries[n].ResInfo.icon; - *Width = Icon->bWidth; - *Height = Icon->bHeight; - *Bits = ResDir->idEntries[n].wBitCount; - return TRUE; -} - -static BOOL -CURSORICON_GetResCursorEntry(LPVOID dir, - int n, - int *Width, - int *Height, - int *Bits) -{ - GRPCURSORICONDIR *ResDir = dir; - CURSORRESDIR *Cursor; - - if (ResDir->idCount <= n) - return FALSE; - - Cursor = &ResDir->idEntries[n].ResInfo.cursor; - *Width = Cursor->wWidth; - *Height = Cursor->wHeight; - *Bits = ResDir->idEntries[n].wBitCount; - return TRUE; -} - -static GRPCURSORICONDIRENTRY * -CURSORICON_FindBestIconRes(GRPCURSORICONDIR * dir, - int Width, - int Height, - int ColorBits) -{ - int n; - n = CURSORICON_FindBestIcon(dir, - CURSORICON_GetResIconEntry, - Width, - Height, - ColorBits); - if (n < 0) - return NULL; - - return &dir->idEntries[n]; -} - -static GRPCURSORICONDIRENTRY * -CURSORICON_FindBestCursorRes(GRPCURSORICONDIR *dir, - int Width, - int Height, - int ColorBits) -{ - int n; - n = CURSORICON_FindBestCursor(dir, - CURSORICON_GetResCursorEntry, - Width, - Height, - ColorBits); - if (n < 0) - return NULL; - - return &dir->idEntries[n]; -} - - -INT WINAPI -LookupIconIdFromDirectoryEx(PBYTE xdir, - BOOL bIcon, - INT width, - INT height, - UINT cFlag) -{ - GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)xdir; - UINT retVal = 0; - - GetConnected(); - - if(dir && !dir->idReserved && (IMAGE_ICON == dir->idType || IMAGE_CURSOR == dir->idType)) - { - GRPCURSORICONDIRENTRY *entry = NULL; - int ColorBits; - - if (cFlag & LR_MONOCHROME) - { - ColorBits = 1; - } - else if (cFlag & LR_VGACOLOR) - { - ColorBits = 4; - } - else - { - ColorBits = gpsi->BitsPixel; - } - - if(bIcon) - entry = CURSORICON_FindBestIconRes(dir, width, height, ColorBits); - else - entry = CURSORICON_FindBestCursorRes(dir, width, height, 1); - - if (entry) - retVal = entry->nID; - } - else - WARN("%s() : Invalid resource directory\n", __FUNCTION__); - - return retVal; -} diff --git a/reactos/include/reactos/win32k/ntusrtyp.h b/reactos/include/reactos/win32k/ntusrtyp.h index 3d40ac86b87..b54bc9bc7e1 100644 --- a/reactos/include/reactos/win32k/ntusrtyp.h +++ b/reactos/include/reactos/win32k/ntusrtyp.h @@ -82,31 +82,27 @@ typedef struct typedef struct { - WORD wXHotspot; // Number of Color Planes in the XOR image - WORD wYHotspot; // Bits per pixel in the XOR image + WORD wWidth; + WORD wHeight; } CURSORDIR; typedef struct -{ - BYTE bWidth; // Width, in pixels, of the icon image - BYTE bHeight; // Height, in pixels, of the icon image - BYTE bColorCount; // Number of colors in image (0 if >=8bpp) - BYTE bReserved; // Reserved ( must be 0) - union - { - ICONDIR icon; - CURSORDIR cursor; - } Info; - DWORD dwBytesInRes; // How many bytes in this resource? - DWORD dwImageOffset; // Where in the file is this image? +{ union + { ICONRESDIR icon; + CURSORDIR cursor; + } ResInfo; + WORD wPlanes; + WORD wBitCount; + DWORD dwBytesInRes; + WORD wResId; } CURSORICONDIRENTRY; typedef struct { - WORD idReserved; // Reserved (must be 0) - WORD idType; // Resource Type (1 for icons, 0 for cursors) - WORD idCount; // How many images? - CURSORICONDIRENTRY idEntries[1];// An entry for idCount number of images + WORD idReserved; + WORD idType; + WORD idCount; + CURSORICONDIRENTRY idEntries[1]; } CURSORICONDIR; typedef struct