Wed Jan 31 10:58:00 1996 Alexandre Julliard <julliard@sunsite.unc.edu> * [configure.in] Added --with-dll option to build libwine.so. * [controls/listbox.c] Fixed ListBoxDirectory(), DlgDirSelect() and DlgDirList(). Hopefully their behavior is correct now. * [controls/menu.c] Use SEGPTRs in ChangeMenu(), InsertMenu(), AppendMenu() and ModifyMenu() for the item data, to avoid corrupting the pointer for owner-drawn items. * [controls/static.c] Attempt to load OEM icons for SS_ICON controls. Probably not entirely correct. Don't clip the text output. * [files/directory.c] Add temp dir and Windows dir to environment. * [files/dos_fs.c] Fixed a few path handling bugs in DOSFS_GetUnixFileName(). Cache last used directory in DOSFS_FindNext() to avoid quadratic search time. * [files/drive.c] New format for drives configuration in wine.conf; allows specifying the type, label and serial number of a drive. * [files/file.c] New function FILE_OpenUnixFile to make sure we don't open a directory instead of a file. Fixed DOSFS_GetUnixFileName() check_last flag in FILE_MakeDir(). * [files/profile.c] Rewrote profile handling. Should be closer to Windows behavior now. New function PROFILE_GetWineIniString() to get a string from wine.conf. Support environment variables in wine.conf. * [loader/task.c] Fixed the order of deletion in TASK_DeleteTask() to avoid memory corruption. * [memory/global.c] Create a discarded block on GlobalAlloc() if the size is 0; thanks to John Harvey for noticing this. * [memory/local.c] LOCAL_GetHeap: make sure the pointer is valid before checking magic number. * [misc/main.c] Moved profile and registry saving to ExitWindows(), so we don't try to save them in case of a crash. * [miscemu/int21.c] INT21_GetFreeDiskSpace: try to compute the cluster size from the filesystem size instead of hard-coding it to 64. Fixed functions 0x3f and 0x40 to use _hread and _hwrite to allow reading or writing 65535 bytes (thanks to Bruce Milner for this one). * [windows/message.c] Fixed bug in linked-list handling in MSG_DeleteQueue(). Simplified SetMessageQueue(). * [wine.ini] [wine.man] Updated for new drives configuration format. Tue Jan 30 11:24:46 1996 William Magro <wmagro@tc.cornell.edu> * [controls/edit.c] Implemented ES_PASSWORD style, EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR messages. * [controls/widgets.c] Adjusted class creation flags to better match values Windows uses. * [include/windows.h] Fixed ES_NOHIDESEL typo. * [loader/ne_image.c] Added detection for zero offset in RADDR fixups. Quicken was in an infinite loop here. Mon Jan 29 20:12:22 1996 Albrecht Kleine <kleine@ak.sax.de> * [files/dos_fs.c] Bugfix: range error in month value (0..11 set to 1..12). * [windows/caret.c] Changed ROP2-mode to R2_NOTXORPEN in CARET_Callback for pulsed appearance of the caret. * [windows/mdi.c] [include/mdi.h] Changed MDITile(): added a new parameter WORD wParam for WM_MDITILE second tiling method (MDITILE_HORIZONTAL in wParam) as used in Win3.1 Sun Jan 28 14:20:00 1996 Cameron Heide <heide@ee.ualberta.ca> * [miscemu/int2f.c] Added a small bit of MSCDEX emulation. * [windows/alias.c] ALIAS_RegisterAlias was returning the hash value when it should have been returning the record number. Sat Jan 27 10:53:51 1996 Jim Peterson <jspeter@birch.ee.vt.edu> * [include/shell.h] [include/wintypes.h] Moved definition of HKEY and LPHKEY types to include/wintypes.h. Declared FONTENUMPROC in wintypes.h. * [include/windows.h] Added definition of KERNINGPAIR and LPKERNINGPAIR types. Added declarations for CopyCursor(), CopyIcon(), EnumFontFamilies(), ExtractIcon(), FatalAppExit(), FindExecutable(), GetClipCursor(), GetKerningPairs(), GetQueueStatus(), GetRasterizerCaps(), IsGDIObject(), IsMenu(), IsTask(), RegCloseKey(), RegCreateKey(), RegDeleteKey(), RegEnumKey(), RegOpenKey(), RegQueryValue(), RegSetValue(), ResetDC(), ShellExecute(), SystemParametersInfo(), and wsprintf(). * [tools/makehtml.pl] [documentation/apiw.index] New files that scan windows.h, commdlg.h, and toolhelp.h and output an HTML sorted list with optional links to www.willows.com and a tally of unimplemented APIW functions. * [objects/cursoricon.c] Added Win32 versions of CopyIcon() and CopyCursor() for use in libwine. * [win32/resource.c] [win32/winprocs.c] Added '#include "libres.h"' and explicit declarations of windows procs in order to avoid warnings. * [windows/utility.c] Added Win32 version of MulDiv() for libwine. * [*/*] [include/windows.h] Changed several function declarations to comply more strictly to the windows API (without, hopefully, altering their functionality). * [controls/menu.c] Made the return value of CheckMenuItem be the previous state of the menu item if it was found, otherwise -1 as specified in the SDK. This conflicts with the APIW specification, which says it should return TRUE if successful, otherwise FALSE. * [include/windows.h] Added obsolete WM_SIZE message wParam names for compatibility. Added WinHelp() command constants, even though they are not yet supported. * [rc/winerc.c] Tidied up transform_binary_file(). In argument checking, flattened any invalid characters specified with the prefix argument. * [library/libres.c] Made FindResource() case-insensitive when parameter 'name' is a string. Sat Jan 27 02:30 1996 Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de * [files/drive.c] If root "/" is given in wine.conf, use it as last resort. * [files/file.c] Report ER_AccessDenied it disk ist not writable More Debug Output * [miscemu/int21.c] Squeezed some bugs in ExtendedOpenCreateFile * [windows/winpos.c] Some windows may not be moved or resized. We are missing some structures to be exact, but the approach should help in some cases and make things worse in much fewer. Fri Jan 26 10:24:00 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk> * [loader/pe_image.c] fixup_imports: Find builtins for Borland style entries, too Fri Jan 26 10:24:00 1996 Martin von Loewis <loewis@informatik.hu-berlin.de> * [controls/menu.c] LoadMenu: branch to Win32 for PE modules * [if1632/gdi.spec][if1632/kernel32.spec][if1632/user32.spec] DeleteObject, GetPixel, SetPixel,WritePrivateProfileStringA, WriteProfileStringA, EmptyClipboard, EnableMenuItem, EnableScrollBar, EnableWindow, InvalidateRect, SetWindowTextA, WinHelpA: new relays DrawTextA, MoveToEx, GetClientRect, InvalidateRect, LoadBitmapA/W, LoadAcceleratorsA/W, LoadMenu[Indirect]A/W, LoadStringA/W: changed to convert parameters or naming convention * [include/kernel32.h][include/wintypes.h] moved WCHAR, defined LPWSTR * [include/string32.h][win32/string32.c][include/struct32.h] New files * [loader/module.h] LoadModule: exit after returning from PE_LoadModule * [loader/pe_image.c] my_wcstombs: isascii does not work on Linux for Unicode PE_LoadImage: Handle directories * [misc/user32.c] USER32_RECT32to16, USER32_RECT16to32: new functions implemented new user32 relays * [misc/newfns.c] WIN32_WinHelpA: new function * [win32/param32.c] New file * [win32/resource.c] GetResDirEntry: added support for named entries WIN32_LoadAcceleratorsW: invoke *32 resource functions WIN32_LoadBitmapA: convert name to unicode if appropriate WIN32_ParseMenu: new function implemented new resource functions from user32.spec Wed Jan 24 18:09:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu> * [objects/cursoricon.c] GetIconId() and LoadIconHandler() functions. * [windows/mdi.c] Better maximization support, TranslateMDISysAccel() function, misc improvements. * [windows/defwnd.c] Fix for WM_WINDOWPOSCHANGED message handler. * [windows/winpos.c] Rewrote WindowFromPoint() function. Sun Jan 21 1996 17:05:09 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de> * [include/toolhelp.h] [misc/toolhelp.c] Added Notify(Un)Register, but no callbacks yet. Fri Jan 19 01:43:37 1996 Victor Schneider <root@tailor.roman.org> * [Makefile.in] Added target for libwine.so.1.0. * [library/winmain.c] For WINELIBDLL, _WinMain just returns hInstance instead of calling WinMain(). * [misc/main.c] For WINELIBDLL, renamed main() to _wine_main() for calling from the stub main function. * [library/winestub.c] (new file) Provides a stub main() function for using libwine.so. Tue Jan 16 11:04:34 1996 Anand Kumria <akumria@ozemail.com.au> * [winsocket.c] Fix EPERM problem. * [global.c] Attempt to do some sanity checking in MemManInfo(). * [Changelog] Fix changelog oversight for previous entry.
959 lines
31 KiB
C
959 lines
31 KiB
C
/*
|
|
* Cursor and icon support
|
|
*
|
|
* Copyright 1995 Alexandre Julliard
|
|
*/
|
|
|
|
/*
|
|
* Theory:
|
|
*
|
|
* 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 "windows.h"
|
|
#include "bitmap.h"
|
|
#include "callback.h"
|
|
#include "cursoricon.h"
|
|
#include "sysmetrics.h"
|
|
#include "win.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
#include "xmalloc.h"
|
|
#include "task.h"
|
|
|
|
|
|
Cursor CURSORICON_XCursor = None; /* Current X cursor */
|
|
static HCURSOR hActiveCursor = 0; /* Active cursor */
|
|
static int CURSOR_ShowCount = 0; /* Cursor display count */
|
|
static RECT 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)
|
|
{
|
|
fprintf( stderr, "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)
|
|
{
|
|
fprintf( stderr, "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_LoadDirEntry
|
|
*
|
|
* Load the icon/cursor directory for a given resource name and find the
|
|
* best matching entry.
|
|
*/
|
|
static BOOL CURSORICON_LoadDirEntry(HANDLE hInstance, SEGPTR name,
|
|
int width, int height, int colors,
|
|
BOOL fCursor, CURSORICONDIRENTRY *dirEntry)
|
|
{
|
|
HRSRC hRsrc;
|
|
HANDLE hMem;
|
|
CURSORICONDIR *dir;
|
|
CURSORICONDIRENTRY *entry = NULL;
|
|
|
|
if (!(hRsrc = FindResource( hInstance, name,
|
|
fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON )))
|
|
return FALSE;
|
|
if (!(hMem = LoadResource( hInstance, hRsrc ))) return FALSE;
|
|
if ((dir = (CURSORICONDIR *)LockResource( hMem )))
|
|
{
|
|
if (fCursor)
|
|
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
|
|
width, height );
|
|
else
|
|
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
|
|
width, height, colors );
|
|
if (entry) *dirEntry = *entry;
|
|
}
|
|
FreeResource( hMem );
|
|
return (entry != NULL);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* CURSORICON_LoadHandler
|
|
*
|
|
* Create a cursor or icon from a resource.
|
|
*/
|
|
static HANDLE CURSORICON_LoadHandler( HANDLE handle, HINSTANCE hInstance,
|
|
BOOL fCursor )
|
|
{
|
|
HANDLE hAndBits, hXorBits;
|
|
HDC hdc;
|
|
int size, sizeAnd, sizeXor;
|
|
POINT hotspot = { 0 ,0 };
|
|
BITMAPOBJ *bmpXor, *bmpAnd;
|
|
BITMAPINFO *bmi, *pInfo;
|
|
CURSORICONINFO *info;
|
|
char *bits;
|
|
|
|
if (fCursor) /* If cursor, get the hotspot */
|
|
{
|
|
POINT *pt = (POINT *)LockResource( handle );
|
|
hotspot = *pt;
|
|
bmi = (BITMAPINFO *)(pt + 1);
|
|
}
|
|
else bmi = (BITMAPINFO *)LockResource( handle );
|
|
|
|
/* Create a copy of the bitmap header */
|
|
|
|
size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
|
|
/* Make sure we have room for the monochrome bitmap later on */
|
|
size = MAX( size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD) );
|
|
pInfo = (BITMAPINFO *)xmalloc( size );
|
|
memcpy( pInfo, bmi, size );
|
|
|
|
if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
|
|
{
|
|
if (pInfo->bmiHeader.biCompression != BI_RGB)
|
|
{
|
|
fprintf(stderr,"Unknown size for compressed icon bitmap.\n");
|
|
free( pInfo );
|
|
return 0;
|
|
}
|
|
pInfo->bmiHeader.biHeight /= 2;
|
|
}
|
|
else if (pInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
|
{
|
|
BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)pInfo;
|
|
core->bcHeight /= 2;
|
|
}
|
|
else
|
|
{
|
|
fprintf( stderr, "CURSORICON_Load: Unknown bitmap length %ld!\n",
|
|
pInfo->bmiHeader.biSize );
|
|
free( pInfo );
|
|
return 0;
|
|
}
|
|
|
|
/* Create the XOR bitmap */
|
|
|
|
if (!(hdc = GetDC( 0 )))
|
|
{
|
|
free( pInfo );
|
|
return 0;
|
|
}
|
|
|
|
hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
|
|
(char*)bmi + size, pInfo, DIB_RGB_COLORS );
|
|
|
|
/* Fix the bitmap header to load the monochrome mask */
|
|
|
|
if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
|
|
{
|
|
BITMAPINFOHEADER *bih = &pInfo->bmiHeader;
|
|
RGBQUAD *rgb = pInfo->bmiColors;
|
|
bits = (char *)bmi + size +
|
|
DIB_GetImageWidthBytes(bih->biWidth,bih->biBitCount)*bih->biHeight;
|
|
bih->biBitCount = 1;
|
|
bih->biClrUsed = bih->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
|
|
{
|
|
BITMAPCOREHEADER *bch = (BITMAPCOREHEADER *)pInfo;
|
|
RGBTRIPLE *rgb = (RGBTRIPLE *)(bch + 1);
|
|
bits = (char *)bmi + size +
|
|
DIB_GetImageWidthBytes(bch->bcWidth,bch->bcBitCount)*bch->bcHeight;
|
|
bch->bcBitCount = 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 = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
|
|
bits, pInfo, DIB_RGB_COLORS );
|
|
ReleaseDC( 0, hdc );
|
|
|
|
/* 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 (!(handle = GlobalAlloc( GMEM_MOVEABLE,
|
|
sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
|
|
{
|
|
DeleteObject( hXorBits );
|
|
DeleteObject( hAndBits );
|
|
return 0;
|
|
}
|
|
|
|
/* Make it owned by the module */
|
|
if (hInstance) FarSetOwner( handle, (WORD)(DWORD)GetExePtr(hInstance) );
|
|
|
|
info = (CURSORICONINFO *)GlobalLock( handle );
|
|
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 */
|
|
|
|
GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
|
|
GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
|
|
DeleteObject( hXorBits );
|
|
DeleteObject( hAndBits );
|
|
GlobalUnlock( handle );
|
|
return handle;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CURSORICON_Load
|
|
*
|
|
* Load a cursor or icon.
|
|
*/
|
|
static HANDLE CURSORICON_Load( HANDLE hInstance, SEGPTR name, int width,
|
|
int height, int colors, BOOL fCursor )
|
|
{
|
|
HANDLE handle,hRet;
|
|
HRSRC 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_LoadDirEntry( hInstance, name, width, height,
|
|
colors, fCursor, &dirEntry )) return 0;
|
|
|
|
/* Load the resource */
|
|
|
|
if (!(hRsrc = FindResource( hInstance,
|
|
MAKEINTRESOURCE( dirEntry.icon.wResId ),
|
|
fCursor ? RT_CURSOR : RT_ICON ))) return 0;
|
|
if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
|
|
|
|
hRet = CURSORICON_LoadHandler( handle, hInstance, fCursor );
|
|
FreeResource(handle);
|
|
return hRet;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CURSORICON_Copy
|
|
*
|
|
* Make a copy of a cursor or icon.
|
|
*/
|
|
static HANDLE CURSORICON_Copy( HANDLE hInstance, HANDLE handle )
|
|
{
|
|
char *ptrOld, *ptrNew;
|
|
int size;
|
|
HANDLE hNew;
|
|
|
|
if (!(ptrOld = (char *)GlobalLock( handle ))) return 0;
|
|
if (!(hInstance = GetExePtr( hInstance ))) return 0;
|
|
size = GlobalSize( handle );
|
|
hNew = GlobalAlloc( GMEM_MOVEABLE, size );
|
|
FarSetOwner( hNew, (WORD)(DWORD)hInstance );
|
|
ptrNew = (char *)GlobalLock( hNew );
|
|
memcpy( ptrNew, ptrOld, size );
|
|
GlobalUnlock( handle );
|
|
GlobalUnlock( hNew );
|
|
return hNew;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CURSORICON_IconToCursor
|
|
*
|
|
* Should convert bitmap to mono and truncate if too large
|
|
* FIXME: if icon is passed returns a copy of OCR_DRAGOBJECT cursor
|
|
* but should actually convert icon to cursor.
|
|
*/
|
|
HCURSOR CURSORICON_IconToCursor(HICON hIcon)
|
|
{
|
|
CURSORICONINFO *ptr = NULL;
|
|
|
|
if(hIcon)
|
|
if (!(ptr = (CURSORICONINFO*)GlobalLock( hIcon ))) return FALSE;
|
|
if (ptr->bPlanes * ptr->bBitsPerPixel == 1)
|
|
{
|
|
return hIcon; /* assuming it's a cursor */
|
|
}
|
|
else
|
|
{
|
|
/* kludge */
|
|
|
|
HTASK hTask = GetCurrentTask();
|
|
TDB* pTask = (TDB *)GlobalLock(hTask);
|
|
|
|
if(!pTask) return 0;
|
|
|
|
fprintf( stdnimp, "IconToCursor: Icons are not supported, returning default!\n");
|
|
return CURSORICON_Copy( pTask->hInstance ,
|
|
CURSORICON_Load(0,MAKEINTRESOURCE(OCR_DRAGOBJECT),
|
|
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* LoadCursor (USER.173)
|
|
*/
|
|
HCURSOR LoadCursor( HANDLE hInstance, SEGPTR name )
|
|
{
|
|
if (HIWORD(name))
|
|
dprintf_cursor( stddeb, "LoadCursor: "NPFMT" '%s'\n",
|
|
hInstance, (char *)PTR_SEG_TO_LIN( name ) );
|
|
else
|
|
dprintf_cursor( stddeb, "LoadCursor: "NPFMT" %04x\n",
|
|
hInstance, LOWORD(name) );
|
|
|
|
return CURSORICON_Load( hInstance, name,
|
|
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LoadIcon (USER.174)
|
|
*/
|
|
HICON LoadIcon( HANDLE hInstance, SEGPTR name )
|
|
{
|
|
if (HIWORD(name))
|
|
dprintf_icon( stddeb, "LoadIcon: "NPFMT" '%s'\n",
|
|
hInstance, (char *)PTR_SEG_TO_LIN( name ) );
|
|
else
|
|
dprintf_icon( stddeb, "LoadIcon: "NPFMT" %04x\n",
|
|
hInstance, LOWORD(name) );
|
|
|
|
return CURSORICON_Load( hInstance, name,
|
|
SYSMETRICS_CXICON, SYSMETRICS_CYICON,
|
|
MIN( 16, 1 << screenDepth ), FALSE );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateCursor (USER.406)
|
|
*/
|
|
HCURSOR CreateCursor( HINSTANCE hInstance, INT xHotSpot, INT yHotSpot,
|
|
INT nWidth, INT nHeight, LPVOID lpANDbits, LPVOID lpXORbits)
|
|
{
|
|
CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
|
|
|
|
dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
|
|
nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
|
|
return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateIcon (USER.407)
|
|
*/
|
|
HICON CreateIcon( HANDLE hInstance, INT nWidth, INT nHeight, BYTE bPlanes,
|
|
BYTE bBitsPixel, LPSTR lpANDbits, LPSTR lpXORbits)
|
|
{
|
|
CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel };
|
|
|
|
dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
|
|
nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
|
|
return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateCursorIconIndirect (USER.408)
|
|
*/
|
|
HANDLE CreateCursorIconIndirect( HANDLE hInstance, CURSORICONINFO *info,
|
|
LPSTR lpANDbits, LPSTR lpXORbits )
|
|
{
|
|
HANDLE handle;
|
|
char *ptr;
|
|
int sizeAnd, sizeXor;
|
|
|
|
hInstance = GetExePtr( hInstance ); /* Make it a module handle */
|
|
if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
|
|
info->nWidthBytes = (info->nWidth * info->bBitsPerPixel + 15) / 16 * 2;
|
|
sizeXor = info->nHeight * info->nWidthBytes;
|
|
sizeAnd = info->nHeight * ((info->nWidth + 15) / 16 * 2);
|
|
if (!(handle = DirectResAlloc(hInstance, 0x10,
|
|
sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
|
|
return 0;
|
|
ptr = (char *)GlobalLock( handle );
|
|
memcpy( ptr, info, sizeof(*info) );
|
|
memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
|
|
memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
|
|
GlobalUnlock( handle );
|
|
return handle;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CopyIcon (USER.368)
|
|
*/
|
|
#ifdef WINELIB32
|
|
HICON CopyIcon( HICON hIcon )
|
|
{
|
|
dprintf_icon( stddeb, "CopyIcon: "NPFMT"\n", hIcon );
|
|
return CURSORICON_Copy( 0, hIcon );
|
|
}
|
|
#else
|
|
HICON CopyIcon( HANDLE hInstance, HICON hIcon )
|
|
{
|
|
dprintf_icon( stddeb, "CopyIcon: "NPFMT" "NPFMT"\n", hInstance, hIcon );
|
|
return CURSORICON_Copy( hInstance, hIcon );
|
|
}
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
* CopyCursor (USER.369)
|
|
*/
|
|
#ifdef WINELIB32
|
|
HCURSOR CopyCursor( HCURSOR hCursor )
|
|
{
|
|
dprintf_cursor( stddeb, "CopyCursor: "NPFMT"\n", hCursor );
|
|
return CURSORICON_Copy( 0, hCursor );
|
|
}
|
|
#else
|
|
HCURSOR CopyCursor( HANDLE hInstance, HCURSOR hCursor )
|
|
{
|
|
dprintf_cursor( stddeb, "CopyCursor: "NPFMT" "NPFMT"\n", hInstance, hCursor );
|
|
return CURSORICON_Copy( hInstance, hCursor );
|
|
}
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
* DestroyIcon (USER.457)
|
|
*/
|
|
BOOL DestroyIcon( HICON hIcon )
|
|
{
|
|
dprintf_icon( stddeb, "DestroyIcon: "NPFMT"\n", hIcon );
|
|
/* FIXME: should check for OEM icon here */
|
|
return (GlobalFree( hIcon ) != 0);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* DestroyCursor (USER.458)
|
|
*/
|
|
BOOL DestroyCursor( HCURSOR hCursor )
|
|
{
|
|
dprintf_cursor( stddeb, "DestroyCursor: "NPFMT"\n", hCursor );
|
|
/* FIXME: should check for OEM cursor here */
|
|
return (GlobalFree( hCursor ) != 0);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* DrawIcon (USER.84)
|
|
*/
|
|
BOOL DrawIcon( HDC hdc, short x, short y, HICON hIcon )
|
|
{
|
|
CURSORICONINFO *ptr;
|
|
HDC hMemDC;
|
|
HBITMAP hXorBits, hAndBits;
|
|
COLORREF oldFg, oldBg;
|
|
|
|
if (!(ptr = (CURSORICONINFO *)GlobalLock( hIcon ))) return FALSE;
|
|
if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
|
|
hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1, (char *)(ptr+1));
|
|
hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
|
|
ptr->bBitsPerPixel, (char *)(ptr + 1)
|
|
+ ptr->nHeight * ((ptr->nWidth + 15) / 16 * 2) );
|
|
oldFg = SetTextColor( hdc, RGB(0,0,0) );
|
|
oldBg = SetBkColor( hdc, RGB(255,255,255) );
|
|
|
|
if (hXorBits && hAndBits)
|
|
{
|
|
HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
|
|
BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
|
|
SelectObject( hMemDC, hXorBits );
|
|
BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCINVERT);
|
|
SelectObject( hMemDC, hBitTemp );
|
|
}
|
|
DeleteDC( hMemDC );
|
|
if (hXorBits) DeleteObject( hXorBits );
|
|
if (hAndBits) DeleteObject( hAndBits );
|
|
GlobalUnlock( hIcon );
|
|
SetTextColor( hdc, oldFg );
|
|
SetBkColor( hdc, oldBg );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* DumpIcon (USER.459)
|
|
*/
|
|
DWORD 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 * ((info->nWidth + 15) / 16 * 2);
|
|
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().
|
|
*/
|
|
static BOOL CURSORICON_SetCursor( HCURSOR 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*)GlobalLock( hCursor ))) return FALSE;
|
|
if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
|
|
{
|
|
fprintf( stderr, "Cursor "NPFMT" has more than 1 bpp!\n", hCursor );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Create a pixmap and transfer all the bits to it */
|
|
|
|
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)
|
|
{
|
|
extern void _XInitImageFuncPtrs( XImage* );
|
|
image->byte_order = MSBFirst;
|
|
image->bitmap_bit_order = MSBFirst;
|
|
image->bitmap_unit = 16;
|
|
_XInitImageFuncPtrs(image);
|
|
if (pixmapAll)
|
|
CallTo32_LargeStack( XPutImage, 10,
|
|
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 );
|
|
GlobalUnlock( 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 */
|
|
HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
|
|
while(hwnd)
|
|
{
|
|
Window win = WIN_GetXWindow( hwnd );
|
|
if (win) XDefineCursor( display, win, cursor );
|
|
hwnd = GetWindow( hwnd, GW_HWNDNEXT );
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetCursor (USER.69)
|
|
*/
|
|
HCURSOR SetCursor( HCURSOR hCursor )
|
|
{
|
|
HCURSOR hOldCursor;
|
|
|
|
if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
|
|
dprintf_cursor( stddeb, "SetCursor: "NPFMT"\n", hCursor );
|
|
hOldCursor = hActiveCursor;
|
|
hActiveCursor = hCursor;
|
|
/* Change the cursor shape only if it is visible */
|
|
if (CURSOR_ShowCount >= 0) CURSORICON_SetCursor( hActiveCursor );
|
|
return hOldCursor;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetCursorPos (USER.70)
|
|
*/
|
|
void SetCursorPos( short x, short y )
|
|
{
|
|
dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
|
|
XWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* ShowCursor (USER.71)
|
|
*/
|
|
int ShowCursor( BOOL bShow )
|
|
{
|
|
dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
|
|
bShow, CURSOR_ShowCount );
|
|
|
|
if (bShow)
|
|
{
|
|
if (++CURSOR_ShowCount == 0)
|
|
CURSORICON_SetCursor( hActiveCursor ); /* Show it */
|
|
}
|
|
else
|
|
{
|
|
if (--CURSOR_ShowCount == -1)
|
|
CURSORICON_SetCursor( 0 ); /* Hide it */
|
|
}
|
|
return CURSOR_ShowCount;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetCursor (USER.247)
|
|
*/
|
|
HCURSOR GetCursor(void)
|
|
{
|
|
return hActiveCursor;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* ClipCursor (USER.16)
|
|
*/
|
|
BOOL ClipCursor( RECT *rect )
|
|
{
|
|
if (!rect) SetRectEmpty( &CURSOR_ClipRect );
|
|
else CopyRect( &CURSOR_ClipRect, rect );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetCursorPos (USER.17)
|
|
*/
|
|
void GetCursorPos( POINT *pt )
|
|
{
|
|
Window root, child;
|
|
int rootX, rootY, childX, childY;
|
|
unsigned int mousebut;
|
|
|
|
if (!pt) return;
|
|
if (!XQueryPointer( display, rootWindow, &root, &child,
|
|
&rootX, &rootY, &childX, &childY, &mousebut ))
|
|
pt->x = pt->y = 0;
|
|
else
|
|
{
|
|
pt->x = rootX + desktopX;
|
|
pt->y = rootY + desktopY;
|
|
}
|
|
dprintf_cursor(stddeb, "GetCursorPos: ret=%ld,%ld\n", (LONG)pt->x,
|
|
(LONG)pt->y );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetClipCursor (USER.309)
|
|
*/
|
|
void GetClipCursor( RECT *rect )
|
|
{
|
|
if (rect) CopyRect( rect, &CURSOR_ClipRect );
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* GetIconID (USER.455)
|
|
*/
|
|
WORD GetIconID( HANDLE hResource, DWORD resType )
|
|
{
|
|
CURSORICONDIR *lpDir = LockResource(hResource);
|
|
|
|
if (!lpDir || lpDir->idReserved ||
|
|
((lpDir->idType != 1) && (lpDir->idType != 2)))
|
|
{
|
|
dprintf_cursor(stddeb,"GetIconID: invalid resource directory\n");
|
|
return 0;
|
|
}
|
|
|
|
dprintf_cursor( stddeb, "GetIconID: hRes="NPFMT", entries=%i\n",
|
|
hResource, lpDir->idCount );
|
|
|
|
switch(resType)
|
|
{
|
|
case 1: /* cursor */
|
|
{
|
|
CURSORDIRENTRY *entry = CURSORICON_FindBestCursor( lpDir,
|
|
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR );
|
|
return entry ? entry->wResId : 0;
|
|
}
|
|
case 3: /* icon */
|
|
{
|
|
ICONDIRENTRY *entry = CURSORICON_FindBestIcon( lpDir,
|
|
SYSMETRICS_CXICON, SYSMETRICS_CYICON,
|
|
MIN( 16, 1 << screenDepth ) );
|
|
return entry ? entry->wResId : 0;
|
|
}
|
|
}
|
|
fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* LoadIconHandler (USER.456)
|
|
*/
|
|
HICON LoadIconHandler( HANDLE hResource, BOOL bNew )
|
|
{
|
|
dprintf_cursor(stddeb,"LoadIconHandler: hRes="NPFMT"\n",hResource);
|
|
|
|
if( !bNew )
|
|
{
|
|
fprintf(stdnimp,"LoadIconHandler: 2.xx resources are not supported\n");
|
|
return 0;
|
|
}
|
|
return CURSORICON_LoadHandler( hResource, 0, FALSE);
|
|
}
|