wine/windows/cursor.c
Alexandre Julliard fa68b75bad Release 950403
Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [Configure] [if1632/Imakefile]
	Removed new build and short names options.

	* [if1632/*.c] [tools/build.c]
	Implemented compiled call-back functions for better performance;
	all the relay code is now done in assembly code generated by the
	build program.
	Relay code is no longer dependent on being loaded below 64K.

	* [loader/resource.c]
	Fixed memory leak in LoadString(). A fix will also be needed for
	other resources.

	* [memory/global.c]
	Implemented global heap arenas, so we can store informations about
	global blocks, like lock counts or owner handle.
	Implemented FarGetOwner() and FarSetOwner().
	Implemented global heap TOOLHELP functions.

	* [memory/selector.c]
	Bug fix: it was not possible to re-use a free selector.

Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)

	*  [controls/listbox.c]
	Major work on listbox code
         - Many bugs fixed (still many bugs)
         - More messages supported
         - Code simplified

Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [controls/edit.c]
	Lots of bug fixes related to diappearing text, lost carets,
	highlighting, segmentation faults, occurance of random
	characters, insertion of characters over selection, misplaced
	caret location, display corruption, end of line behavior, etc.

	* [controls/widgets.c]
	EDIT class doesn't want to use CS_PARENTDC flag.

Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/selector.c]
	  FixupFunctionPrologs() should also handle multiple data modules.
	  (this bug only became visible because MakeProcInstance() was fixed
	  in 950319)
	
	* [misc/dosfs.c]
	  Simplified DOS_SimplifyPath.
	  Small fix to DOS_opendir to reuse an entry if an open directory
	  is opened again, to prevent "too many open directories" messages.

Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
	CoDisconnectObject: new stub function

	* [include/msdos.h]
	fix DOSVERSION

	* [loader/ne_image.c]
	NE_FixupSegment: Be more generous on additive fixups

	* [if1632/user.spec][misc/network.c]
	Add more WNet* stubs

Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	  DlgDirList(): send segptr instead of linear pointer 
	  in message to static control
	* [controls/menu.c]
	  Tried to implement ownerdrawn menuitems. Doesn't work.
	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
	  Provide a stub for GetRasterizerCaps()
	* [loader/selector.c]
	  Pass end address instead of length to LocalInit() in 
	  CreateSelectors()
	* [memory/local.c]
	  LocalInit(): If there's already a local heap in the segment, do
	  nothing and return TRUE
	* [objects/linedda.c]
	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
	  now.
	* [windows/cursor.c]
	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
	  more work still.

Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
	  [windows/nonclient.c] [misc/message.c]
	  Added a new builtin DLL that provides 16 bit entry points for all
	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
	  again.
	* [misc/shell.c]
	  RegOpenKey()/RegCreateKey() bugs fixed.
        * [loader/ne_image.c]
	  Skipping the initialization of a DLL when CS == 0 was broken.
1995-04-03 16:55:37 +00:00

440 lines
13 KiB
C

/*
* WINE
static char Copyright[] = "Copyright Martin Ayotte, 1993";
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <X11/cursorfont.h>
#include <X11/Xlib.h>
#include "windows.h"
#include "win.h"
#include "gdi.h"
#include "library.h"
#include "neexe.h"
#include "wine.h"
#include "cursor.h"
#include "stddebug.h"
/* #define DEBUG_CURSOR */
/* #define DEBUG_RESOURCE */
#include "debug.h"
#include "arch.h"
static int ShowCursCount = 0;
static HCURSOR hActiveCursor;
static HCURSOR hEmptyCursor = 0;
RECT ClipCursorRect;
static struct { SEGPTR name; HCURSOR cursor; } system_cursor[] =
{
{ IDC_ARROW, 0 },
{ IDC_IBEAM, 0 },
{ IDC_WAIT, 0 },
{ IDC_CROSS, 0 },
{ IDC_UPARROW, 0 },
{ IDC_SIZE, 0 },
{ IDC_ICON, 0 },
{ IDC_SIZENWSE, 0 },
{ IDC_SIZENESW, 0 },
{ IDC_SIZEWE, 0 },
{ IDC_SIZENS, 0 }
};
#define NB_SYS_CURSORS (sizeof(system_cursor)/sizeof(system_cursor[0]))
/**********************************************************************
* LoadCursor [USER.173]
*/
HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
{
HCURSOR hCursor;
HANDLE rsc_mem;
WORD *lp;
LONG *lpl,size;
CURSORDESCRIP *lpcurdesc;
CURSORALLOC *lpcur;
HDC hdc;
int i, image_size;
unsigned char *cp1,*cp2;
dprintf_resource(stddeb,"LoadCursor: instance = %04x, name = %08lx\n",
instance, cursor_name);
if (!instance)
{
for (i = 0; i < NB_SYS_CURSORS; i++)
if (system_cursor[i].name == cursor_name)
{
if (system_cursor[i].cursor) return system_cursor[i].cursor;
else break;
}
if (i == NB_SYS_CURSORS) return 0;
}
hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L);
if (hCursor == (HCURSOR)NULL) return 0;
if (!instance) system_cursor[i].cursor = hCursor;
dprintf_cursor(stddeb,"LoadCursor Alloc hCursor=%X\n", hCursor);
lpcur = (CURSORALLOC *)GlobalLock(hCursor);
memset(lpcur, 0, sizeof(CURSORALLOC));
if (instance == (HANDLE)NULL) {
switch((LONG)cursor_name) {
case IDC_ARROW:
lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
GlobalUnlock(hCursor);
return hCursor;
case IDC_CROSS:
lpcur->xcursor = XCreateFontCursor(display, XC_crosshair);
GlobalUnlock(hCursor);
return hCursor;
case IDC_IBEAM:
lpcur->xcursor = XCreateFontCursor(display, XC_xterm);
GlobalUnlock(hCursor);
return hCursor;
case IDC_WAIT:
lpcur->xcursor = XCreateFontCursor(display, XC_watch);
GlobalUnlock(hCursor);
return hCursor;
case IDC_SIZENS:
lpcur->xcursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
GlobalUnlock(hCursor);
return hCursor;
case IDC_SIZEWE:
lpcur->xcursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
GlobalUnlock(hCursor);
return hCursor;
case IDC_SIZENWSE:
case IDC_SIZENESW:
lpcur->xcursor = XCreateFontCursor(display, XC_fleur);
GlobalUnlock(hCursor);
return hCursor;
default:
break;
}
}
#if 0
/* this code replaces all bitmap cursors with the default cursor */
lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
GlobalUnlock(hCursor);
return hCursor;
#endif
if (!(hdc = GetDC(0))) return 0;
rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR,
&image_size);
if (rsc_mem == (HANDLE)NULL) {
fprintf(stderr,"LoadCursor / Cursor %08lx not Found !\n", cursor_name);
ReleaseDC(0, hdc);
return 0;
}
lp = (WORD *)GlobalLock(rsc_mem);
if (lp == NULL) {
GlobalFree(rsc_mem);
ReleaseDC(0, hdc);
return 0;
}
lpcurdesc = (CURSORDESCRIP *)(lp + 3);
#if 0
dprintf_cursor(stddeb,"LoadCursor / image_size=%d\n", image_size);
dprintf_cursor(stddeb,"LoadCursor / curReserved=%X\n", *lp);
dprintf_cursor(stddeb,"LoadCursor / curResourceType=%X\n", *(lp + 1));
dprintf_cursor(stddeb,"LoadCursor / curResourceCount=%X\n", *(lp + 2));
dprintf_cursor(stddeb,"LoadCursor / cursor Width=%d\n",
(int)lpcurdesc->Width);
dprintf_cursor(stddeb,"LoadCursor / cursor Height=%d\n",
(int)lpcurdesc->Height);
dprintf_cursor(stddeb,"LoadCursor / cursor curXHotspot=%d\n",
(int)lpcurdesc->curXHotspot);
dprintf_cursor(stddeb,"LoadCursor / cursor curYHotspot=%d\n",
(int)lpcurdesc->curYHotspot);
dprintf_cursor(stddeb,"LoadCursor / cursor curDIBSize=%lX\n",
(DWORD)lpcurdesc->curDIBSize);
dprintf_cursor(stddeb,"LoadCursor / cursor curDIBOffset=%lX\n",
(DWORD)lpcurdesc->curDIBOffset);
#endif
lpcur->descriptor = *lpcurdesc;
GlobalUnlock(rsc_mem);
GlobalFree(rsc_mem);
rsc_mem = RSC_LoadResource(instance,
MAKEINTRESOURCE(lpcurdesc->curDIBOffset),
NE_RSCTYPE_CURSOR, &image_size);
if (rsc_mem == (HANDLE)NULL) {
fprintf(stderr,
"LoadCursor / Cursor %08lx Bitmap not Found !\n", cursor_name);
ReleaseDC(0, hdc);
return 0;
}
lpl = (LONG *)GlobalLock(rsc_mem);
if (lp == NULL) {
GlobalFree(rsc_mem);
ReleaseDC(0, hdc);
return 0;
}
lpl++;
size = CONV_LONG (*lpl);
if (size == sizeof(BITMAPCOREHEADER)){
CONV_BITMAPCOREHEADER (lpl);
((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
lpcur->hBitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lpl );
} else if (size == sizeof(BITMAPINFOHEADER)){
CONV_BITMAPINFO (lpl);
((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
lpcur->hBitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lpl );
} else {
fprintf(stderr,"No bitmap for cursor?\n");
lpcur->hBitmap = 0;
}
lpl = (char *)lpl + size + 8;
/* This is rather strange! The data is stored *BACKWARDS* and */
/* mirrored! But why?? FIXME: the image must be flipped at the Y */
/* axis, either here or in CreateCusor(); */
size = lpcur->descriptor.Height/2 * ((lpcur->descriptor.Width+7)/8);
#if 0
dprintf_cursor(stddeb,"Before:\n");
for(i=0;i<2*size;i++) {
dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
}
#endif
cp1 = (char *)lpl;
cp2 = cp1+2*size;
for(i = 0; i < size; i++) {
char tmp=*--cp2;
*cp2 = *cp1;
*cp1++ = tmp;
}
#if 0
dprintf_cursor(stddeb,"After:\n");
for(i=0;i<2*size;i++) {
dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
}
#endif
hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot,
lpcur->descriptor.curYHotspot, lpcur->descriptor.Width,
lpcur->descriptor.Height/2,
(LPSTR)lpl, ((LPSTR)lpl)+size);
GlobalUnlock(rsc_mem);
GlobalFree(rsc_mem);
GlobalUnlock(hCursor);
ReleaseDC(0,hdc);
return hCursor;
}
/**********************************************************************
* CreateCursor [USER.406]
*/
HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot,
short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
{
HCURSOR hCursor;
CURSORALLOC *lpcur;
HDC hdc;
int bpllen = (nWidth + 7)/8 * nHeight;
char *tmpbpl = malloc(bpllen);
int i;
XColor bkcolor,fgcolor;
Colormap cmap = XDefaultColormap(display,XDefaultScreen(display));
dprintf_resource(stddeb,"CreateCursor: inst=%04x nXhotspot=%d nYhotspot=%d nWidth=%d nHeight=%d\n",
instance, nXhotspot, nYhotspot, nWidth, nHeight);
dprintf_resource(stddeb,"CreateCursor: inst=%04x lpANDbitPlane=%p lpXORbitPlane=%p\n",
instance, lpANDbitPlane, lpXORbitPlane);
if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L);
if (hCursor == (HCURSOR)NULL) {
ReleaseDC(GetDesktopWindow(), hdc);
return 0;
}
dprintf_cursor(stddeb,"CreateCursor Alloc hCursor=%X\n", hCursor);
lpcur = (CURSORALLOC *)GlobalLock(hCursor);
memset(lpcur, 0, sizeof(CURSORALLOC));
lpcur->descriptor.curXHotspot = nXhotspot;
lpcur->descriptor.curYHotspot = nYhotspot;
for(i=0; i<bpllen; i++) tmpbpl[i] = ~lpANDbitPlane[i];
lpcur->pixmask = XCreatePixmapFromBitmapData(
display, DefaultRootWindow(display),
tmpbpl, nWidth, nHeight, 1, 0, 1);
for(i=0; i<bpllen; i++) tmpbpl[i] ^= lpXORbitPlane[i];
lpcur->pixshape = XCreatePixmapFromBitmapData(
display, DefaultRootWindow(display),
tmpbpl, nWidth, nHeight, 1, 0, 1);
XParseColor(display,cmap,"#000000",&fgcolor);
XParseColor(display,cmap,"#ffffff",&bkcolor);
lpcur->xcursor = XCreatePixmapCursor(display,
lpcur->pixshape, lpcur->pixmask,
&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot,
lpcur->descriptor.curYHotspot);
free(tmpbpl);
XFreePixmap(display, lpcur->pixshape);
XFreePixmap(display, lpcur->pixmask);
ReleaseDC(GetDesktopWindow(), hdc);
GlobalUnlock(hCursor);
return hCursor;
}
/**********************************************************************
* DestroyCursor [USER.458]
*/
BOOL DestroyCursor(HCURSOR hCursor)
{
CURSORALLOC *lpcur;
if (hCursor == (HCURSOR)NULL) return FALSE;
lpcur = (CURSORALLOC *)GlobalLock(hCursor);
if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
GlobalUnlock(hCursor);
GlobalFree(hCursor);
return TRUE;
}
/**********************************************************************
* CURSOR_SetCursor
*
* Internal helper function for SetCursor() and ShowCursor().
*/
static void CURSOR_SetCursor( HCURSOR hCursor )
{
CURSORALLOC *lpcur;
if (!(lpcur = (CURSORALLOC *)GlobalLock(hCursor))) return;
if (rootWindow != DefaultRootWindow(display))
{
XDefineCursor( display, rootWindow, lpcur->xcursor );
}
else
{
HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
while(hwnd)
{
Window win = WIN_GetXWindow( hwnd );
if (win) XDefineCursor( display, win, lpcur->xcursor );
hwnd = GetWindow( hwnd, GW_HWNDNEXT );
}
}
GlobalUnlock( hCursor );
}
/**********************************************************************
* SetCursor [USER.69]
*/
HCURSOR SetCursor(HCURSOR hCursor)
{
HCURSOR hOldCursor;
dprintf_cursor(stddeb,"SetCursor / hCursor=%04X !\n", hCursor);
hOldCursor = hActiveCursor;
hActiveCursor = hCursor;
if ((hCursor != hOldCursor) || (ShowCursCount < 0))
{
CURSOR_SetCursor( hCursor );
}
ShowCursCount = 0;
return hOldCursor;
}
/**********************************************************************
* GetCursor [USER.247]
*/
HCURSOR GetCursor(void)
{
return hActiveCursor;
}
/**********************************************************************
* SetCursorPos [USER.70]
*/
void SetCursorPos(short x, short y)
{
dprintf_cursor(stddeb,"SetCursorPos // x=%d y=%d\n", x, y);
XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
}
/**********************************************************************
* GetCursorPos [USER.17]
*/
void GetCursorPos(LPPOINT lpRetPoint)
{
Window root, child;
int rootX, rootY;
int childX, childY;
unsigned int mousebut;
if (!lpRetPoint) return;
if (!XQueryPointer( display, rootWindow, &root, &child,
&rootX, &rootY, &childX, &childY, &mousebut ))
lpRetPoint->x = lpRetPoint->y = 0;
else
{
lpRetPoint->x = rootX + desktopX;
lpRetPoint->y = rootY + desktopY;
}
dprintf_cursor(stddeb,
"GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
}
/**********************************************************************
* ShowCursor [USER.71]
*/
int ShowCursor(BOOL bShow)
{
dprintf_cursor(stddeb, "ShowCursor(%d), count=%d\n", bShow, ShowCursCount);
if (bShow)
{
if (++ShowCursCount == 0) /* Time to show it */
CURSOR_SetCursor( hActiveCursor );
}
else /* Hide it */
{
if (--ShowCursCount == -1) /* Time to hide it */
{
if (!hEmptyCursor)
hEmptyCursor = CreateCursor( 0, 1, 1, 1, 1,
"\xFF\xFF", "\xFF\xFF" );
CURSOR_SetCursor( hEmptyCursor );
}
}
return 0;
}
/**********************************************************************
* ClipCursor [USER.16]
*/
void ClipCursor(LPRECT lpNewClipRect)
{
if (!lpNewClipRect) SetRectEmpty( &ClipCursorRect );
else CopyRect( &ClipCursorRect, lpNewClipRect );
}
/**********************************************************************
* GetClipCursor [USER.309]
*/
void GetClipCursor(LPRECT lpRetClipRect)
{
if (lpRetClipRect != NULL)
CopyRect(lpRetClipRect, &ClipCursorRect);
}