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