[2/10] user: Create 32-bit cursor handles
H. Verbeet
hverbeet at gmail.com
Sat Aug 5 16:38:53 CDT 2006
This makes user create 32-bit cursor handles, and adds code for
mapping between 16-bits and 32-bits cursor handles. It doesn't store
anything it the 32-bits cursors though, the next patch does that.
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index d563457..c644bc4 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -60,6 +60,8 @@ #include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "wine/exception.h"
#include "wine/debug.h"
+#include "wine/list.h"
+#include "wine/server.h"
#include "user_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
@@ -132,6 +134,159 @@ static CRITICAL_SECTION IconCrst = { &cr
static WORD ICON_HOTSPOT = 0x4242;
+/* What is a good table size? */
+#define CURSOR_HASH_SIZE 97
+
+typedef struct {
+ HCURSOR16 cursor16;
+ HCURSOR cursor32;
+ struct list entry16;
+ struct list entry32;
+} cursor_map_entry_t;
+
+static struct list cursor16to32[CURSOR_HASH_SIZE];
+static struct list cursor32to16[CURSOR_HASH_SIZE];
+
+static inline int hash_cursor_handle( DWORD handle )
+{
+ return handle % CURSOR_HASH_SIZE;
+}
+
+static void add_cursor16to32_entry( cursor_map_entry_t *entry )
+{
+ int idx = hash_cursor_handle( entry->cursor16 );
+
+ if (!cursor16to32[idx].next) list_init( &cursor16to32[idx] );
+
+ list_add_head( &cursor16to32[idx], &entry->entry16 );
+}
+
+static void add_cursor32to16_entry( cursor_map_entry_t *entry )
+{
+ int idx = hash_cursor_handle( (DWORD)entry->cursor32 );
+
+ if (!cursor32to16[idx].next) list_init( &cursor32to16[idx] );
+
+ list_add_head( &cursor32to16[idx], &entry->entry32 );
+}
+
+static cursor_map_entry_t *remove_cursor16to32_entry( HCURSOR16 cursor16 )
+{
+ cursor_map_entry_t *entry = NULL;
+ int idx = hash_cursor_handle( cursor16 );
+
+ if (cursor16to32[idx].next)
+ {
+ LIST_FOR_EACH_ENTRY( entry, &cursor16to32[idx], cursor_map_entry_t, entry16 )
+ if (entry->cursor16 == cursor16)
+ {
+ list_remove( &entry->entry16 );
+ return entry;
+ }
+ }
+
+ return entry;
+}
+
+static cursor_map_entry_t *remove_cursor32to16_entry( HCURSOR cursor32 )
+{
+ cursor_map_entry_t *entry = NULL;
+ int idx = hash_cursor_handle( (DWORD)cursor32 );
+
+ if (cursor32to16[idx].next)
+ {
+ LIST_FOR_EACH_ENTRY( entry, &cursor32to16[idx], cursor_map_entry_t, entry32 )
+ if (entry->cursor32 == cursor32)
+ {
+ list_remove( &entry->entry32 );
+ return entry;
+ }
+ }
+
+ return entry;
+}
+
+static HCURSOR create_cursor( unsigned int num_frames, unsigned int delay, HCURSOR16 cursor16 )
+{
+ HCURSOR cursor = 0;
+
+ SERVER_START_REQ(create_cursor)
+ {
+ req->num_frames = num_frames;
+ req->delay = delay;
+ if (!wine_server_call_err( req )) cursor = reply->handle;
+ }
+ SERVER_END_REQ;
+
+ if (cursor)
+ {
+ cursor_map_entry_t *entry = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_map_entry_t) );
+ entry->cursor16 = cursor16;
+ entry->cursor32 = cursor;
+
+ add_cursor16to32_entry( entry );
+ add_cursor32to16_entry( entry );
+ }
+
+ return cursor;
+}
+
+static HCURSOR16 destroy_cursor( HCURSOR cursor )
+{
+ cursor_map_entry_t *entry;
+ HCURSOR16 cursor16;
+
+ if (!cursor) return 0;
+
+ SERVER_START_REQ(destroy_cursor)
+ {
+ req->handle = cursor;
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ entry = remove_cursor32to16_entry( cursor );
+ if (entry)
+ {
+ cursor16 = entry->cursor16;
+ remove_cursor16to32_entry( cursor16 );
+ HeapFree( GetProcessHeap(), 0, entry );
+ }
+
+ return GlobalFree16( cursor16 );
+}
+
+HCURSOR16 get_cursor_handle16( HCURSOR cursor32 )
+{
+ cursor_map_entry_t *entry;
+ int idx = hash_cursor_handle( (DWORD)cursor32 );
+
+ if (!cursor32) return 0;
+
+ if (cursor32to16[idx].next)
+ {
+ LIST_FOR_EACH_ENTRY( entry, &cursor32to16[idx], cursor_map_entry_t, entry32 )
+ if (entry->cursor32 == cursor32) return entry->cursor16;
+ }
+
+ return 0;
+}
+
+HCURSOR get_cursor_handle32( HCURSOR16 cursor16 )
+{
+ cursor_map_entry_t *entry;
+ int idx = hash_cursor_handle( cursor16 );
+
+ if (!cursor16) return 0;
+
+ if (cursor16to32[idx].next)
+ {
+ LIST_FOR_EACH_ENTRY( entry, &cursor16to32[idx], cursor_map_entry_t, entry16 )
+ if (entry->cursor16 == cursor16) return entry->cursor32;
+ }
+
+ return 0;
+}
/***********************************************************************
* map_fileW
@@ -468,7 +623,7 @@ void CURSORICON_FreeModuleIcons( HMODULE
ICONCACHE *freePtr = *ptr;
*ptr = freePtr->next;
- GlobalFree16(HICON_16(freePtr->hIcon));
+ destroy_cursor( freePtr->hIcon );
HeapFree( GetProcessHeap(), 0, freePtr );
continue;
}
@@ -873,7 +1028,8 @@ HICON WINAPI CreateIconFromResourceEx( L
DeleteObject( hAndBits );
DeleteObject( hXorBits );
- return HICON_32((HICON16)hObj);
+
+ return create_cursor( 1, 0, hObj );
}
@@ -1025,7 +1181,8 @@ static HICON CURSORICON_Copy( HINSTANCE1
memcpy( ptrNew, ptrOld, size );
GlobalUnlock16( hOld );
GlobalUnlock16( hNew );
- return HICON_32(hNew);
+
+ return create_cursor( 1, 0, hNew );
}
/*************************************************************************
@@ -1346,7 +1503,7 @@ HGLOBAL16 WINAPI CreateCursorIconIndirec
memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
GlobalUnlock16( handle );
- return handle;
+ return HICON_16(create_cursor( 1, 0, handle ));
}
@@ -1415,7 +1572,7 @@ WORD WINAPI DestroyIcon32( HGLOBAL16 han
/* Now assume non-shared cursor/icon */
- retv = GlobalFree16( handle );
+ retv = destroy_cursor( HCURSOR_32(handle) );
return (flags & CID_RESOURCE)? retv : TRUE;
}
@@ -1862,7 +2019,8 @@ HICON WINAPI CreateIconIndirect(PICONINF
if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
GlobalUnlock16( hObj );
}
- return HICON_32(hObj);
+
+ return create_cursor( 1, 0, hObj );
}
/******************************************************************************
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index ffb2796..9bd1d38 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -232,12 +232,15 @@ extern void SPY_ExitMessage( INT iFlag,
extern int SPY_Init(void);
/* HANDLE16 <-> HANDLE conversions */
-#define HCURSOR_16(h32) (LOWORD(h32))
-#define HICON_16(h32) (LOWORD(h32))
+HCURSOR16 get_cursor_handle16( HCURSOR cursor32 );
+HCURSOR get_cursor_handle32( HCURSOR16 cursor16 );
+
+#define HCURSOR_16(h32) get_cursor_handle16(h32)
+#define HICON_16(h32) get_cursor_handle16(h32)
#define HINSTANCE_16(h32) (LOWORD(h32))
-#define HCURSOR_32(h16) ((HCURSOR)(ULONG_PTR)(h16))
-#define HICON_32(h16) ((HICON)(ULONG_PTR)(h16))
+#define HCURSOR_32(h16) get_cursor_handle32(h16)
+#define HICON_32(h16) get_cursor_handle32(h16)
#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16))
#define HMODULE_32(h16) ((HMODULE)(ULONG_PTR)(h16))
diff --git a/dlls/user/wnd16.c b/dlls/user/wnd16.c
index ea68d62..a91d147 100644
--- a/dlls/user/wnd16.c
+++ b/dlls/user/wnd16.c
@@ -648,7 +648,17 @@ void WINAPI ValidateRgn16( HWND16 hwnd,
*/
WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
{
- return GetClassWord( WIN_Handle32(hwnd), offset );
+ WORD ret = GetClassWord( WIN_Handle32(hwnd), offset );
+
+ switch (offset)
+ {
+ case GCLP_HCURSOR:
+ case GCLP_HICON:
+ case GCLP_HICONSM:
+ return HCURSOR_16((HCURSOR)(LONG_PTR)ret);
+ default:
+ return ret;
+ }
}
@@ -657,7 +667,15 @@ WORD WINAPI GetClassWord16( HWND16 hwnd,
*/
WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
{
- return SetClassWord( WIN_Handle32(hwnd), offset, newval );
+ switch (offset)
+ {
+ case GCLP_HCURSOR:
+ case GCLP_HICON:
+ case GCLP_HICONSM:
+ return HCURSOR_16((HCURSOR)SetClassLongW( WIN_Handle32(hwnd), offset, (LONG_PTR)HCURSOR_32(newval) ));
+ default:
+ return SetClassWord( WIN_Handle32(hwnd), offset, newval );
+ }
}
@@ -670,6 +688,10 @@ LONG WINAPI GetClassLong16( HWND16 hwnd1
switch( offset )
{
+ case GCLP_HCURSOR:
+ case GCLP_HICON:
+ case GCLP_HICONSM:
+ return HCURSOR_16((HCURSOR)ret);
case GCLP_WNDPROC:
return (LONG_PTR)WINPROC_GetProc16( (WNDPROC)ret, FALSE );
case GCLP_MENUNAME:
@@ -687,6 +709,10 @@ LONG WINAPI SetClassLong16( HWND16 hwnd1
{
switch( offset )
{
+ case GCLP_HCURSOR:
+ case GCLP_HICON:
+ case GCLP_HICONSM:
+ return HCURSOR_16((HCURSOR)SetClassLongW( WIN_Handle32(hwnd16), offset, (LONG_PTR)HCURSOR_32( newval ) ));
case GCLP_WNDPROC:
{
WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
More information about the wine-patches
mailing list