wine/objects/cursoricon.c
Alexandre Julliard ebfc0fee51 Release 980628
Sun Jun 28 18:37:02 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [if1632/signal.c] [miscemu/instr.c] [memory/virtual.c]
	Moved page-fault handling to INSTR_EmulateInstruction.

	* [scheduler/thread.c]
	Added locking and check for own thread in Suspend/ResumeThread.

Sat Jun 27 21:25:21 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [objects/dib.c] [objects/bitmap.c] [objects/oembitmap.c] 
	  [graphics/x11drv/bitblt.c] [include/bitmap.h]
	Improved DIB section handling using page fault handlers.
	(Note: This patch includes code contributed by Matthew J. Francis.)

	* [memory/virtual.c] [if1632/signal.c] [include/global.h]
	Page Fault handler support added.

	* [if1632/signal.c] [loader/signal.c] [tools/build.c] [misc/system.c]
	  [misc/winsock_dns.c] [include/sig_context.h] [include/thread.h]
	16-bit %fs handling improved: Always preserve 16-bit %fs value,
	always restore 32-bit %fs value for signal handlers.

	* [if1632/thunk.c] [loader/module.c] [misc/callback.c] [windows/user.c]
	  [loader/ne/resource.c] [include/callback.h] [include/module.h]
	  [if1632/kernel.spec] [if1632/wprocs.spec]
	Resource Handler function pointer stored as 16-bit SEGPTR.

	* [loader/task.c] [windows/win.c] [windows/winpos.c] [if1632/user.spec]
	  [if1632/kernel.spec] [loader/ne/module.c]
	Some minor incompatibilities fixed (Win32s relies on those):
	GetExePtr, IsWindow16 should set ES on return; WINPOS_SendNCCalcSize
	should cope with having the WINDOWPOS structure trashed;
	the OFSTRUCT in the NE module image should be placed *last*.

	* [include/windows.h]
	Missing prototype for FlushViewOfFile.

	* [loader/task.c]
	Bugfix: Command line should *not* start with a blank.
	
	* [loader/ne/segment.c]
	Bugfix: Fixups to offset 0 were never applied.

	* [misc/lstr.c]
	Use debugstr_a in OutputDebugString16.

	* [msdos/dpmi.c]
	Stub for int 31 BL=2f AX=7a20 (NetWare: Get VLM Call Address) added.

	* [msdos/int21.c]
	Stub for int 21 AX=440d CL=6f (get drive map information) added.

Fri Jun 26 18:08:30 1998  Rein Klazes <rklazes@casema.net>

	* [windows/winpos.c]
	Fix small buglet that mixed up maximized and minimized windows.

	* [include/x11drv.h] [objects/dc.c] [graphics/x11drv/pen.c]
	  [graphics/x11drv/graphics.c]
	Fix some bugs with lines joining styles. Draws rectangles
	with thick pens now correctly.

Fri Jun 26 16:22:23 1998  James Juran <jrj120@psu.edu>

	* [misc/shell.c]
	Fixed bug I introduced last release in InternalExtractIcon.

	* [win32/file.c]
	Added documentation for CreateFile32A.

	* [documentation/wine.man]
	Updated manpage.	

	* [ChangeLog]
	Added my entry from last release.

