Implemented GetAncestor and removed WIN_GetTopParent.
[wine] / windows / property.c
1 /*
2  * Window properties
3  *
4  * Copyright 1995, 1996 Alexandre Julliard
5  */
6
7 #include <string.h>
8
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winuser16.h"
12 #include "win.h"
13 #include "heap.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(prop);
17
18
19 typedef struct tagPROPERTY
20 {
21     struct tagPROPERTY *next;     /* Next property in window list */
22     HANDLE            handle;   /* User's data */
23     LPSTR               string;   /* Property string (or atom) */
24 } PROPERTY;
25
26
27 #define MAX_ATOM_LEN 255
28
29 /***********************************************************************
30  *           PROP_FindProp
31  */
32 static PROPERTY *PROP_FindProp( HWND hwnd, LPCSTR str )
33 {
34     ATOM atom;
35     PROPERTY *prop;
36     WND *pWnd = WIN_FindWndPtr( hwnd );
37
38     if (!pWnd) return NULL;
39     if (HIWORD(str))
40     {
41         atom = GlobalFindAtomA( str );
42         for (prop = pWnd->pProp; prop; prop = prop->next)
43         {
44             if (HIWORD(prop->string))
45             {
46                 if (!lstrcmpiA( prop->string, str )) goto END;
47             }
48             else if (LOWORD(prop->string) == atom) goto END;
49         }
50     }
51     else  /* atom */
52     {
53         atom = LOWORD(str);
54         for (prop = pWnd->pProp; (prop); prop = prop->next)
55         {
56             if (HIWORD(prop->string))
57             {
58                 if (GlobalFindAtomA( prop->string ) == atom) goto END;
59             }
60             else if (LOWORD(prop->string) == atom) goto END;
61         }
62     }
63     prop = NULL;
64 END:
65     WIN_ReleaseWndPtr(pWnd);
66     return prop;
67 }
68
69
70 /***********************************************************************
71  *              GetProp (USER.25)
72  */
73 HANDLE16 WINAPI GetProp16( HWND16 hwnd, LPCSTR str )
74 {
75     return (HANDLE16)GetPropA( hwnd, str );
76 }
77
78
79 /***********************************************************************
80  *              GetPropA (USER32.@)
81  */
82 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
83 {
84     PROPERTY *prop = PROP_FindProp( hwnd, str );
85
86     if (HIWORD(str))
87         TRACE("(%08x,'%s'): returning %08x\n",
88                       hwnd, str, prop ? prop->handle : 0 );
89     else
90         TRACE("(%08x,#%04x): returning %08x\n",
91                       hwnd, LOWORD(str), prop ? prop->handle : 0 );
92
93     return prop ? prop->handle : 0;
94 }
95
96
97 /***********************************************************************
98  *              GetPropW (USER32.@)
99  */
100 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
101 {
102     LPSTR strA;
103     HANDLE ret;
104
105     if (!HIWORD(str)) return GetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
106     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
107     ret = GetPropA( hwnd, strA );
108     HeapFree( GetProcessHeap(), 0, strA );
109     return ret;
110 }
111
112
113 /***********************************************************************
114  *              SetProp (USER.26)
115  */
116 BOOL16 WINAPI SetProp16( HWND16 hwnd, LPCSTR str, HANDLE16 handle )
117 {
118     return (BOOL16)SetPropA( hwnd, str, handle );
119 }
120
121
122 /***********************************************************************
123  *              SetPropA (USER32.@)
124  */
125 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
126 {
127     PROPERTY *prop;
128
129     if (HIWORD(str))
130         TRACE("%04x '%s' %08x\n", hwnd, str, handle );
131     else
132         TRACE("%04x #%04x %08x\n",
133                       hwnd, LOWORD(str), handle );
134
135     if (!(prop = PROP_FindProp( hwnd, str )))
136     {
137         /* We need to create it */
138         WND *pWnd = WIN_FindWndPtr( hwnd );
139         if (!pWnd) return FALSE;
140         if (!(prop = HeapAlloc( GetProcessHeap(), 0, sizeof(*prop) )))
141         {
142             WIN_ReleaseWndPtr(pWnd);
143             return FALSE;
144         }
145         if (!(prop->string = SEGPTR_STRDUP(str)))
146         {
147             HeapFree( GetProcessHeap(), 0, prop );
148             WIN_ReleaseWndPtr(pWnd);
149             return FALSE;
150
151         }
152         prop->next  = pWnd->pProp;
153         pWnd->pProp = prop;
154         WIN_ReleaseWndPtr(pWnd);
155     }
156     prop->handle = handle;
157     return TRUE;
158 }
159
160
161 /***********************************************************************
162  *              SetPropW (USER32.@)
163  */
164 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
165 {
166     BOOL ret;
167     LPSTR strA;
168
169     if (!HIWORD(str))
170         return SetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str), handle );
171     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
172     ret = SetPropA( hwnd, strA, handle );
173     HeapFree( GetProcessHeap(), 0, strA );
174     return ret;
175 }
176
177
178 /***********************************************************************
179  *              RemoveProp (USER.24)
180  */
181 HANDLE16 WINAPI RemoveProp16( HWND16 hwnd, LPCSTR str )
182 {
183     return (HANDLE16)RemovePropA( hwnd, str );
184 }
185
186
187 /***********************************************************************
188  *              RemovePropA (USER32.@)
189  */
190 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
191 {
192     ATOM atom;
193     HANDLE handle;
194     PROPERTY **pprop, *prop;
195     WND *pWnd = WIN_FindWndPtr( hwnd );
196
197     if (HIWORD(str))
198       TRACE("%04x '%s'\n", hwnd, str );
199     else
200       TRACE("%04x #%04x\n", hwnd, LOWORD(str));
201
202
203     if (!pWnd) return (HANDLE)0;
204     if (HIWORD(str))
205     {
206         atom = GlobalFindAtomA( str );
207         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
208         {
209             if (HIWORD((*pprop)->string))
210             {
211                 if (!lstrcmpiA( (*pprop)->string, str )) break;
212             }
213             else if (LOWORD((*pprop)->string) == atom) break;
214         }
215     }
216     else  /* atom */
217     {
218         atom = LOWORD(str);
219         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
220         {
221             if (HIWORD((*pprop)->string))
222             {
223                 if (GlobalFindAtomA( (*pprop)->string ) == atom) break;
224             }
225             else if (LOWORD((*pprop)->string) == atom) break;
226         }
227     }
228     WIN_ReleaseWndPtr(pWnd);
229     if (!*pprop) return 0;
230     prop   = *pprop;
231     handle = prop->handle;
232     *pprop = prop->next;
233     SEGPTR_FREE(prop->string);
234     HeapFree( GetProcessHeap(), 0, prop );
235     return handle;
236 }
237
238
239 /***********************************************************************
240  *              RemovePropW (USER32.@)
241  */
242 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
243 {
244     LPSTR strA;
245     HANDLE ret;
246
247     if (!HIWORD(str))
248         return RemovePropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
249     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
250     ret = RemovePropA( hwnd, strA );
251     HeapFree( GetProcessHeap(), 0, strA );
252     return ret;
253 }
254
255
256 /***********************************************************************
257  *           PROPERTY_RemoveWindowProps
258  *
259  * Remove all properties of a window.
260  */
261 void PROPERTY_RemoveWindowProps( WND *pWnd )
262 {
263     PROPERTY *prop, *next;
264
265     for (prop = pWnd->pProp; (prop); prop = next)
266     {
267         next = prop->next;
268         SEGPTR_FREE( prop->string );
269         HeapFree( GetProcessHeap(), 0, prop );
270     }
271     pWnd->pProp = NULL;
272 }
273
274
275 /***********************************************************************
276  *              EnumProps (USER.27)
277  */
278 INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
279 {
280     PROPERTY *prop, *next;
281     WND *pWnd;
282     INT16 ret = -1;
283
284     TRACE("%04x %08x\n", hwnd, (UINT)func );
285     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
286     for (prop = pWnd->pProp; (prop); prop = next)
287     {
288         /* Already get the next in case the callback */
289         /* function removes the current property.    */
290         next = prop->next;
291
292         /* SDK docu seems to suggest that EnumProps16 does not retrieve
293          * the string in case of an atom handle, in contrast to Win32 */
294
295         TRACE("  Callback: handle=%08x str=%s\n",
296               prop->handle, debugstr_a(prop->string) );
297         ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle );
298         if (!ret) break;
299     }
300     WIN_ReleaseWndPtr(pWnd);
301     return ret;
302 }
303
304
305 /* relay to call the EnumProps callback function from EnumPropsEx */
306 static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPCSTR str, HANDLE handle, ULONG_PTR lparam )
307 {
308     PROPENUMPROCA func = (PROPENUMPROCA)lparam;
309     return func( hwnd, str, handle );
310 }
311
312
313 /***********************************************************************
314  *              EnumPropsA (USER32.@)
315  */
316 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
317 {
318     return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
319 }
320
321
322 /***********************************************************************
323  *              EnumPropsExA (USER32.@)
324  */
325 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
326 {
327     PROPERTY *prop, *next;
328     WND *pWnd;
329     INT ret = -1;
330     char atomStr[MAX_ATOM_LEN+1];
331     char *pStr;
332
333     TRACE("%04x %p %08lx\n", hwnd, func, lParam);
334     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
335     for (prop = pWnd->pProp; (prop); prop = next)
336     {
337         /* Already get the next in case the callback */
338         /* function removes the current property.    */
339         next = prop->next;
340
341         if (!HIWORD(prop->string))
342         { /* get "real" string the atom points to.
343            * This seems to be done for Win32 only */
344             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
345             {
346                 ERR("huh ? Atom %04x not an atom ??\n", LOWORD(prop->string));
347                 atomStr[0] = '\0';
348             }
349             pStr = atomStr;
350         }
351         else
352             pStr = prop->string;
353
354         TRACE("  Callback: handle=%08x str='%s'\n",
355             prop->handle, prop->string );
356
357         ret = func( hwnd, pStr, prop->handle, lParam );
358         if (!ret) break;
359     }
360     WIN_ReleaseWndPtr(pWnd);
361     return ret;
362 }
363
364
365 /* relay to call the EnumProps callback function from EnumPropsEx */
366 static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPCWSTR str, HANDLE handle, ULONG_PTR lparam )
367 {
368     PROPENUMPROCW func = (PROPENUMPROCW)lparam;
369     return func( hwnd, str, handle );
370 }
371
372 /***********************************************************************
373  *              EnumPropsW (USER32.@)
374  */
375 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
376 {
377     return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
378 }
379
380 /***********************************************************************
381  *              EnumPropsExW (USER32.@)
382  */
383 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
384 {
385     PROPERTY *prop, *next;
386     WND *pWnd;
387     INT ret = -1;
388     char atomStr[MAX_ATOM_LEN+1];
389     char *pStr;
390     LPWSTR strW;
391
392     TRACE("%04x %p %08lx\n", hwnd, func, lParam);
393     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
394     for (prop = pWnd->pProp; (prop); prop = next)
395     {
396         /* Already get the next in case the callback */
397         /* function removes the current property.    */
398         next = prop->next;
399
400         if (!HIWORD(prop->string))
401         { /* get "real" string the atom points to.
402            * This seems to be done for Win32 only */
403             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
404             {
405                 ERR("huh ? Atom %04x not an atom ??\n",
406                     (ATOM)LOWORD(prop->string));
407                 atomStr[0] = '\0';
408             }
409             pStr = atomStr;
410         }
411         else
412             pStr = prop->string;
413
414         TRACE("  Callback: handle=%08x str='%s'\n",
415             prop->handle, prop->string );
416
417         strW = HEAP_strdupAtoW( GetProcessHeap(), 0, pStr );
418
419         ret = func( hwnd, strW, prop->handle, lParam );
420         HeapFree( GetProcessHeap(), 0, strW );
421         if (!ret) break;
422     }
423     WIN_ReleaseWndPtr(pWnd);
424     return ret;
425 }