Alexandre Julliard : user32: Reimplement loading of 16-bit cursors and icons using 16-bit resource functions .

Alexandre Julliard julliard at winehq.org
Tue Dec 22 09:58:56 CST 2009


Module: wine
Branch: master
Commit: d5b270eaddc9d3de249e410b98ce6fe5d177ccc4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d5b270eaddc9d3de249e410b98ce6fe5d177ccc4

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Dec 21 17:38:44 2009 +0100

user32: Reimplement loading of 16-bit cursors and icons using 16-bit resource functions.

---

 dlls/user32/user16.c |  137 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 129 insertions(+), 8 deletions(-)

diff --git a/dlls/user32/user16.c b/dlls/user32/user16.c
index b338720..0957ba2 100644
--- a/dlls/user32/user16.c
+++ b/dlls/user32/user16.c
@@ -33,6 +33,7 @@
 #include "user_private.h"
 #include "win.h"
 #include "controls.h"
+#include "wine/list.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(user);
@@ -248,6 +249,62 @@ static INT parse_format( LPCSTR format, WPRINTF_FORMAT *res )
 
 
 /**********************************************************************
+ * Management of the 16-bit cursor/icon cache
+ */
+
+struct cache_entry
+{
+    struct list entry;
+    HINSTANCE16 inst;
+    HRSRC16     rsrc;
+    HRSRC16     group;
+    HICON16     icon;
+    INT         count;
+};
+
+static struct list icon_cache = LIST_INIT( icon_cache );
+
+static void add_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc, HRSRC16 group, HICON16 icon )
+{
+    struct cache_entry *cache = HeapAlloc( GetProcessHeap(), 0, sizeof(*cache) );
+
+    if (!cache) return;
+    cache->inst  = inst;
+    cache->rsrc  = rsrc;
+    cache->group = group;
+    cache->icon  = icon;
+    cache->count = 1;
+    list_add_tail( &icon_cache, &cache->entry );
+}
+
+static HICON16 find_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc )
+{
+    struct cache_entry *cache;
+
+    LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry )
+    {
+        if (cache->inst != inst || cache->rsrc != rsrc) continue;
+        cache->count++;
+        return cache->icon;
+    }
+    return 0;
+}
+
+static int release_shared_icon( HICON16 icon )
+{
+    struct cache_entry *cache;
+
+    LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry )
+    {
+        if (cache->icon != icon) continue;
+        if (!cache->count) return 0;
+        return --cache->count;
+    }
+    return -1;
+}
+
+
+/**********************************************************************
  *		InitApp (USER.5)
  */
 INT16 WINAPI InitApp16( HINSTANCE16 hInstance )
@@ -755,7 +812,7 @@ BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand,
  */
 HCURSOR16 WINAPI LoadCursor16(HINSTANCE16 hInstance, LPCSTR name)
 {
-  return HCURSOR_16(LoadCursorA(HINSTANCE_32(hInstance), name));
+    return LoadImage16( hInstance, name, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE );
 }
 
 
@@ -764,7 +821,7 @@ HCURSOR16 WINAPI LoadCursor16(HINSTANCE16 hInstance, LPCSTR name)
  */
 HICON16 WINAPI LoadIcon16(HINSTANCE16 hInstance, LPCSTR name)
 {
-  return HICON_16(LoadIconA(HINSTANCE_32(hInstance), name));
+    return LoadImage16( hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE );
 }
 
 /**********************************************************************
@@ -1685,11 +1742,67 @@ DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
  *		LoadImage (USER.389)
  *
  */
-HANDLE16 WINAPI LoadImage16(HINSTANCE16 hinst, LPCSTR name, UINT16 type,
-			    INT16 desiredx, INT16 desiredy, UINT16 loadflags)
+HANDLE16 WINAPI LoadImage16(HINSTANCE16 hinst, LPCSTR name, UINT16 type, INT16 cx, INT16 cy, UINT16 flags)
 {
-  return HANDLE_16(LoadImageA(HINSTANCE_32(hinst), name, type, desiredx,
-			      desiredy, loadflags));
+    if (!hinst || (flags & LR_LOADFROMFILE))
+        return HICON_16( LoadImageA( 0, name, type, cx, cy, flags ));
+
+    hinst = GetExePtr( hinst );
+
+    if (flags & LR_DEFAULTSIZE)
+    {
+        if (type == IMAGE_ICON)
+        {
+            if (!cx) cx = GetSystemMetrics(SM_CXICON);
+            if (!cy) cy = GetSystemMetrics(SM_CYICON);
+        }
+        else if (type == IMAGE_CURSOR)
+        {
+            if (!cx) cx = GetSystemMetrics(SM_CXCURSOR);
+            if (!cy) cy = GetSystemMetrics(SM_CYCURSOR);
+        }
+    }
+
+    switch (type)
+    {
+    case IMAGE_BITMAP:
+        return HBITMAP_16( LoadImageA( HINSTANCE_32(hinst), name, type, cx, cy, flags ));
+
+    case IMAGE_ICON:
+    case IMAGE_CURSOR:
+    {
+        HANDLE16 handle;
+        HICON16 hIcon = 0;
+        HRSRC16 hRsrc, hGroupRsrc;
+        BYTE *dir, *bits;
+        INT id = 0;
+
+        if (!(hRsrc = FindResource16( hinst, name,
+                                      (LPCSTR)(type == IMAGE_ICON ? RT_GROUP_ICON : RT_GROUP_CURSOR ))))
+            return 0;
+        hGroupRsrc = hRsrc;
+
+        if (!(handle = LoadResource16( hinst, hRsrc ))) return 0;
+        if ((dir = LockResource16( handle ))) id = LookupIconIdFromDirectory( dir, type == IMAGE_ICON );
+        FreeResource16( handle );
+        if (!id) return 0;
+
+        if (!(hRsrc = FindResource16( hinst, MAKEINTRESOURCEA(id),
+                                      (LPCSTR)(type == IMAGE_ICON ? RT_ICON : RT_CURSOR) ))) return 0;
+
+        if ((flags & LR_SHARED) && (hIcon = find_shared_icon( hinst, hRsrc ) ) != 0) return hIcon;
+
+        if (!(handle = LoadResource16( hinst, hRsrc ))) return 0;
+        bits = LockResource16( handle );
+        hIcon = CreateIconFromResourceEx16( bits, 0, type == IMAGE_ICON, 0x00030000, cx, cy, flags );
+        FreeResource16( handle );
+
+        if (hIcon && (flags & LR_SHARED)) add_shared_icon( hinst, hRsrc, hGroupRsrc, hIcon );
+        return hIcon;
+    }
+    default:
+        return 0;
+    }
 }
 
 /******************************************************************************
@@ -2199,7 +2312,15 @@ HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
  */
 BOOL16 WINAPI DestroyIcon16(HICON16 hIcon)
 {
-  return DestroyIcon32(hIcon, 0);
+    int count;
+
+    TRACE("%04x\n", hIcon );
+
+    count = release_shared_icon( hIcon );
+    if (count != -1) return !count;
+    /* assume non-shared */
+    GlobalFree16( hIcon );
+    return TRUE;
 }
 
 /***********************************************************************
@@ -2207,7 +2328,7 @@ BOOL16 WINAPI DestroyIcon16(HICON16 hIcon)
  */
 BOOL16 WINAPI DestroyCursor16(HCURSOR16 hCursor)
 {
-  return DestroyIcon32(hCursor, 0);
+    return DestroyIcon16( hCursor );
 }
 
 




More information about the wine-cvs mailing list