Moved MAKEINTATOM to winbase.h and added Unicode version.
[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  *              GetPropA (USER32.@)
72  */
73 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
74 {
75     PROPERTY *prop = PROP_FindProp( hwnd, str );
76
77     if (HIWORD(str))
78         TRACE("(%08x,'%s'): returning %08x\n",
79                       hwnd, str, prop ? prop->handle : 0 );
80     else
81         TRACE("(%08x,#%04x): returning %08x\n",
82                       hwnd, LOWORD(str), prop ? prop->handle : 0 );
83
84     return prop ? prop->handle : 0;
85 }
86
87
88 /***********************************************************************
89  *              GetPropW (USER32.@)
90  */
91 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
92 {
93     LPSTR strA;
94     HANDLE ret;
95
96     if (!HIWORD(str)) return GetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
97     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
98     ret = GetPropA( hwnd, strA );
99     HeapFree( GetProcessHeap(), 0, strA );
100     return ret;
101 }
102
103
104 /***********************************************************************
105  *              SetPropA (USER32.@)
106  */
107 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
108 {
109     PROPERTY *prop;
110
111     if (HIWORD(str))
112         TRACE("%04x '%s' %08x\n", hwnd, str, handle );
113     else
114         TRACE("%04x #%04x %08x\n",
115                       hwnd, LOWORD(str), handle );
116
117     if (!(prop = PROP_FindProp( hwnd, str )))
118     {
119         /* We need to create it */
120         WND *pWnd = WIN_FindWndPtr( hwnd );
121         if (!pWnd) return FALSE;
122         if (!(prop = HeapAlloc( GetProcessHeap(), 0, sizeof(*prop) )))
123         {
124             WIN_ReleaseWndPtr(pWnd);
125             return FALSE;
126         }
127         if (!(prop->string = SEGPTR_STRDUP(str)))
128         {
129             HeapFree( GetProcessHeap(), 0, prop );
130             WIN_ReleaseWndPtr(pWnd);
131             return FALSE;
132
133         }
134         prop->next  = pWnd->pProp;
135         pWnd->pProp = prop;
136         WIN_ReleaseWndPtr(pWnd);
137     }
138     prop->handle = handle;
139     return TRUE;
140 }
141
142
143 /***********************************************************************
144  *              SetPropW (USER32.@)
145  */
146 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
147 {
148     BOOL ret;
149     LPSTR strA;
150
151     if (!HIWORD(str))
152         return SetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str), handle );
153     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
154     ret = SetPropA( hwnd, strA, handle );
155     HeapFree( GetProcessHeap(), 0, strA );
156     return ret;
157 }
158
159
160 /***********************************************************************
161  *              RemovePropA (USER32.@)
162  */
163 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
164 {
165     ATOM atom;
166     HANDLE handle;
167     PROPERTY **pprop, *prop;
168     WND *pWnd = WIN_FindWndPtr( hwnd );
169
170     if (HIWORD(str))
171       TRACE("%04x '%s'\n", hwnd, str );
172     else
173       TRACE("%04x #%04x\n", hwnd, LOWORD(str));
174
175
176     if (!pWnd) return (HANDLE)0;
177     if (HIWORD(str))
178     {
179         atom = GlobalFindAtomA( str );
180         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
181         {
182             if (HIWORD((*pprop)->string))
183             {
184                 if (!lstrcmpiA( (*pprop)->string, str )) break;
185             }
186             else if (LOWORD((*pprop)->string) == atom) break;
187         }
188     }
189     else  /* atom */
190     {
191         atom = LOWORD(str);
192         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
193         {
194             if (HIWORD((*pprop)->string))
195             {
196                 if (GlobalFindAtomA( (*pprop)->string ) == atom) break;
197             }
198             else if (LOWORD((*pprop)->string) == atom) break;
199         }
200     }
201     WIN_ReleaseWndPtr(pWnd);
202     if (!*pprop) return 0;
203     prop   = *pprop;
204     handle = prop->handle;
205     *pprop = prop->next;
206     SEGPTR_FREE(prop->string);
207     HeapFree( GetProcessHeap(), 0, prop );
208     return handle;
209 }
210
211
212 /***********************************************************************
213  *              RemovePropW (USER32.@)
214  */
215 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
216 {
217     LPSTR strA;
218     HANDLE ret;
219
220     if (!HIWORD(str))
221         return RemovePropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
222     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
223     ret = RemovePropA( hwnd, strA );
224     HeapFree( GetProcessHeap(), 0, strA );
225     return ret;
226 }
227
228
229 /***********************************************************************
230  *           PROPERTY_RemoveWindowProps
231  *
232  * Remove all properties of a window.
233  */
234 void PROPERTY_RemoveWindowProps( HWND hwnd )
235 {
236     PROPERTY *prop, *next;
237     WND *pWnd = WIN_FindWndPtr( hwnd );
238
239     if (!pWnd) return;
240     for (prop = pWnd->pProp; (prop); prop = next)
241     {
242         next = prop->next;
243         SEGPTR_FREE( prop->string );
244         HeapFree( GetProcessHeap(), 0, prop );
245     }
246     pWnd->pProp = NULL;
247     WIN_ReleaseWndPtr( pWnd );
248 }
249
250
251 /***********************************************************************
252  *              EnumProps (USER.27)
253  */
254 INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
255 {
256     PROPERTY *prop, *next;
257     WND *pWnd;
258     INT16 ret = -1;
259
260     TRACE("%04x %08x\n", hwnd, (UINT)func );
261     if (!(pWnd = WIN_FindWndPtr16( hwnd ))) return -1;
262     for (prop = pWnd->pProp; (prop); prop = next)
263     {
264         /* Already get the next in case the callback */
265         /* function removes the current property.    */
266         next = prop->next;
267
268         /* SDK docu seems to suggest that EnumProps16 does not retrieve
269          * the string in case of an atom handle, in contrast to Win32 */
270
271         TRACE("  Callback: handle=%08x str=%s\n",
272               prop->handle, debugstr_a(prop->string) );
273         ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle );
274         if (!ret) break;
275     }
276     WIN_ReleaseWndPtr(pWnd);
277     return ret;
278 }
279
280
281 /* relay to call the EnumProps callback function from EnumPropsEx */
282 static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPCSTR str, HANDLE handle, ULONG_PTR lparam )
283 {
284     PROPENUMPROCA func = (PROPENUMPROCA)lparam;
285     return func( hwnd, str, handle );
286 }
287
288
289 /***********************************************************************
290  *              EnumPropsA (USER32.@)
291  */
292 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
293 {
294     return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
295 }
296
297
298 /***********************************************************************
299  *              EnumPropsExA (USER32.@)
300  */
301 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
302 {
303     PROPERTY *prop, *next;
304     WND *pWnd;
305     INT ret = -1;
306     char atomStr[MAX_ATOM_LEN+1];
307     char *pStr;
308
309     TRACE("%04x %p %08lx\n", hwnd, func, lParam);
310     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
311     for (prop = pWnd->pProp; (prop); prop = next)
312     {
313         /* Already get the next in case the callback */
314         /* function removes the current property.    */
315         next = prop->next;
316
317         if (!HIWORD(prop->string))
318         { /* get "real" string the atom points to.
319            * This seems to be done for Win32 only */
320             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
321             {
322                 ERR("huh ? Atom %04x not an atom ??\n", LOWORD(prop->string));
323                 atomStr[0] = '\0';
324             }
325             pStr = atomStr;
326         }
327         else
328             pStr = prop->string;
329
330         TRACE("  Callback: handle=%08x str='%s'\n",
331             prop->handle, prop->string );
332
333         ret = func( hwnd, pStr, prop->handle, lParam );
334         if (!ret) break;
335     }
336     WIN_ReleaseWndPtr(pWnd);
337     return ret;
338 }
339
340
341 /* relay to call the EnumProps callback function from EnumPropsEx */
342 static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPCWSTR str, HANDLE handle, ULONG_PTR lparam )
343 {
344     PROPENUMPROCW func = (PROPENUMPROCW)lparam;
345     return func( hwnd, str, handle );
346 }
347
348 /***********************************************************************
349  *              EnumPropsW (USER32.@)
350  */
351 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
352 {
353     return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
354 }
355
356 /***********************************************************************
357  *              EnumPropsExW (USER32.@)
358  */
359 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
360 {
361     PROPERTY *prop, *next;
362     WND *pWnd;
363     INT ret = -1;
364     char atomStr[MAX_ATOM_LEN+1];
365     char *pStr;
366     LPWSTR strW;
367
368     TRACE("%04x %p %08lx\n", hwnd, func, lParam);
369     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
370     for (prop = pWnd->pProp; (prop); prop = next)
371     {
372         /* Already get the next in case the callback */
373         /* function removes the current property.    */
374         next = prop->next;
375
376         if (!HIWORD(prop->string))
377         { /* get "real" string the atom points to.
378            * This seems to be done for Win32 only */
379             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
380             {
381                 ERR("huh ? Atom %04x not an atom ??\n",
382                     (ATOM)LOWORD(prop->string));
383                 atomStr[0] = '\0';
384             }
385             pStr = atomStr;
386         }
387         else
388             pStr = prop->string;
389
390         TRACE("  Callback: handle=%08x str='%s'\n",
391             prop->handle, prop->string );
392
393         strW = HEAP_strdupAtoW( GetProcessHeap(), 0, pStr );
394
395         ret = func( hwnd, strW, prop->handle, lParam );
396         HeapFree( GetProcessHeap(), 0, strW );
397         if (!ret) break;
398     }
399     WIN_ReleaseWndPtr(pWnd);
400     return ret;
401 }