Fri Jun 26 13:33:30 1998  Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>

	* [graphics/psdrv/*] [if1632/wineps.spec] [include/psdrv.h]
	  [include/print.h] [objects/gdiobj.c]
	First stages of an internal Postscript driver. See
	graphics/psdrv/README . Should print text (badly) from win3.1 notepad,
	write and winword6.

	* [documentation/printing]
	Some notes on printing.

	* [controls/edit.c]
	Strip off WS_BORDER in WM_NCREATE, edit draws its own rectangle.
	EC_USEFONTINFO seems to be used as a left/right value for EM_SETMARGINS
	and not as an action as the docs say. This actually makes more sense.
	Scroll the caret back to zero after a WM_SETTEXT.

Fri Jun 26 10:56:25 1998  Marcus Meissner <marcus@jet.franken.de>

	* [if1632/snoop.c]
	Added win16 inter-dll snooping.

	* [win32/ordinals.c]
	KERNEL_485 is GetProcessDword.

	* [include/xmalloc.h][include/bitmap.h][misc/xmalloc.c]
	Added xcalloc so we 0 initialize XImages. 
	Fixes/Hides the 'junk around MOPYFish'.

	* [misc/ntdll.c]
	Some stubs added.

Thu Jun 25 15:22:43 1998  Adrian Harvey <adrian@select.com.au>

	* [scheduler/thread.c] 
	Implemented SuspendThread and ResumeThread.

Thu Jun 25 00:55:03 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/debug.h,dplay.h,dsound.h][multimedia/dsound.c,dplay.c]
	  [relay32/dplayx.spec,dplay.spec][multimedia/Makefile.in]
	  [documentation/status/directplay]
	Added preliminary support for DirectPlay & DirectPlayLobby. Moved the
	preliminary stubs put in the dsound files into two new files
	dplay.h and dplay.c.
	Added new debug channel (dplay) for this.
	Created new document to keep track of implementation.

	* [include/winioctl.h][win32/device.c]
	Added some framework in DeviceIoControl to, in the future, support
	the "builtin" windows dwIoControlCodes. Added new header file
	winioctl.h . 

	* [multimedia/mmsystem.c]
	Added slightly improved debugging information for PlaySound.

Wed Jun 24 12:00:00 1998  Juergen Schmied <juergen.schmied@metronet.de> 

	* [files/profile.c][graphics/x11drv/xfont.c][loader/module.c]
	Changed lstrcmpi32A to strcasecmp, lstrncmpi32A to strncasecmp,
	lstrcpy32A to strcpy, lstrlen32A to strlen, lstrcmp32A to strcmp
	because it's not necessary to support locale on such places.
	It causes a huge overhead and even fails sometimes 

	* [include/oleauto.h][include/winerror.h]
	Added some ole-related constants.

	* [misc/shell.c]
	SHELL32_DllGetClassObject, SHGetSpecialFolderLocation,
	SHGetPathFromIDList improved the stubs

	* [ole/folders.c]
	IShellFolder* functions rewrote the stubs so don't crash and give
	something sensible back, started implementation of.

	* [ole/typelib.c][relay32/oleaut32.spec]
	LoadTypeLib32, RegisterTypeLib stub.

	* [ole/ole2nls.c]
	Fixed a buffer overrun in CompareString32A.
	Test for a bad pointer in LCMapString32A (happens
	in winhlp32 while building a index for searching). 

	* [relay32/oleaut32.spec] [ole/typelib.c]
	Added stub for LoadTypeLib (ole32) to make excel95 happy.

Tue Jun 23 22:47:09 1998  Alex Priem <alexp@sci.kun.nl>

	* [files/profile.c] [relay32/kernel32.spec]
	Added WritePrivateProfileStructA, GetPrivateProfileStructA,
	GetPrivateProfileSectionNames16.

Tue Jun 23 01:34:43 1998  Pascal Cuoq <pcuoq@ens-lyon.fr>

	* [ole/ole2nls.c]
	GetStringTypeEx32A: Implemented CT_CTYPE2 and CT_CTYPE3 cases.
	LCMapString32A: Map final '\0' for '\0'-terminated strings.

	* [misc/shellord.c] [files/profile.c] [graphics/driver.c] 
	  [loader/module.c] [msdos/int21.c] [windows/driver.c] [files/drive.c]
	Changed lstrcmpi32A -> strcasecmp.  Should be OK in these places.

Sat Jun 20 23:40:00 1998  Bertho Stultiens <bertho@akhphd.au.dk>

	* [tools/wrc/]
	Wrc version 1.0.2 (20-Jun-1998). Please revert to 
	the file tools/wrc/CHANGES for details.

Sat Jun 20 14:58:00 1998  Marcel Baur  <mbaur@g26.ethz.ch>

	* [ole/ole2nls.c] [ole/nls/*]
	Added the first 57 nls files, most are not yet complete.

Wed Jun 17 11:16:54 1998  David Luyer <luyer@ucs.uwa.edu.au>

	* [relay32/relay386.c] [if1632/relay.c]
	Move debug_relay_(include|exclude)_list handling into
	seperate function RELAY_ShowDebugmsgsRelay().  Include
	checking of this for 16 bit calls (originally only
	32-bit calls).

	* [relay32/snoop.c] [misc/main.c]
	Add debug_snoop_(include|exclude)_list as per the relay stuff.
	Fix typo and add information on -debugmsg +/-relay=... in
	help on -debugmsg.  Refer to availability of snoop too.

Tue Jun 10 22:00:18 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [controls/header.c][include/header.h][include/commctrl.h]
	Added owner draw support.

	* [windows/nonclient.c][windows/sysmetics.c]
	Fixed menu bar height for Win95 look.
	Split NC_AdjustRect95() into NC_AdjustRectOuter95() and
	NC_AdjustRectInner95 to fix a menu bar bug.
	Improved Win95 look.

	* [controls/progress.c]
	Improved drawing code. Borders will be drawn by non-client code.

	* [controls/updown.c]
	Changed memory allocation and fixed some bugs.

	* [controls/toolbar.c]
	Fixed TB_BUTTONSTRUCTSIZE bug in MFC programs.
	Several improvements.

	* [misc/shell.c]
	Added stub for BrowseForFoldersA().

	* [misc/shellord.c]
	Added stub for SHELL32_147().

	* [controls/comctl32undoc.c]
	Minor changes.

	* [documentation/common_controls]
	New File: Documentation about development status, undocumented
	features and functions of the common controls.
1998-06-28 18:40:26 +00:00

1678 lines
55 KiB
C

/*
* Cursor and icon support
*
* Copyright 1995 Alexandre Julliard
* 1996 Martin Von Loewis
* 1997 Alex Korobka
*/
/*
* Theory:
*
* http://www.microsoft.com/win32dev/ui/icons.htm
*
* Cursors and icons are stored in a global heap block, with the
* following layout:
*
* CURSORICONINFO info;
* BYTE[] ANDbits;
* BYTE[] XORbits;
*
* The bits structures are in the format of a device-dependent bitmap.
*
* This layout is very sub-optimal, as the bitmap bits are stored in
* the X client instead of in the server like other bitmaps; however,
* some programs (notably Paint Brush) expect to be able to manipulate
* the bits directly :-(
*/
#include <string.h>
#include <stdlib.h>
#include "heap.h"
#include "windows.h"
#include "peexe.h"
#include "color.h"
#include "bitmap.h"
#include "callback.h"
#include "cursoricon.h"
#include "sysmetrics.h"
#include "module.h"
#include "win.h"
#include "debug.h"
#include "task.h"
#include "user.h"
#include "keyboard.h"
#include "x11drv.h"
#include "winerror.h"
Cursor CURSORICON_XCursor = None; /* Current X cursor */
static HCURSOR32 hActiveCursor = 0; /* Active cursor */
static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
/**********************************************************************
* CURSORICON_FindBestIcon
*
* Find the icon closest to the requested size and number of colors.
*/
static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
int height, int colors )
{
int i, maxcolors, maxwidth, maxheight;
ICONDIRENTRY *entry, *bestEntry = NULL;
if (dir->idCount < 1)
{
WARN(icon, "Empty directory!\n" );
return NULL;
}
if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
/* First find the exact size with less colors */
maxcolors = 0;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth == width) && (entry->bHeight == height) &&
(entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
{
bestEntry = entry;
maxcolors = entry->bColorCount;
}
if (bestEntry) return bestEntry;
/* First find the exact size with more colors */
maxcolors = 255;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth == width) && (entry->bHeight == height) &&
(entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
{
bestEntry = entry;
maxcolors = entry->bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a smaller one with less colors */
maxcolors = maxwidth = maxheight = 0;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
(entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
(entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
{
bestEntry = entry;
maxwidth = entry->bWidth;
maxheight = entry->bHeight;
maxcolors = entry->bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a smaller one with more colors */
maxcolors = 255;
maxwidth = maxheight = 0;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
(entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
(entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
{
bestEntry = entry;
maxwidth = entry->bWidth;
maxheight = entry->bHeight;
maxcolors = entry->bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a larger one with less colors */
maxcolors = 0;
maxwidth = maxheight = 255;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
(entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
{
bestEntry = entry;
maxwidth = entry->bWidth;
maxheight = entry->bHeight;
maxcolors = entry->bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a larger one with more colors */
maxcolors = maxwidth = maxheight = 255;
for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
(entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
{
bestEntry = entry;
maxwidth = entry->bWidth;
maxheight = entry->bHeight;
maxcolors = entry->bColorCount;
}
return bestEntry;
}
/**********************************************************************
* CURSORICON_FindBestCursor
*
* Find the cursor closest to the requested size.
*/
static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
int width, int height )
{
int i, maxwidth, maxheight;
CURSORDIRENTRY *entry, *bestEntry = NULL;
if (dir->idCount < 1)
{
WARN(cursor, "Empty directory!\n" );
return NULL;
}
if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
/* First find the largest one smaller than or equal to the requested size*/
maxwidth = maxheight = 0;
for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
(entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
{
bestEntry = entry;
maxwidth = entry->wWidth;
maxheight = entry->wHeight;
}
if (bestEntry) return bestEntry;
/* Now find the smallest one larger than the requested size */
maxwidth = maxheight = 255;
for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
{
bestEntry = entry;
maxwidth = entry->wWidth;
maxheight = entry->wHeight;
}
return bestEntry;
}
/**********************************************************************
* CURSORICON_LoadDirEntry16
*
* Load the icon/cursor directory for a given resource name and find the
* best matching entry.
*/
static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
INT32 width, INT32 height, INT32 colors,
BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
{
HRSRC16 hRsrc;
HGLOBAL16 hMem;
CURSORICONDIR *dir;
CURSORICONDIRENTRY *entry = NULL;
if (!(hRsrc = FindResource16( hInstance, name,
fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
return FALSE;
if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
{
if (fCursor)
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
width, height );
else
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
width, height, colors );
if (entry) *dirEntry = *entry;
}
FreeResource16( hMem );
return (entry != NULL);
}
/**********************************************************************
* CURSORICON_LoadDirEntry32
*
* Load the icon/cursor directory for a given resource name and find the
* best matching entry.
*/
static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
INT32 width, INT32 height, INT32 colors,
BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
{
HANDLE32 hRsrc;
HANDLE32 hMem;
CURSORICONDIR *dir;
CURSORICONDIRENTRY *entry = NULL;
if (!(hRsrc = FindResource32W( hInstance, name,
fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
return FALSE;
if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
{
if (fCursor)
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
width, height );
else
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
width, height, colors );
if (entry) *dirEntry = *entry;
}
FreeResource32( hMem );
return (entry != NULL);
}
/**********************************************************************
* CURSORICON_CreateFromResource
*
* Create a cursor or icon from in-memory resource template.
*
* FIXME: Adjust icon size when width and height are nonzero (stretchblt).
* Convert to mono when cFlag is LR_MONOCHROME. Do something
* with cbSize parameter as well.
*/
static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
INT32 width, INT32 height, UINT32 cFlag )
{
int sizeAnd, sizeXor;
HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
BITMAPOBJ *bmpXor, *bmpAnd;
POINT16 hotspot = { 0 ,0 };
BITMAPINFO *bmi;
HDC32 hdc;
TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
(unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
if (dwVersion == 0x00020000)
{
FIXME(cursor,"\t2.xx resources are not supported\n");
return 0;
}
if (bIcon)
bmi = (BITMAPINFO *)bits;
else /* get the hotspot */
{
POINT16 *pt = (POINT16 *)bits;
hotspot = *pt;
bmi = (BITMAPINFO *)(pt + 1);
}
/* 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( (hdc = GetDC32( 0 )) )
{
BITMAPINFO* pInfo;
INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
/* Make sure we have room for the monochrome bitmap later on.
* Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
* up to and including the biBitCount. In-memory icon resource
* format is as follows:
*
* BITMAPINFOHEADER icHeader // DIB header
* RGBQUAD icColors[] // Color table
* BYTE icXOR[] // DIB bits for XOR mask
* BYTE icAND[] // DIB bits for AND mask
*/
if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
{
memcpy( pInfo, bmi, size );
pInfo->bmiHeader.biHeight /= 2;
/* Create the XOR bitmap */
hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
(char*)bmi + size, pInfo, DIB_RGB_COLORS );
if( hXorBits )
{
char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
bmi->bmiHeader.biBitCount) / 2;
pInfo->bmiHeader.biBitCount = 1;
if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
{
RGBQUAD *rgb = pInfo->bmiColors;
pInfo->bmiHeader.biClrUsed = pInfo->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 *)pInfo) + 1);
rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
}
/* Create the AND bitmap */
hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
bits, pInfo, DIB_RGB_COLORS );
if( !hAndBits ) DeleteObject32( hXorBits );
}
HeapFree( GetProcessHeap(), 0, pInfo );
}
ReleaseDC32( 0, hdc );
}
if( !hXorBits || !hAndBits )
{
WARN(cursor,"\tunable to create an icon bitmap.\n");
return 0;
}
/* Now create the CURSORICONINFO structure */
bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
if (hObj) hObj = GlobalReAlloc16( hObj,
sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
if (hObj)
{
CURSORICONINFO *info;
/* Make it owned by the module */
if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
info = (CURSORICONINFO *)GlobalLock16( hObj );
info->ptHotSpot.x = hotspot.x;
info->ptHotSpot.y = hotspot.y;
info->nWidth = bmpXor->bitmap.bmWidth;
info->nHeight = bmpXor->bitmap.bmHeight;
info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
info->bPlanes = bmpXor->bitmap.bmPlanes;
info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
/* Transfer the bitmap bits to the CURSORICONINFO structure */
GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
GlobalUnlock16( hObj );
}
DeleteObject32( hXorBits );
DeleteObject32( hAndBits );
return hObj;
}
/**********************************************************************
* CreateIconFromResourceEx16 (USER.450)
*
* FIXME: not sure about exact parameter types
*/
HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
{
TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
if( pTask )
return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
width, height, cFlag );
return 0;
}
/**********************************************************************
* CreateIconFromResource (USER32.76)
* FIXME:
* bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
* showed only blank layout. Couldn't determine if this is a problem
* with CreateIconFromResource32 or the application. The application
* windows behaves strange (no redraw) before CreateIconFromResource32
*/
HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
BOOL32 bIcon, DWORD dwVersion)
{
HICON32 ret;
ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
FIXME(icon,"probably only a stub\n");
TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
(bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
return ret;
}
/**********************************************************************
* CreateIconFromResourceEx32 (USER32.77)
*/
HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
BOOL32 bIcon, DWORD dwVersion,
INT32 width, INT32 height,
UINT32 cFlag )
{
return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
}
/**********************************************************************
* CURSORICON_Load16
*
* Load a cursor or icon from a 16-bit resource.
*/
static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
INT32 width, INT32 height, INT32 colors,
BOOL32 fCursor )
{
HGLOBAL16 handle;
HRSRC16 hRsrc;
CURSORICONDIRENTRY dirEntry;
if (!hInstance) /* OEM cursor/icon */
{
if (HIWORD(name)) /* Check for '#xxx' name */
{
char *ptr = PTR_SEG_TO_LIN( name );
if (ptr[0] != '#') return 0;
if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
}
return OBM_LoadCursorIcon( LOWORD(name), fCursor );
}
/* Find the best entry in the directory */
if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
colors, fCursor, &dirEntry ) ) return 0;
/* Load the resource */
if ( (hRsrc = FindResource16( hInstance,
MAKEINTRESOURCE16( dirEntry.icon.wResId ),
fCursor ? RT_CURSOR16 : RT_ICON16 )) )
{
/* 16-bit icon or cursor resources are processed
* transparently by the LoadResource16() via custom
* resource handlers set by SetResourceHandler().
*/
if ( (handle = LoadResource16( hInstance, hRsrc )) )
return handle;
}
return 0;
}
/**********************************************************************
* CURSORICON_Load32
*
* Load a cursor or icon from a 32-bit resource.
*/
static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
int width, int height, int colors,
BOOL32 fCursor )
{
HANDLE32 handle;
HANDLE32 hRsrc;
CURSORICONDIRENTRY dirEntry;
if(!hInstance) /* OEM cursor/icon */
{
WORD resid;
if(HIWORD(name))
{
LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
if( ansi[0]=='#') /*Check for '#xxx' name */
{
resid = atoi(ansi+1);
HeapFree( GetProcessHeap(), 0, ansi );
}
else
{
HeapFree( GetProcessHeap(), 0, ansi );
return 0;
}
}
else resid = LOWORD(name);
return OBM_LoadCursorIcon(resid, fCursor);
}
/* Find the best entry in the directory */
if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
colors, fCursor, &dirEntry ) ) return 0;
/* Load the resource */
if ( (hRsrc = FindResource32W( hInstance,
MAKEINTRESOURCE32W( dirEntry.icon.wResId ),
fCursor ? RT_CURSOR32W : RT_ICON32W )) )
{
HANDLE32 h = 0;
if ( (handle = LoadResource32( hInstance, hRsrc )) )
{
/* Hack to keep LoadCursor/Icon32() from spawning multiple
* copies of the same object.
*/
#define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
if( !pRsrcEntry->ResourceHandle )
{
LPBYTE bits = (LPBYTE)LockResource32( handle );
h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
!fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
pRsrcEntry->ResourceHandle = h;
}
else h = pRsrcEntry->ResourceHandle;
#undef pRsrcEntry
}
return h;
}
return 0;
}
/***********************************************************************
* CURSORICON_Copy
*
* Make a copy of a cursor or icon.
*/
static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
{
char *ptrOld, *ptrNew;
int size;
HGLOBAL16 hNew;
if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
if (!(hInstance = GetExePtr( hInstance ))) return 0;
size = GlobalSize16( handle );
hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
FarSetOwner( hNew, hInstance );
ptrNew = (char *)GlobalLock16( hNew );
memcpy( ptrNew, ptrOld, size );
GlobalUnlock16( handle );
GlobalUnlock16( hNew );
return hNew;
}
/***********************************************************************
* CURSORICON_IconToCursor
*
* Converts bitmap to mono and truncates if icon is too large (should
* probably do StretchBlt() instead).
*/
HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
{
HCURSOR16 hRet = 0;
CURSORICONINFO *pIcon = NULL;
HTASK16 hTask = GetCurrentTask();
TDB* pTask = (TDB *)GlobalLock16(hTask);
if(hIcon && pTask)
if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
else
{
BYTE pAndBits[128];
BYTE pXorBits[128];
int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
BYTE* psPtr, *pxbPtr = pXorBits;
unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
BYTE* pbc = NULL;
COLORREF col;
CURSORICONINFO cI;
TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
memset(pXorBits, 0, 128);
cI.bBitsPerPixel = 1; cI.bPlanes = 1;
cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
cI.nWidth = 32; cI.nHeight = 32;
cI.nWidthBytes = 4; /* 32x1bpp */
maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
for( iy = 0; iy < maxy; iy++ )
{
unsigned shift = iy % 2;
memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
(and_width > 4) ? 4 : and_width );
for( ix = 0; ix < maxx; ix++ )
{
if( bSemiTransparent && ((ix+shift)%2) )
{
/* set AND bit, XOR bit stays 0 */
pbc = pAndBits + iy * 4 + ix/8;
*pbc |= 0x80 >> (ix%8);
}
else
{
/* keep AND bit, set XOR bit */
unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
col = COLOR_ToLogical(val);
if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
{
pbc = pxbPtr + ix/8;
*pbc |= 0x80 >> (ix%8);
}
}
}
psPtr += xor_width;
pxbPtr += 4;
}
hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
if( !hRet ) /* fall back on default drag cursor */
hRet = CURSORICON_Copy( pTask->hInstance ,
CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
}
return hRet;
}
/***********************************************************************
* LoadCursor16 (USER.173)
*/
HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
{
if (HIWORD(name))
TRACE(cursor, "%04x '%s'\n",
hInstance, (char *)PTR_SEG_TO_LIN( name ) );
else
TRACE(cursor, "%04x %04x\n",
hInstance, LOWORD(name) );
return CURSORICON_Load16( hInstance, name,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
}
/***********************************************************************
* LoadIcon16 (USER.174)
*/
HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
{
if (HIWORD(name))
TRACE(icon, "%04x '%s'\n",
hInstance, (char *)PTR_SEG_TO_LIN( name ) );
else
TRACE(icon, "%04x %04x\n",
hInstance, LOWORD(name) );
return CURSORICON_Load16( hInstance, name,
SYSMETRICS_CXICON, SYSMETRICS_CYICON,
MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
}
/***********************************************************************
* CreateCursor16 (USER.406)
*/
HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
INT16 xHotSpot, INT16 yHotSpot,
INT16 nWidth, INT16 nHeight,
LPCVOID lpANDbits, LPCVOID lpXORbits )
{
CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
}
/***********************************************************************
* CreateCursor32 (USER32.67)
*/
HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
INT32 xHotSpot, INT32 yHotSpot,
INT32 nWidth, INT32 nHeight,
LPCVOID lpANDbits, LPCVOID lpXORbits )
{
CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
}
/***********************************************************************
* CreateIcon16 (USER.407)
*/
HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
LPCVOID lpANDbits, LPCVOID lpXORbits )
{
CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
}
/***********************************************************************
* CreateIcon32 (USER32.75)
*/
HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
LPCVOID lpANDbits, LPCVOID lpXORbits )
{
CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
}
/***********************************************************************
* CreateCursorIconIndirect (USER.408)
*/
HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
CURSORICONINFO *info,
LPCVOID lpANDbits,
LPCVOID lpXORbits )
{
HGLOBAL16 handle;
char *ptr;
int sizeAnd, sizeXor;
hInstance = GetExePtr( hInstance ); /* Make it a module handle */
if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
sizeXor = info->nHeight * info->nWidthBytes;
sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
return 0;
if (hInstance) FarSetOwner( handle, hInstance );
ptr = (char *)GlobalLock16( handle );
memcpy( ptr, info, sizeof(*info) );
memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
GlobalUnlock16( handle );
return handle;
}
/***********************************************************************
* CopyIcon16 (USER.368)
*/
HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
{
TRACE(icon, "%04x %04x\n", hInstance, hIcon );
return CURSORICON_Copy( hInstance, hIcon );
}
/***********************************************************************
* CopyIcon32 (USER32.60)
*/
HICON32 WINAPI CopyIcon32( HICON32 hIcon )
{
HTASK16 hTask = GetCurrentTask ();
TDB* pTask = (TDB *) GlobalLock16 (hTask);
TRACE(icon, "%04x\n", hIcon );
return CURSORICON_Copy( pTask->hInstance, hIcon );
}
/***********************************************************************
* CopyCursor16 (USER.369)
*/
HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
{
TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
return CURSORICON_Copy( hInstance, hCursor );
}
/***********************************************************************
* DestroyIcon16 (USER.457)
*/
BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
{
return DestroyIcon32( hIcon );
}
/***********************************************************************
* DestroyIcon32 (USER32.133)
*/
BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
{
TRACE(icon, "%04x\n", hIcon );
/* FIXME: should check for OEM icon here */
return (FreeResource16( hIcon ) == 0);
}
/***********************************************************************
* DestroyCursor16 (USER.458)
*/
BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
{
return DestroyCursor32( hCursor );
}
/***********************************************************************
* DestroyCursor32 (USER32.132)
*/
BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
{
TRACE(cursor, "%04x\n", hCursor );
/* FIXME: should check for OEM cursor here */
return (FreeResource16( hCursor ) == 0);
}
/***********************************************************************
* DrawIcon16 (USER.84)
*/
BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
{
return DrawIcon32( hdc, x, y, hIcon );
}
/***********************************************************************
* DrawIcon32 (USER32.159)
*/
BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
{
CURSORICONINFO *ptr;
HDC32 hMemDC;
HBITMAP32 hXorBits, hAndBits;
COLORREF oldFg, oldBg;
if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
(char *)(ptr+1) );
hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
ptr->bBitsPerPixel, (char *)(ptr + 1)
+ ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
oldFg = SetTextColor32( hdc, RGB(0,0,0) );
oldBg = SetBkColor32( hdc, RGB(255,255,255) );
if (hXorBits && hAndBits)
{
HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
SelectObject32( hMemDC, hXorBits );
BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
SelectObject32( hMemDC, hBitTemp );
}
DeleteDC32( hMemDC );
if (hXorBits) DeleteObject32( hXorBits );
if (hAndBits) DeleteObject32( hAndBits );
GlobalUnlock16( hIcon );
SetTextColor32( hdc, oldFg );
SetBkColor32( hdc, oldBg );
return TRUE;
}
/***********************************************************************
* DumpIcon (USER.459)
*/
DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
SEGPTR *lpXorBits, SEGPTR *lpAndBits )
{
CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
int sizeAnd, sizeXor;
if (!info) return 0;
sizeXor = info->nHeight * info->nWidthBytes;
sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
return MAKELONG( sizeXor, sizeXor );
}
/***********************************************************************
* CURSORICON_SetCursor
*
* Change the X cursor. Helper function for SetCursor() and ShowCursor().
* The Xlib critical section must be entered before calling this function.
*/
static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
{
Pixmap pixmapBits, pixmapMask, pixmapAll;
XColor fg, bg;
Cursor cursor = None;
if (!hCursor) /* Create an empty cursor */
{
static const char data[] = { 0 };
bg.red = bg.green = bg.blue = 0x0000;
pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
if (pixmapBits)
{
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
&bg, &bg, 0, 0 );
XFreePixmap( display, pixmapBits );
}
}
else /* Create the X cursor from the bits */
{
CURSORICONINFO *ptr;
XImage *image;
if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
{
WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
return FALSE;
}
/* Create a pixmap and transfer all the bits to it */
/* NOTE: Following hack works, but only because XFree depth
* 1 images really use 1 bit/pixel (and so the same layout
* as the Windows cursor data). Perhaps use a more generic
* algorithm here.
*/
pixmapAll = XCreatePixmap( display, rootWindow,
ptr->nWidth, ptr->nHeight * 2, 1 );
image = XCreateImage( display, DefaultVisualOfScreen(screen),
1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
ptr->nHeight * 2, 16, ptr->nWidthBytes);
if (image)
{
image->byte_order = MSBFirst;
image->bitmap_bit_order = MSBFirst;
image->bitmap_unit = 16;
_XInitImageFuncPtrs(image);
if (pixmapAll)
XPutImage( display, pixmapAll, BITMAP_monoGC, image,
0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
image->data = NULL;
XDestroyImage( image );
}
/* Now create the 2 pixmaps for bits and mask */
pixmapBits = XCreatePixmap( display, rootWindow,
ptr->nWidth, ptr->nHeight, 1 );
pixmapMask = XCreatePixmap( display, rootWindow,
ptr->nWidth, ptr->nHeight, 1 );
/* Make sure everything went OK so far */
if (pixmapBits && pixmapMask && pixmapAll)
{
/* We have to do some magic here, as cursors are not fully
* compatible between Windows and X11. Under X11, there
* are only 3 possible color cursor: black, white and
* masked. So we map the 4th Windows color (invert the
* bits on the screen) to black. This require some boolean
* arithmetic:
*
* Windows | X11
* Xor And Result | Bits Mask Result
* 0 0 black | 0 1 background
* 0 1 no change | X 0 no change
* 1 0 white | 1 1 foreground
* 1 1 inverted | 0 1 background
*
* which gives:
* Bits = 'Xor' and not 'And'
* Mask = 'Xor' or not 'And'
*
* FIXME: apparently some servers do support 'inverted' color.
* I don't know if it's correct per the X spec, but maybe
* we ought to take advantage of it. -- AJ
*/
XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, BITMAP_monoGC, GXandReverse );
XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, BITMAP_monoGC, GXorReverse );
XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, BITMAP_monoGC, GXcopy );
fg.red = fg.green = fg.blue = 0xffff;
bg.red = bg.green = bg.blue = 0x0000;
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
&fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
}
/* Now free everything */
if (pixmapAll) XFreePixmap( display, pixmapAll );
if (pixmapBits) XFreePixmap( display, pixmapBits );
if (pixmapMask) XFreePixmap( display, pixmapMask );
GlobalUnlock16( hCursor );
}
if (cursor == None) return FALSE;
if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
CURSORICON_XCursor = cursor;
if (rootWindow != DefaultRootWindow(display))
{
/* Set the cursor on the desktop window */
XDefineCursor( display, rootWindow, cursor );
}
else
{
/* Set the same cursor for all top-level windows */
HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
while(hwnd)
{
Window win = WIN_GetXWindow( hwnd );
if (win && win!=DefaultRootWindow(display))
XDefineCursor( display, win, cursor );
hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
}
}
return TRUE;
}
/***********************************************************************
* SetCursor16 (USER.69)
*/
HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
{
return (HCURSOR16)SetCursor32( hCursor );
}
/***********************************************************************
* SetCursor32 (USER32.472)
* RETURNS:
* A handle to the previous cursor shape.
*/
HCURSOR32 WINAPI SetCursor32(
HCURSOR32 hCursor /* Handle of cursor to show */
) {
HCURSOR32 hOldCursor;
if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
TRACE(cursor, "%04x\n", hCursor );
hOldCursor = hActiveCursor;
hActiveCursor = hCursor;
/* Change the cursor shape only if it is visible */
if (CURSOR_ShowCount >= 0)
{
EnterCriticalSection( &X11DRV_CritSection );
CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
LeaveCriticalSection( &X11DRV_CritSection );
}
return hOldCursor;
}
/***********************************************************************
* SetCursorPos16 (USER.70)
*/
void WINAPI SetCursorPos16( INT16 x, INT16 y )
{
SetCursorPos32( x, y );
}
/***********************************************************************
* SetCursorPos32 (USER32.474)
*/
BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
{
TRACE(cursor, "x=%d y=%d\n", x, y );
TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
return TRUE;
}
/***********************************************************************
* ShowCursor16 (USER.71)
*/
INT16 WINAPI ShowCursor16( BOOL16 bShow )
{
return ShowCursor32( bShow );
}
/***********************************************************************
* ShowCursor32 (USER32.530)
*/
INT32 WINAPI ShowCursor32( BOOL32 bShow )
{
TRACE(cursor, "%d, count=%d\n",
bShow, CURSOR_ShowCount );
EnterCriticalSection( &X11DRV_CritSection );
if (bShow)
{
if (++CURSOR_ShowCount == 0) /* Show it */
CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
}
else
{
if (--CURSOR_ShowCount == -1) /* Hide it */
CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
}
LeaveCriticalSection( &X11DRV_CritSection );
return CURSOR_ShowCount;
}
/***********************************************************************
* GetCursor16 (USER.247)
*/
HCURSOR16 WINAPI GetCursor16(void)
{
return hActiveCursor;
}
/***********************************************************************
* GetCursor32 (USER32.227)
*/
HCURSOR32 WINAPI GetCursor32(void)
{
return hActiveCursor;
}
/***********************************************************************
* ClipCursor16 (USER.16)
*/
BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
{
if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
return TRUE;
}
/***********************************************************************
* ClipCursor32 (USER32.53)
*/
BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
{
if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
else CopyRect32( &CURSOR_ClipRect, rect );
return TRUE;
}
/***********************************************************************
* GetCursorPos16 (USER.17)
*/
void WINAPI GetCursorPos16( POINT16 *pt )
{
Window root, child;
int rootX, rootY, childX, childY;
unsigned int mousebut;
if (!pt) return;
if (!TSXQueryPointer( display, rootWindow, &root, &child,
&rootX, &rootY, &childX, &childY, &mousebut ))
pt->x = pt->y = 0;
else
{
pt->x = childX;
pt->y = childY;
if (mousebut & Button1Mask)
AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
else
MouseButtonsStates[0] = FALSE;
if (mousebut & Button2Mask)
AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
else
MouseButtonsStates[1] = FALSE;
if (mousebut & Button3Mask)
AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
else
MouseButtonsStates[2] = FALSE;
}
TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
}
/***********************************************************************
* GetCursorPos32 (USER32.229)
*/
void WINAPI GetCursorPos32( POINT32 *pt )
{
POINT16 pt16;
GetCursorPos16( &pt16 );
if (pt) CONV_POINT16TO32( &pt16, pt );
}
/***********************************************************************
* GetClipCursor16 (USER.309)
*/
void WINAPI GetClipCursor16( RECT16 *rect )
{
if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
}
/***********************************************************************
* GetClipCursor32 (USER32.221)
*/
void WINAPI GetClipCursor32( RECT32 *rect )
{
if (rect) CopyRect32( rect, &CURSOR_ClipRect );
}
/**********************************************************************
* LookupIconIdFromDirectoryEx16 (USER.364)
*
* FIXME: exact parameter sizes
*/
INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
INT16 width, INT16 height, UINT16 cFlag )
{
CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
UINT16 retVal = 0;
if( dir && !dir->idReserved && (dir->idType & 3) )
{
int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
if( bIcon )
{
ICONDIRENTRY* entry;
entry = CURSORICON_FindBestIcon( dir, width, height, colors );
if( entry ) retVal = entry->wResId;
}
else
{
CURSORDIRENTRY* entry;
entry = CURSORICON_FindBestCursor( dir, width, height );
if( entry ) retVal = entry->wResId;
}
}
else WARN(cursor, "invalid resource directory\n");
return retVal;
}
/**********************************************************************
* LookupIconIdFromDirectoryEx32 (USER32.380)
*/
INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
INT32 width, INT32 height, UINT32 cFlag )
{
return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
}
/**********************************************************************
* LookupIconIdFromDirectory (USER.???)
*/
INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
{
return LookupIconIdFromDirectoryEx16( dir, bIcon,
bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
}
/**********************************************************************
* LookupIconIdFromDirectory (USER32.379)
*/
INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
{
return LookupIconIdFromDirectoryEx32( dir, bIcon,
bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
}
/**********************************************************************
* GetIconID (USER.455)
*/
WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
{
LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
TRACE(cursor, "hRes=%04x, entries=%i\n",
hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
switch(resType)
{
case RT_CURSOR16:
return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
case RT_ICON16:
return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
default:
WARN(cursor, "invalid res type %ld\n", resType );
}
return 0;
}
/**********************************************************************
* LoadCursorIconHandler (USER.336)
*
* Supposed to load resources of Windows 2.x applications.
*/
HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
{
FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
hResource, hModule, hRsrc);
return (HGLOBAL16)0;
}
/**********************************************************************
* LoadDIBIconHandler (USER.357)
*
* RT_ICON resource loader, installed by USER_SignalProc when module
* is initialized.
*/
HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
{
/* If hResource is zero we must allocate a new memory block, if it's
* non-zero but GlobalLock() returns NULL then it was discarded and
* we have to recommit some memory, otherwise we just need to check
* the block size. See LoadProc() in 16-bit SDK for more.
*/
hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
if( hMemObj )
{
LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
}
return hMemObj;
}
/**********************************************************************
* LoadDIBCursorHandler (USER.356)
*
* RT_CURSOR resource loader. Same as above.
*/
HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
{
hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
if( hMemObj )
{
LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
}
return hMemObj;
}
/**********************************************************************
* LoadIconHandler (USER.456)
*/
HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
{
LPBYTE bits = (LPBYTE)LockResource16( hResource );
TRACE(cursor,"hRes=%04x\n",hResource);
return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
}
/***********************************************************************
* LoadCursorW (USER32.362)
*/
HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
{
return CURSORICON_Load32( hInstance, name,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
}
/***********************************************************************
* LoadCursorA (USER32.359)
*/
HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
{
HCURSOR32 res=0;
if(!HIWORD(name))
return LoadCursor32W(hInstance,(LPCWSTR)name);
else
{
LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
res = LoadCursor32W(hInstance, uni);
HeapFree( GetProcessHeap(), 0, uni);
}
return res;
}
/***********************************************************************
* LoadCursorFromFile32W (USER32.361)
*/
HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
{ FIXME(cursor, ":stub LoadCursorFromFile32W\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/***********************************************************************
* LoadCursorFromFile32A (USER32.360)
*/
HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
{ FIXME(cursor, ":stub LoadCursorFromFile32A %s\n", name);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/***********************************************************************
* LoadIconW (USER32.364)
*/
HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
{
return CURSORICON_Load32( hInstance, name,
SYSMETRICS_CXICON, SYSMETRICS_CYICON,
MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
}
/***********************************************************************
* LoadIconA (USER32.363)
*/
HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
{
HICON32 res=0;
if( !HIWORD(name) )
return LoadIcon32W(hInstance, (LPCWSTR)name);
else
{
LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
res = LoadIcon32W( hInstance, uni );
HeapFree( GetProcessHeap(), 0, uni );
}
return res;
}
/**********************************************************************
* GetIconInfo (USER32.242)
*/
BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
CURSORICONINFO *ciconinfo;
ciconinfo = GlobalLock16(hIcon);
if (!ciconinfo)
return FALSE;
iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
iconinfo->fIcon = TRUE; /* hmm */
/* FIXME ... add both bitmaps */
return TRUE;
}
/**********************************************************************
* CreateIconIndirect (USER32.78)
*/
HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
BITMAPOBJ *bmpXor,*bmpAnd;
HICON32 hObj;
int sizeXor,sizeAnd;
bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
hObj = GlobalAlloc16( GMEM_MOVEABLE,
sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
if (hObj)
{
CURSORICONINFO *info;
info = (CURSORICONINFO *)GlobalLock16( hObj );
info->ptHotSpot.x = iconinfo->xHotspot;
info->ptHotSpot.y = iconinfo->yHotspot;
info->nWidth = bmpXor->bitmap.bmWidth;
info->nHeight = bmpXor->bitmap.bmHeight;
info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
info->bPlanes = bmpXor->bitmap.bmPlanes;
info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
/* Transfer the bitmap bits to the CURSORICONINFO structure */
GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
GlobalUnlock16( hObj );
}
return hObj;
}
/**********************************************************************
* DrawIconEx16 (USER.394)
*/
BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
INT16 cxWidth, INT16 cyWidth, UINT16 istep,
HBRUSH16 hbr, UINT16 flags)
{
return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
istep, hbr, flags);
}
/******************************************************************************
* DrawIconEx32 [USER32.160] 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
*/
BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
INT32 cxWidth, INT32 cyWidth, UINT32 istep,
HBRUSH32 hbr, UINT32 flags )
{
CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
HDC32 hMemDC = CreateCompatibleDC32 (hdc);
BOOL32 result = FALSE;
if (istep)
FIXME(icon, "Ignoring istep=%d\n", istep);
if (hbr)
FIXME(icon, "Ignoring hbr=%x\n", hbr);
if (flags & DI_COMPAT)
FIXME(icon, "Ignoring flag DI_COMPAT\n");
if (hMemDC && ptr)
{
HBITMAP32 hXorBits, hAndBits;
COLORREF oldFg, oldBg;
INT32 nStretchMode;
/* Calculate the size of the destination image. */
if (cxWidth == 0)
if (flags & DI_DEFAULTSIZE)
cxWidth = GetSystemMetrics32 (SM_CXICON);
else
cxWidth = ptr->nWidth;
if (cyWidth == 0)
if (flags & DI_DEFAULTSIZE)
cyWidth = GetSystemMetrics32 (SM_CYICON);
else
cyWidth = ptr->nHeight;
nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
ptr->bPlanes, ptr->bBitsPerPixel,
(char *)(ptr + 1)
+ ptr->nHeight *
BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1, 1, (char *)(ptr+1) );
oldFg = SetTextColor32( hdc, RGB(0,0,0) );
oldBg = SetBkColor32( hdc, RGB(255,255,255) );
if (hXorBits && hAndBits)
{
HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
if (flags & DI_MASK)
StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
SelectObject32( hMemDC, hXorBits );
if (flags & DI_IMAGE)
StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
SelectObject32( hMemDC, hBitTemp );
result = TRUE;
}
SetTextColor32( hdc, oldFg );
SetBkColor32( hdc, oldBg );
if (hXorBits) DeleteObject32( hXorBits );
if (hAndBits) DeleteObject32( hAndBits );
SetStretchBltMode32 (hdc, nStretchMode);
}
if (hMemDC) DeleteDC32( hMemDC );
GlobalUnlock16( hIcon );
return result;
}