| /* |
| * Window properties |
| * |
| * Copyright 1995, 1996 Alexandre Julliard |
| */ |
| |
| #include <string.h> |
| #include "win.h" |
| #include "heap.h" |
| #include "debug.h" |
| |
| DEFAULT_DEBUG_CHANNEL(prop) |
| |
| |
| typedef struct tagPROPERTY |
| { |
| struct tagPROPERTY *next; /* Next property in window list */ |
| HANDLE handle; /* User's data */ |
| LPSTR string; /* Property string (or atom) */ |
| } PROPERTY; |
| |
| |
| /*********************************************************************** |
| * PROP_FindProp |
| */ |
| static PROPERTY *PROP_FindProp( HWND hwnd, LPCSTR str ) |
| { |
| ATOM atom; |
| PROPERTY *prop; |
| WND *pWnd = WIN_FindWndPtr( hwnd ); |
| |
| if (!pWnd) return NULL; |
| if (HIWORD(str)) |
| { |
| atom = GlobalFindAtomA( str ); |
| for (prop = pWnd->pProp; prop; prop = prop->next) |
| { |
| if (HIWORD(prop->string)) |
| { |
| if (!lstrcmpiA( prop->string, str )) goto END; |
| } |
| else if (LOWORD(prop->string) == atom) goto END; |
| } |
| } |
| else /* atom */ |
| { |
| atom = LOWORD(str); |
| for (prop = pWnd->pProp; (prop); prop = prop->next) |
| { |
| if (HIWORD(prop->string)) |
| { |
| if (GlobalFindAtomA( prop->string ) == atom) goto END; |
| } |
| else if (LOWORD(prop->string) == atom) goto END; |
| } |
| } |
| prop = NULL; |
| END: |
| WIN_ReleaseWndPtr(pWnd); |
| return prop; |
| } |
| |
| |
| /*********************************************************************** |
| * GetProp16 (USER.25) |
| */ |
| HANDLE16 WINAPI GetProp16( HWND16 hwnd, LPCSTR str ) |
| { |
| return (HANDLE16)GetPropA( hwnd, str ); |
| } |
| |
| |
| /*********************************************************************** |
| * GetProp32A (USER32.281) |
| */ |
| HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str ) |
| { |
| PROPERTY *prop = PROP_FindProp( hwnd, str ); |
| |
| if (HIWORD(str)) |
| TRACE(prop, "(%08x,'%s'): returning %08x\n", |
| hwnd, str, prop ? prop->handle : 0 ); |
| else |
| TRACE(prop, "(%08x,#%04x): returning %08x\n", |
| hwnd, LOWORD(str), prop ? prop->handle : 0 ); |
| |
| return prop ? prop->handle : 0; |
| } |
| |
| |
| /*********************************************************************** |
| * GetProp32W (USER32.282) |
| */ |
| HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str ) |
| { |
| LPSTR strA; |
| HANDLE ret; |
| |
| if (!HIWORD(str)) return GetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str) ); |
| strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); |
| ret = GetPropA( hwnd, strA ); |
| HeapFree( GetProcessHeap(), 0, strA ); |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * SetProp16 (USER.26) |
| */ |
| BOOL16 WINAPI SetProp16( HWND16 hwnd, LPCSTR str, HANDLE16 handle ) |
| { |
| return (BOOL16)SetPropA( hwnd, str, handle ); |
| } |
| |
| |
| /*********************************************************************** |
| * SetProp32A (USER32.497) |
| */ |
| BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle ) |
| { |
| PROPERTY *prop; |
| |
| if (HIWORD(str)) |
| TRACE(prop, "%04x '%s' %08x\n", hwnd, str, handle ); |
| else |
| TRACE(prop, "%04x #%04x %08x\n", |
| hwnd, LOWORD(str), handle ); |
| |
| if (!(prop = PROP_FindProp( hwnd, str ))) |
| { |
| /* We need to create it */ |
| WND *pWnd = WIN_FindWndPtr( hwnd ); |
| if (!pWnd) return FALSE; |
| if (!(prop = HeapAlloc( SystemHeap, 0, sizeof(*prop) ))) |
| { |
| WIN_ReleaseWndPtr(pWnd); |
| return FALSE; |
| } |
| if (!(prop->string = SEGPTR_STRDUP(str))) |
| { |
| HeapFree( SystemHeap, 0, prop ); |
| WIN_ReleaseWndPtr(pWnd); |
| return FALSE; |
| |
| } |
| prop->next = pWnd->pProp; |
| pWnd->pProp = prop; |
| WIN_ReleaseWndPtr(pWnd); |
| } |
| prop->handle = handle; |
| return TRUE; |
| } |
| |
| |
| /*********************************************************************** |
| * SetProp32W (USER32.498) |
| */ |
| BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle ) |
| { |
| BOOL ret; |
| LPSTR strA; |
| |
| if (!HIWORD(str)) |
| return SetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str), handle ); |
| strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); |
| ret = SetPropA( hwnd, strA, handle ); |
| HeapFree( GetProcessHeap(), 0, strA ); |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * RemoveProp16 (USER.24) |
| */ |
| HANDLE16 WINAPI RemoveProp16( HWND16 hwnd, LPCSTR str ) |
| { |
| return (HANDLE16)RemovePropA( hwnd, str ); |
| } |
| |
| |
| /*********************************************************************** |
| * RemoveProp32A (USER32.442) |
| */ |
| HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str ) |
| { |
| ATOM atom; |
| HANDLE handle; |
| PROPERTY **pprop, *prop; |
| WND *pWnd = WIN_FindWndPtr( hwnd ); |
| |
| if (HIWORD(str)) |
| TRACE(prop, "%04x '%s'\n", hwnd, str ); |
| else |
| TRACE(prop, "%04x #%04x\n", hwnd, LOWORD(str)); |
| |
| |
| if (!pWnd) return (HANDLE)0; |
| if (HIWORD(str)) |
| { |
| atom = GlobalFindAtomA( str ); |
| for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next) |
| { |
| if (HIWORD((*pprop)->string)) |
| { |
| if (!lstrcmpiA( (*pprop)->string, str )) break; |
| } |
| else if (LOWORD((*pprop)->string) == atom) break; |
| } |
| } |
| else /* atom */ |
| { |
| atom = LOWORD(str); |
| for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next) |
| { |
| if (HIWORD((*pprop)->string)) |
| { |
| if (GlobalFindAtomA( (*pprop)->string ) == atom) break; |
| } |
| else if (LOWORD((*pprop)->string) == atom) break; |
| } |
| } |
| WIN_ReleaseWndPtr(pWnd); |
| if (!*pprop) return 0; |
| prop = *pprop; |
| handle = prop->handle; |
| *pprop = prop->next; |
| SEGPTR_FREE(prop->string); |
| HeapFree( SystemHeap, 0, prop ); |
| return handle; |
| } |
| |
| |
| /*********************************************************************** |
| * RemoveProp32W (USER32.443) |
| */ |
| HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str ) |
| { |
| LPSTR strA; |
| HANDLE ret; |
| |
| if (!HIWORD(str)) |
| return RemovePropA( hwnd, (LPCSTR)(UINT)LOWORD(str) ); |
| strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); |
| ret = RemovePropA( hwnd, strA ); |
| HeapFree( GetProcessHeap(), 0, strA ); |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * PROPERTY_RemoveWindowProps |
| * |
| * Remove all properties of a window. |
| */ |
| void PROPERTY_RemoveWindowProps( WND *pWnd ) |
| { |
| PROPERTY *prop, *next; |
| |
| for (prop = pWnd->pProp; (prop); prop = next) |
| { |
| next = prop->next; |
| SEGPTR_FREE( prop->string ); |
| HeapFree( SystemHeap, 0, prop ); |
| } |
| pWnd->pProp = NULL; |
| } |
| |
| |
| /*********************************************************************** |
| * EnumProps16 (USER.27) |
| */ |
| INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func ) |
| { |
| PROPERTY *prop, *next; |
| WND *pWnd; |
| INT16 ret = -1; |
| |
| TRACE(prop, "%04x %08x\n", hwnd, (UINT)func ); |
| if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; |
| for (prop = pWnd->pProp; (prop); prop = next) |
| { |
| /* Already get the next in case the callback */ |
| /* function removes the current property. */ |
| next = prop->next; |
| |
| TRACE(prop, " Callback: handle=%08x str='%s'\n", |
| prop->handle, prop->string ); |
| ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle ); |
| if (!ret) break; |
| } |
| WIN_ReleaseWndPtr(pWnd); |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * EnumProps32A (USER32.186) |
| */ |
| INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func ) |
| { |
| return EnumPropsExA( hwnd, (PROPENUMPROCEXA)func, 0 ); |
| } |
| |
| |
| /*********************************************************************** |
| * EnumProps32W (USER32.189) |
| */ |
| INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func ) |
| { |
| return EnumPropsExW( hwnd, (PROPENUMPROCEXW)func, 0 ); |
| } |
| |
| |
| /*********************************************************************** |
| * EnumPropsEx32A (USER32.187) |
| */ |
| INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam) |
| { |
| PROPERTY *prop, *next; |
| WND *pWnd; |
| INT ret = -1; |
| |
| TRACE(prop, "%04x %08x %08lx\n", |
| hwnd, (UINT)func, lParam ); |
| if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; |
| for (prop = pWnd->pProp; (prop); prop = next) |
| { |
| /* Already get the next in case the callback */ |
| /* function removes the current property. */ |
| next = prop->next; |
| |
| TRACE(prop, " Callback: handle=%08x str='%s'\n", |
| prop->handle, prop->string ); |
| ret = func( hwnd, prop->string, prop->handle, lParam ); |
| if (!ret) break; |
| } |
| WIN_ReleaseWndPtr(pWnd); |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * EnumPropsEx32W (USER32.188) |
| */ |
| INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam) |
| { |
| PROPERTY *prop, *next; |
| WND *pWnd; |
| INT ret = -1; |
| |
| TRACE(prop, "%04x %08x %08lx\n", |
| hwnd, (UINT)func, lParam ); |
| if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; |
| for (prop = pWnd->pProp; (prop); prop = next) |
| { |
| /* Already get the next in case the callback */ |
| /* function removes the current property. */ |
| next = prop->next; |
| |
| TRACE(prop, " Callback: handle=%08x str='%s'\n", |
| prop->handle, prop->string ); |
| if (HIWORD(prop->string)) |
| { |
| LPWSTR str = HEAP_strdupAtoW( GetProcessHeap(), 0, prop->string ); |
| ret = func( hwnd, str, prop->handle, lParam ); |
| HeapFree( GetProcessHeap(), 0, str ); |
| } |
| else |
| ret = func( hwnd, (LPCWSTR)(UINT)LOWORD( prop->string ), |
| prop->handle, lParam ); |
| if (!ret) break; |
| } |
| WIN_ReleaseWndPtr(pWnd); |
| return ret; |
| } |