Release 961215
[wine] / windows / win.c
1 /*
2  * Window related functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <X11/Xatom.h>
11
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "heap.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "string32.h"
26 #include "queue.h"
27 #include "winpos.h"
28 #include "color.h"
29 #include "shm_main_blk.h"
30 #include "dde_proc.h"
31 #include "clipboard.h"
32 #include "winproc.h"
33 #include "stddebug.h"
34 /* #define DEBUG_WIN  */ 
35 /* #define DEBUG_MENU */
36 #include "debug.h"
37
38 /* Desktop window */
39 static WND *pWndDesktop = NULL;
40
41 static HWND hwndSysModal = 0;
42
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
45
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
47 extern HWND32 CARET_GetHwnd(void);
48 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
49 extern void   WINPOS_CheckActive(HWND32);
50
51 /***********************************************************************
52  *           WIN_FindWndPtr
53  *
54  * Return a pointer to the WND structure corresponding to a HWND.
55  */
56 WND * WIN_FindWndPtr( HWND32 hwnd )
57 {
58     WND * ptr;
59     
60     if (!hwnd || HIWORD(hwnd)) return NULL;
61     ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
62     if (ptr->dwMagic != WND_MAGIC) return NULL;
63     if (ptr->hwndSelf != hwnd)
64     {
65         fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
66                  hwnd, ptr->hwndSelf );
67         return NULL;
68     }
69     return ptr;
70 }
71
72
73 /***********************************************************************
74  *           WIN_DumpWindow
75  *
76  * Dump the content of a window structure to stderr.
77  */
78 void WIN_DumpWindow( HWND32 hwnd )
79 {
80     WND *ptr;
81     char className[80];
82     int i;
83
84     if (!(ptr = WIN_FindWndPtr( hwnd )))
85     {
86         fprintf( stderr, "%04x is not a window handle\n", hwnd );
87         return;
88     }
89
90     if (!GetClassName32A( hwnd, className, sizeof(className ) ))
91         strcpy( className, "#NULL#" );
92
93     fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
94     fprintf( stderr,
95              "next=%p  child=%p  parent=%p  owner=%p  class=%p '%s'\n"
96              "inst=%04x  taskQ=%04x  updRgn=%04x  active=%04x dce=%p  idmenu=%04x\n"
97              "style=%08lx  exstyle=%08lx  wndproc=%08x  text='%s'\n"
98              "client=%d,%d-%d,%d  window=%d,%d-%d,%d  iconpos=%d,%d  maxpos=%d,%d\n"
99              "sysmenu=%04x  flags=%04x  props=%p  vscroll=%p  hscroll=%p\n",
100              ptr->next, ptr->child, ptr->parent, ptr->owner,
101              ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
102              ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
103              ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
104              ptr->text ? ptr->text : "",
105              ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
106              ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
107              ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
108              ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
109              ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
110
111     if (ptr->class->cbWndExtra)
112     {
113         fprintf( stderr, "extra bytes:" );
114         for (i = 0; i < ptr->class->cbWndExtra; i++)
115             fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
116         fprintf( stderr, "\n" );
117     }
118     fprintf( stderr, "\n" );
119 }
120
121
122 /***********************************************************************
123  *           WIN_WalkWindows
124  *
125  * Walk the windows tree and print each window on stderr.
126  */
127 void WIN_WalkWindows( HWND32 hwnd, int indent )
128 {
129     WND *ptr;
130     char className[80];
131
132     ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
133     if (!ptr)
134     {
135         fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
136         return;
137     }
138
139     if (!indent)  /* first time around */
140         fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
141                  "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
142
143     while (ptr)
144     {
145         fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
146
147         GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
148         
149         fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
150                  (DWORD)ptr, ptr->hmemTaskQ, className,
151                  (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
152         
153         if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
154         ptr = ptr->next;
155     }
156 }
157
158
159 /***********************************************************************
160  *           WIN_GetXWindow
161  *
162  * Return the X window associated to a window.
163  */
164 Window WIN_GetXWindow( HWND32 hwnd )
165 {
166     WND *wndPtr = WIN_FindWndPtr( hwnd );
167     while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
168     return wndPtr ? wndPtr->window : 0;
169 }
170
171
172 /***********************************************************************
173  *           WIN_UnlinkWindow
174  *
175  * Remove a window from the siblings linked list.
176  */
177 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
178 {    
179     WND *wndPtr, **ppWnd;
180
181     if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182     ppWnd = &wndPtr->parent->child;
183     while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
184     *ppWnd = wndPtr->next;
185     return TRUE;
186 }
187
188
189 /***********************************************************************
190  *           WIN_LinkWindow
191  *
192  * Insert a window into the siblings linked list.
193  * The window is inserted after the specified window, which can also
194  * be specified as HWND_TOP or HWND_BOTTOM.
195  */
196 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
197 {    
198     WND *wndPtr, **ppWnd;
199
200     if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
201
202     if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
203     {
204         ppWnd = &wndPtr->parent->child;  /* Point to first sibling hwnd */
205         if (hwndInsertAfter == HWND_BOTTOM)  /* Find last sibling hwnd */
206             while (*ppWnd) ppWnd = &(*ppWnd)->next;
207     }
208     else  /* Normal case */
209     {
210         WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
211         if (!afterPtr) return FALSE;
212         ppWnd = &afterPtr->next;
213     }
214     wndPtr->next = *ppWnd;
215     *ppWnd = wndPtr;
216     return TRUE;
217 }
218
219
220 /***********************************************************************
221  *           WIN_FindWinToRepaint
222  *
223  * Find a window that needs repaint.
224  */
225 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
226 {
227     HWND hwndRet;
228     WND *pWnd = pWndDesktop;
229
230     /* Note: the desktop window never gets WM_PAINT messages 
231      * The real reason why is because Windows DesktopWndProc
232      * does ValidateRgn inside WM_ERASEBKGND handler.
233      */
234
235     pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
236
237     for ( ; pWnd ; pWnd = pWnd->next )
238     {
239         if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
240         {
241             dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
242                          pWnd->hwndSelf );
243             continue;
244         }
245         if ((pWnd->hmemTaskQ == hQueue) &&
246             (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
247         
248         if (pWnd->child )
249             if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
250                 return hwndRet;
251     }
252     
253     if (!pWnd) return 0;
254     
255     hwndRet = pWnd->hwndSelf;
256
257     /* look among siblings if we got a transparent window */
258     while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
259                     !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
260     {
261         pWnd = pWnd->next;
262     }
263     if (pWnd) hwndRet = pWnd->hwndSelf;
264     dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
265     return hwndRet;
266 }
267
268
269 /***********************************************************************
270  *           WIN_SendParentNotify
271  *
272  * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
273  * the window has the WS_EX_NOPARENTNOTIFY style.
274  */
275 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
276 {
277     LPPOINT16 lppt = (LPPOINT16)&lValue;
278     WND     *wndPtr = WIN_FindWndPtr( hwnd );
279     BOOL     bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
280
281     /* if lValue contains cursor coordinates they have to be
282      * mapped to the client area of parent window */
283
284     if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
285
286     while (wndPtr)
287     {
288         if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
289            !(wndPtr->dwStyle & WS_CHILD)) break;
290
291         if (bMouse)
292         {
293             lppt->x += wndPtr->rectClient.left;
294             lppt->y += wndPtr->rectClient.top;
295         }
296
297         wndPtr = wndPtr->parent;
298         SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY, 
299                         MAKEWPARAM( event, idChild ), lValue );
300     }
301 }
302
303
304 /***********************************************************************
305  *           WIN_DestroyWindow
306  *
307  * Destroy storage associated to a window. "Internals" p.358
308  */
309 static void WIN_DestroyWindow( WND* wndPtr )
310 {
311     HWND hwnd = wndPtr->hwndSelf;
312     WND* pWnd,*pNext;
313
314     dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
315
316 #ifdef CONFIG_IPC
317     if (main_block)
318         DDE_DestroyWindow(wndPtr->hwndSelf);
319 #endif  /* CONFIG_IPC */
320         
321     /* free child windows */
322
323     pNext = wndPtr->child;
324     while( (pWnd = pNext) )
325     {
326         pNext = pWnd->next;
327         WIN_DestroyWindow( pWnd );
328     }
329
330     SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
331
332     /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
333
334     WINPOS_CheckActive( hwnd );
335     if( hwnd == GetCapture32()) ReleaseCapture();
336
337     /* free resources associated with the window */
338
339     TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
340     PROPERTY_RemoveWindowProps( wndPtr );
341
342     wndPtr->dwMagic = 0;  /* Mark it as invalid */
343     wndPtr->hwndSelf = 0;
344
345     if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
346     {
347         if (wndPtr->hrgnUpdate) DeleteObject32( wndPtr->hrgnUpdate );
348         QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
349     }
350
351     /* toss stale messages from the queue */
352
353     if( wndPtr->hmemTaskQ )
354     {
355       int           pos;
356       MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
357
358       while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 ) 
359               QUEUE_RemoveMsg(msgQ, pos);
360       wndPtr->hmemTaskQ = 0;
361     }
362
363     if (!(wndPtr->dwStyle & WS_CHILD))
364        if (wndPtr->wIDmenu) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
365     if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
366     if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
367     if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
368
369     WINPROC_FreeProc( wndPtr->winproc );
370
371     wndPtr->class->cWindows--;
372     wndPtr->class = NULL;
373
374     USER_HEAP_FREE( hwnd );
375 }
376
377 /***********************************************************************
378  *           WIN_ResetQueueWindows
379  */
380 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
381 {
382     WND* next;
383
384     while (wnd)
385     {
386         next = wnd->next;
387         if (wnd->hmemTaskQ == hQueue)
388            if( hNew ) wnd->hmemTaskQ = hNew;
389            else DestroyWindow( wnd->hwndSelf );
390         else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
391         wnd = next;
392     }
393 }
394
395 /***********************************************************************
396  *           WIN_CreateDesktopWindow
397  *
398  * Create the desktop window.
399  */
400 BOOL32 WIN_CreateDesktopWindow(void)
401 {
402     CLASS *class;
403     HWND hwndDesktop;
404
405     dprintf_win(stddeb,"Creating desktop window\n");
406
407     if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
408         return FALSE;
409
410     hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
411     if (!hwndDesktop) return FALSE;
412     pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
413
414     pWndDesktop->next              = NULL;
415     pWndDesktop->child             = NULL;
416     pWndDesktop->parent            = NULL;
417     pWndDesktop->owner             = NULL;
418     pWndDesktop->class             = class;
419     pWndDesktop->winproc           = NULL;
420     pWndDesktop->dwMagic           = WND_MAGIC;
421     pWndDesktop->hwndSelf          = hwndDesktop;
422     pWndDesktop->hInstance         = 0;
423     pWndDesktop->rectWindow.left   = 0;
424     pWndDesktop->rectWindow.top    = 0;
425     pWndDesktop->rectWindow.right  = SYSMETRICS_CXSCREEN;
426     pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
427     pWndDesktop->rectClient        = pWndDesktop->rectWindow;
428     pWndDesktop->rectNormal        = pWndDesktop->rectWindow;
429     pWndDesktop->ptIconPos.x       = -1;
430     pWndDesktop->ptIconPos.y       = -1;
431     pWndDesktop->ptMaxPos.x        = -1;
432     pWndDesktop->ptMaxPos.y        = -1;
433     pWndDesktop->text              = NULL;
434     pWndDesktop->hmemTaskQ         = 0; /* Desktop does not belong to a task */
435     pWndDesktop->hrgnUpdate        = 0;
436     pWndDesktop->hwndLastActive    = hwndDesktop;
437     pWndDesktop->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN |
438                                      WS_CLIPSIBLINGS;
439     pWndDesktop->dwExStyle         = 0;
440     pWndDesktop->dce               = NULL;
441     pWndDesktop->pVScroll          = NULL;
442     pWndDesktop->pHScroll          = NULL;
443     pWndDesktop->pProp             = NULL;
444     pWndDesktop->wIDmenu           = 0;
445     pWndDesktop->flags             = 0;
446     pWndDesktop->window            = rootWindow;
447     pWndDesktop->hSysMenu          = 0;
448     pWndDesktop->userdata          = 0;
449
450     WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
451     EVENT_RegisterWindow( pWndDesktop );
452     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
453     pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
454     return TRUE;
455 }
456
457
458 /***********************************************************************
459  *           WIN_CreateWindowEx
460  *
461  * Implementation of CreateWindowEx().
462  */
463 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
464                                 BOOL unicode )
465 {
466     CLASS *classPtr;
467     WND *wndPtr;
468     HWND16 hwnd, hwndLinkAfter;
469     POINT16 maxSize, maxPos, minTrack, maxTrack;
470     LRESULT wmcreate;
471
472     dprintf_win( stddeb, "CreateWindowEx: " );
473     if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
474     else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
475     if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
476     else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
477
478     dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
479                  cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
480                  cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
481
482     /* Find the parent window */
483
484     if (cs->hwndParent)
485     {
486         /* Make sure parent is valid */
487         if (!IsWindow( cs->hwndParent ))
488         {
489             fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
490             return 0;
491         }
492     }
493     else if (cs->style & WS_CHILD)
494     {
495         fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
496         return 0;  /* WS_CHILD needs a parent */
497     }
498
499     /* Find the window class */
500
501     if (!(classPtr = CLASS_FindClassByAtom( classAtom,
502                                             GetExePtr(cs->hInstance) )))
503     {
504         char buffer[256];
505         GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
506         fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
507         return 0;
508     }
509
510     /* Fix the coordinates */
511
512     if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
513     if (cs->cx == CW_USEDEFAULT32)
514     {
515 /*        if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
516         else */
517         {
518             cs->cx = 600;
519             cs->cy = 400;
520         }
521     }
522
523     /* Create the window structure */
524
525     if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
526                                   - sizeof(wndPtr->wExtra) )))
527     {
528         dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
529         return 0;
530     }
531
532     /* Fill the window structure */
533
534     wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
535     wndPtr->next  = NULL;
536     wndPtr->child = NULL;
537
538     if (cs->style & WS_CHILD)
539     {
540         wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
541         wndPtr->owner  = NULL;
542     }
543     else
544     {
545         wndPtr->parent = pWndDesktop;
546         if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
547             wndPtr->owner = NULL;
548         else
549             wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
550     }
551
552     wndPtr->window         = 0;
553     wndPtr->class          = classPtr;
554     wndPtr->winproc        = NULL;
555     wndPtr->dwMagic        = WND_MAGIC;
556     wndPtr->hwndSelf       = hwnd;
557     wndPtr->hInstance      = cs->hInstance;
558     wndPtr->ptIconPos.x    = -1;
559     wndPtr->ptIconPos.y    = -1;
560     wndPtr->ptMaxPos.x     = -1;
561     wndPtr->ptMaxPos.y     = -1;
562     wndPtr->text           = NULL;
563     wndPtr->hmemTaskQ      = GetTaskQueue(0);
564     wndPtr->hrgnUpdate     = 0;
565     wndPtr->hwndLastActive = hwnd;
566     wndPtr->dwStyle        = cs->style & ~WS_VISIBLE;
567     wndPtr->dwExStyle      = cs->dwExStyle;
568     wndPtr->wIDmenu        = 0;
569     wndPtr->flags          = 0;
570     wndPtr->pVScroll       = NULL;
571     wndPtr->pHScroll       = NULL;
572     wndPtr->pProp          = NULL;
573     wndPtr->hSysMenu       = MENU_GetDefSysMenu();
574     wndPtr->userdata       = 0;
575
576     if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
577
578     /* Call the WH_CBT hook */
579
580     hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
581
582     if (HOOK_IsHooked( WH_CBT ))
583     {
584         CBT_CREATEWND32A cbtc;
585
586         cbtc.lpcs = cs;
587         cbtc.hwndInsertAfter = hwndLinkAfter;
588         wmcreate = !HOOK_CallHooks32A( WH_CBT, HCBT_CREATEWND, hwnd,
589                                        (LPARAM)&cbtc );
590         if (!wmcreate)
591         {
592             dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
593             USER_HEAP_FREE( hwnd );
594             return 0;
595         }
596     }
597
598     /* Set the window procedure */
599
600     classPtr->cWindows++;
601     WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
602
603     /* Correct the window style */
604
605     if (!(cs->style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
606     {
607         wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
608         wndPtr->flags |= WIN_NEED_SIZE;
609     }
610     if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
611
612     /* Get class or window DC if needed */
613
614     if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
615     else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
616     else wndPtr->dce = NULL;
617
618     /* Insert the window in the linked list */
619
620     WIN_LinkWindow( hwnd, hwndLinkAfter );
621
622     /* Send the WM_GETMINMAXINFO message and fix the size if needed */
623
624     if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
625     {
626         NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
627         if (maxSize.x < cs->cx) cs->cx = maxSize.x;
628         if (maxSize.y < cs->cy) cs->cy = maxSize.y;
629         if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
630         if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
631     }
632     if (cs->cx <= 0) cs->cx = 1;
633     if (cs->cy <= 0) cs->cy = 1;
634
635     wndPtr->rectWindow.left   = cs->x;
636     wndPtr->rectWindow.top    = cs->y;
637     wndPtr->rectWindow.right  = cs->x + cs->cx;
638     wndPtr->rectWindow.bottom = cs->y + cs->cy;
639     wndPtr->rectClient        = wndPtr->rectWindow;
640     wndPtr->rectNormal        = wndPtr->rectWindow;
641
642     /* Create the X window (only for top-level windows, and then only */
643     /* when there's no desktop window) */
644
645     if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
646     {
647         XSetWindowAttributes win_attr;
648
649         if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
650             (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
651         {
652             win_attr.event_mask = ExposureMask | KeyPressMask |
653                                   KeyReleaseMask | PointerMotionMask |
654                                   ButtonPressMask | ButtonReleaseMask |
655                                   FocusChangeMask | StructureNotifyMask;
656             win_attr.override_redirect = FALSE;
657             wndPtr->flags |= WIN_MANAGED;
658         }
659         else
660         {
661             win_attr.event_mask = ExposureMask | KeyPressMask |
662                                   KeyReleaseMask | PointerMotionMask |
663                                   ButtonPressMask | ButtonReleaseMask |
664                                   FocusChangeMask | StructureNotifyMask;
665             win_attr.override_redirect = TRUE;
666         }
667         win_attr.colormap      = COLOR_GetColormap();
668         win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
669         win_attr.save_under    = ((classPtr->style & CS_SAVEBITS) != 0);
670         win_attr.cursor        = CURSORICON_XCursor;
671         wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
672                                         cs->cx, cs->cy, 0, CopyFromParent,
673                                         InputOutput, CopyFromParent,
674                                         CWEventMask | CWOverrideRedirect |
675                                         CWColormap | CWCursor | CWSaveUnder |
676                                         CWBackingStore, &win_attr );
677
678         if ((wndPtr->flags & WIN_MANAGED) &&
679             (cs->dwExStyle & WS_EX_DLGMODALFRAME))
680         {
681             XSizeHints* size_hints = XAllocSizeHints();
682
683             if (size_hints)
684             {
685                 size_hints->min_width = size_hints->max_width = cs->cx;
686                 size_hints->min_height = size_hints->max_height = cs->cy;
687                 size_hints->flags = (PSize | PMinSize | PMaxSize);
688                 XSetWMSizeHints( display, wndPtr->window, size_hints,
689                                  XA_WM_NORMAL_HINTS );
690                 XFree(size_hints);
691             }
692         }
693
694         if (cs->hwndParent)  /* Get window owner */
695         {
696             Window win = WIN_GetXWindow( cs->hwndParent );
697             if (win) XSetTransientForHint( display, wndPtr->window, win );
698         }
699         EVENT_RegisterWindow( wndPtr );
700     }
701
702     /* Set the window menu */
703
704     if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
705     {
706         if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
707         else
708         {
709 #if 0  /* FIXME: should check if classPtr->menuNameW can be used as is */
710             if (classPtr->menuNameA)
711                 cs->hMenu = HIWORD(classPtr->menuNameA) ?
712                        LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
713                        LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
714 #else
715             SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
716             if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
717 #endif
718         }
719         if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
720     }
721     else wndPtr->wIDmenu = (UINT)cs->hMenu;
722
723     /* Send the WM_CREATE message 
724      * Perhaps we shouldn't allow width/height changes as well. 
725      * See p327 in "Internals". 
726      */
727
728     maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
729     if (unicode)
730     {
731         if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
732         else
733         {
734             WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
735                                    NULL, NULL, 0, &wndPtr->rectClient );
736             OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
737                                             maxPos.y - wndPtr->rectWindow.top);
738             wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
739         }
740     }
741     else
742     {
743         if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
744         else
745         {
746             WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
747                                    NULL, NULL, 0, &wndPtr->rectClient );
748             OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
749                                             maxPos.y - wndPtr->rectWindow.top);
750             wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
751         }
752     }
753     
754     if (wmcreate == -1)
755     {
756           /* Abort window creation */
757         dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
758         WIN_UnlinkWindow( hwnd );
759         WIN_DestroyWindow( wndPtr );
760         return 0;
761     }
762
763     /* Send the size messages */
764
765     if (!(wndPtr->flags & WIN_NEED_SIZE))
766     {
767         /* send it anyway */
768         SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
769                    MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
770                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
771         SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
772                                                    wndPtr->rectClient.top ));
773     } 
774
775     WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
776     if (!IsWindow(hwnd)) return 0;
777
778     /* Show the window, maximizing or minimizing if needed */
779
780     if (wndPtr->dwStyle & WS_MINIMIZE)
781     {
782         /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
783
784         wndPtr->dwStyle &= ~WS_MAXIMIZE;
785         WINPOS_FindIconPos( hwnd );
786         SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
787                       SYSMETRICS_CXICON, SYSMETRICS_CYICON, 
788                       SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0)  );
789     }
790     else if (wndPtr->dwStyle & WS_MAXIMIZE)
791     {
792         /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
793
794         NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
795         SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
796             ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
797     }
798     
799     if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
800
801     /* Call WH_SHELL hook */
802
803     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
804         HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
805
806     dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
807     return hwnd;
808 }
809
810
811 /***********************************************************************
812  *           CreateWindow16   (USER.41)
813  */
814 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
815                        DWORD style, INT16 x, INT16 y, INT16 width,
816                        INT16 height, HWND16 parent, HMENU16 menu,
817                        HINSTANCE16 instance, LPVOID data ) 
818 {
819     return CreateWindowEx16( 0, className, windowName, style,
820                            x, y, width, height, parent, menu, instance, data );
821 }
822
823
824 /***********************************************************************
825  *           CreateWindowEx16   (USER.452)
826  */
827 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
828                          DWORD style, INT16 x, INT16 y, INT16 width,
829                          INT16 height, HWND16 parent, HMENU16 menu,
830                          HINSTANCE16 instance, LPVOID data ) 
831 {
832     ATOM classAtom;
833     CREATESTRUCT32A cs;
834
835     /* Find the class atom */
836
837     if (!(classAtom = GlobalFindAtom32A( className )))
838     {
839         fprintf( stderr, "CreateWindowEx16: bad class name " );
840         if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
841         else fprintf( stderr, "'%s'\n", className );
842         return 0;
843     }
844
845     /* Fix the coordinates */
846
847     cs.x  = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
848     cs.y  = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
849     cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
850     cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
851
852     /* Create the window */
853
854     cs.lpCreateParams = data;
855     cs.hInstance      = (HINSTANCE32)instance;
856     cs.hMenu          = (HMENU32)menu;
857     cs.hwndParent     = (HWND32)parent;
858     cs.style          = style;
859     cs.lpszName       = windowName;
860     cs.lpszClass      = className;
861     cs.dwExStyle      = exStyle;
862     return WIN_CreateWindowEx( &cs, classAtom, FALSE );
863 }
864
865
866 /***********************************************************************
867  *           CreateWindowEx32A   (USER32.82)
868  */
869 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
870                           DWORD style, INT32 x, INT32 y, INT32 width,
871                           INT32 height, HWND32 parent, HMENU32 menu,
872                           HINSTANCE32 instance, LPVOID data )
873 {
874     ATOM classAtom;
875     CREATESTRUCT32A cs;
876
877     /* Find the class atom */
878
879     if (!(classAtom = GlobalFindAtom32A( className )))
880     {
881         fprintf( stderr, "CreateWindowEx32A: bad class name " );
882         if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
883         else fprintf( stderr, "'%s'\n", className );
884         return 0;
885     }
886
887     /* Create the window */
888
889     cs.lpCreateParams = data;
890     cs.hInstance      = instance;
891     cs.hMenu          = menu;
892     cs.hwndParent     = parent;
893     cs.x              = x;
894     cs.y              = y;
895     cs.cx             = width;
896     cs.cy             = height;
897     cs.style          = style;
898     cs.lpszName       = windowName;
899     cs.lpszClass      = className;
900     cs.dwExStyle      = exStyle;
901     return WIN_CreateWindowEx( &cs, classAtom, FALSE );
902 }
903
904
905 /***********************************************************************
906  *           CreateWindowEx32W   (USER32.83)
907  */
908 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
909                           DWORD style, INT32 x, INT32 y, INT32 width,
910                           INT32 height, HWND32 parent, HMENU32 menu,
911                           HINSTANCE32 instance, LPVOID data )
912 {
913     ATOM classAtom;
914     CREATESTRUCT32W cs;
915
916     /* Find the class atom */
917
918     if (!(classAtom = GlobalFindAtom32W( className )))
919     {
920         if (HIWORD(className))
921         {
922             LPSTR cn = STRING32_DupUniToAnsi(className);
923             fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
924             free(cn);
925         }
926         else
927             fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
928         return 0;
929     }
930
931     /* Create the window */
932
933     cs.lpCreateParams = data;
934     cs.hInstance      = instance;
935     cs.hMenu          = menu;
936     cs.hwndParent     = parent;
937     cs.x              = x;
938     cs.y              = y;
939     cs.cx             = width;
940     cs.cy             = height;
941     cs.style          = style;
942     cs.lpszName       = windowName;
943     cs.lpszClass      = className;
944     cs.dwExStyle      = exStyle;
945     /* Note: we rely on the fact that CREATESTRUCT32A and */
946     /* CREATESTRUCT32W have the same layout. */
947     return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
948 }
949
950
951 /***********************************************************************
952  *           WIN_CheckFocus
953  */
954 static void WIN_CheckFocus( WND* pWnd )
955 {
956   if( GetFocus16() == pWnd->hwndSelf )
957       SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 ); 
958 }
959
960 /***********************************************************************
961  *           WIN_SendDestroyMsg
962  */
963 static void WIN_SendDestroyMsg( WND* pWnd )
964 {
965   WND*  pChild;
966
967   WIN_CheckFocus(pWnd);
968
969   if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
970   if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd ); 
971   
972   SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
973
974   if( !IsWindow(pWnd->hwndSelf) )
975   {
976     dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
977     return;
978   }
979
980   pChild = pWnd->child;
981   while( pChild )
982   { 
983     WIN_SendDestroyMsg( pChild );
984     pChild = pChild->next;
985   }
986   WIN_CheckFocus(pWnd);
987 }
988
989
990 /***********************************************************************
991  *           DestroyWindow   (USER.53)
992  */
993 BOOL DestroyWindow( HWND hwnd )
994 {
995     WND * wndPtr;
996
997     dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
998     
999       /* Initialization */
1000
1001     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1002     if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1003
1004       /* Call hooks */
1005
1006     if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1007         return FALSE;
1008
1009     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1010     {
1011         HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1012         /* FIXME: clean up palette - see "Internals" p.352 */
1013     }
1014
1015     if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1016          WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1017     if( !IsWindow(hwnd) ) return TRUE;
1018
1019     if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1020
1021       /* Hide the window */
1022
1023     if (wndPtr->dwStyle & WS_VISIBLE)
1024     {
1025         SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1026                       SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
1027                     ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1028         if( !IsWindow(hwnd) ) return TRUE;
1029     }
1030
1031       /* Recursively destroy owned windows */
1032
1033     if( !(wndPtr->dwStyle & WS_CHILD) )
1034     {
1035       for (;;)
1036       {
1037         WND *siblingPtr = wndPtr->parent->child;  /* First sibling */
1038         while (siblingPtr)
1039         {
1040             if (siblingPtr->owner == wndPtr)
1041                if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1042                    break;
1043                else 
1044                    siblingPtr->owner = NULL;
1045             siblingPtr = siblingPtr->next;
1046         }
1047         if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1048         else break;
1049       }
1050
1051       WINPOS_ActivateOtherWindow(wndPtr);
1052
1053       if( wndPtr->owner &&
1054           wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1055           wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1056     }
1057
1058       /* Send destroy messages */
1059
1060     WIN_SendDestroyMsg( wndPtr );
1061     if( !IsWindow(hwnd) ) return TRUE;
1062
1063       /* Unlink now so we won't bother with the children later on */
1064
1065     if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1066
1067       /* Destroy the window storage */
1068
1069     WIN_DestroyWindow( wndPtr );
1070     return TRUE;
1071 }
1072
1073
1074 /***********************************************************************
1075  *           CloseWindow   (USER.43)
1076  */
1077 BOOL CloseWindow(HWND hWnd)
1078 {
1079     WND * wndPtr = WIN_FindWndPtr(hWnd);
1080     if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
1081     ShowWindow(hWnd, SW_MINIMIZE);
1082     return TRUE;
1083 }
1084
1085  
1086 /***********************************************************************
1087  *           OpenIcon   (USER.44)
1088  */
1089 BOOL OpenIcon(HWND hWnd)
1090 {
1091     if (!IsIconic(hWnd)) return FALSE;
1092     ShowWindow(hWnd, SW_SHOWNORMAL);
1093     return(TRUE);
1094 }
1095
1096
1097 /***********************************************************************
1098  *           WIN_FindWindow
1099  *
1100  * Implementation of FindWindow() and FindWindowEx().
1101  */
1102 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1103                             LPCSTR title )
1104 {
1105     WND *pWnd;
1106     CLASS *pClass = NULL;
1107
1108     if (child)
1109     {
1110         if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1111         if (parent)
1112         {
1113             if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1114         }
1115         else if (pWnd->parent != pWndDesktop) return 0;
1116         pWnd = pWnd->next;
1117     }
1118     else
1119     {
1120         if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1121         pWnd = pWnd->child;
1122     }
1123     if (!pWnd) return 0;
1124
1125     /* For a child window, all siblings will have the same hInstance, */
1126     /* so we can look for the class once and for all. */
1127
1128     if (className && (pWnd->dwStyle & WS_CHILD))
1129     {
1130         if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1131             return 0;
1132     }
1133
1134     for ( ; pWnd; pWnd = pWnd->next)
1135     {
1136         if (className && !(pWnd->dwStyle & WS_CHILD))
1137         {
1138             if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1139                 continue;  /* Skip this window */
1140         }
1141         if (pClass && (pWnd->class != pClass))
1142             continue;  /* Not the right class */
1143
1144         /* Now check the title */
1145
1146         if (!title) return pWnd->hwndSelf;
1147         if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1148     }
1149     return 0;
1150 }
1151
1152
1153
1154 /***********************************************************************
1155  *           FindWindow16   (USER.50)
1156  */
1157 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1158 {
1159     return FindWindowEx16( 0, 0, className, title );
1160 }
1161
1162
1163 /***********************************************************************
1164  *           FindWindowEx16   (USER.427)
1165  */
1166 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1167                        SEGPTR className, LPCSTR title )
1168 {
1169     ATOM atom = 0;
1170
1171     if (className)
1172     {
1173         /* If the atom doesn't exist, then no class */
1174         /* with this name exists either. */
1175         if (!(atom = GlobalFindAtom16( className ))) return 0;
1176     }
1177     return WIN_FindWindow( parent, child, atom, title );
1178 }
1179
1180
1181 /***********************************************************************
1182  *           FindWindow32A   (USER32.197)
1183  */
1184 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1185 {
1186     return FindWindowEx32A( 0, 0, className, title );
1187 }
1188
1189
1190 /***********************************************************************
1191  *           FindWindowEx32A   (USER32.198)
1192  */
1193 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1194                         LPCSTR className, LPCSTR title )
1195 {
1196     ATOM atom = 0;
1197
1198     if (className)
1199     {
1200         /* If the atom doesn't exist, then no class */
1201         /* with this name exists either. */
1202         if (!(atom = GlobalFindAtom32A( className ))) return 0;
1203     }
1204     return WIN_FindWindow( 0, 0, atom, title );
1205 }
1206
1207
1208 /***********************************************************************
1209  *           FindWindowEx32W   (USER32.199)
1210  */
1211 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1212                         LPCWSTR className, LPCWSTR title )
1213 {
1214     ATOM atom = 0;
1215     char *buffer;
1216     HWND hwnd;
1217
1218     if (className)
1219     {
1220         /* If the atom doesn't exist, then no class */
1221         /* with this name exists either. */
1222         if (!(atom = GlobalFindAtom32W( className ))) return 0;
1223     }
1224     buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1225     hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1226     if (buffer) free( buffer );
1227     return hwnd;
1228 }
1229
1230
1231 /***********************************************************************
1232  *           FindWindow32W   (USER32.200)
1233  */
1234 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1235 {
1236     return FindWindowEx32W( 0, 0, className, title );
1237 }
1238
1239
1240 /**********************************************************************
1241  *           WIN_GetDesktop
1242  */
1243 WND *WIN_GetDesktop(void)
1244 {
1245     return pWndDesktop;
1246 }
1247
1248
1249 /**********************************************************************
1250  *           GetDesktopWindow16   (USER.286)
1251  */
1252 HWND16 GetDesktopWindow16(void)
1253 {
1254     return (HWND16)pWndDesktop->hwndSelf;
1255 }
1256
1257
1258 /**********************************************************************
1259  *           GetDesktopWindow32   (USER32.231)
1260  */
1261 HWND32 GetDesktopWindow32(void)
1262 {
1263     return pWndDesktop->hwndSelf;
1264 }
1265
1266
1267 /**********************************************************************
1268  *           GetDesktopHwnd   (USER.278)
1269  *
1270  * Exactly the same thing as GetDesktopWindow(), but not documented.
1271  * Don't ask me why...
1272  */
1273 HWND16 GetDesktopHwnd(void)
1274 {
1275     return (HWND16)pWndDesktop->hwndSelf;
1276 }
1277
1278
1279 /*******************************************************************
1280  *           EnableWindow   (USER.34)
1281  */
1282 BOOL EnableWindow( HWND hwnd, BOOL enable )
1283 {
1284     WND *wndPtr;
1285
1286     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1287     if (enable && (wndPtr->dwStyle & WS_DISABLED))
1288     {
1289           /* Enable window */
1290         wndPtr->dwStyle &= ~WS_DISABLED;
1291         SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1292         return TRUE;
1293     }
1294     else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1295     {
1296           /* Disable window */
1297         wndPtr->dwStyle |= WS_DISABLED;
1298         if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1299             SetFocus32( 0 );  /* A disabled window can't have the focus */
1300         if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
1301             ReleaseCapture();  /* A disabled window can't capture the mouse */
1302         SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1303         return FALSE;
1304     }
1305     return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1306 }
1307
1308
1309 /***********************************************************************
1310  *           IsWindowEnabled   (USER.35) (USER32.348)
1311  */ 
1312 BOOL IsWindowEnabled(HWND hWnd)
1313 {
1314     WND * wndPtr; 
1315
1316     if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1317     return !(wndPtr->dwStyle & WS_DISABLED);
1318 }
1319
1320
1321 /***********************************************************************
1322  *           IsWindowUnicode   (USER32.349)
1323  */
1324 BOOL32 IsWindowUnicode( HWND32 hwnd )
1325 {
1326     WND * wndPtr; 
1327
1328     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1329     return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1330 }
1331
1332
1333 /**********************************************************************
1334  *           GetWindowWord    (USER.133) (USER32.313)
1335  */
1336 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1337 {
1338     WND * wndPtr = WIN_FindWndPtr( hwnd );
1339     if (!wndPtr) return 0;
1340     if (offset >= 0)
1341     {
1342         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1343         {
1344             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1345             return 0;
1346         }
1347         return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1348     }
1349     switch(offset)
1350     {
1351     case GWW_ID:         return wndPtr->wIDmenu;
1352     case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1353     case GWW_HINSTANCE:  return (WORD)wndPtr->hInstance;
1354     default:
1355         fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1356         return 0;
1357     }
1358 }
1359
1360
1361 /**********************************************************************
1362  *           WIN_GetWindowInstance
1363  */
1364 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1365 {
1366     WND * wndPtr = WIN_FindWndPtr( hwnd );
1367     if (!wndPtr) return (HINSTANCE16)0;
1368     return wndPtr->hInstance;
1369 }
1370
1371
1372 /**********************************************************************
1373  *           SetWindowWord    (USER.134) (USER32.523)
1374  */
1375 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1376 {
1377     WORD *ptr, retval;
1378     WND * wndPtr = WIN_FindWndPtr( hwnd );
1379     if (!wndPtr) return 0;
1380     if (offset >= 0)
1381     {
1382         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1383         {
1384             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1385             return 0;
1386         }
1387         ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1388     }
1389     else switch(offset)
1390     {
1391         case GWW_ID:        ptr = (WORD *)&wndPtr->wIDmenu; break;
1392         case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1393         case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1394         default:
1395             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1396             return 0;
1397     }
1398     retval = *ptr;
1399     *ptr = newval;
1400     return retval;
1401 }
1402
1403
1404 /**********************************************************************
1405  *           WIN_GetWindowLong
1406  *
1407  * Helper function for GetWindowLong().
1408  */
1409 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1410 {
1411     LONG retval;
1412     WND * wndPtr = WIN_FindWndPtr( hwnd );
1413     if (!wndPtr) return 0;
1414     if (offset >= 0)
1415     {
1416         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1417         {
1418             fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1419             return 0;
1420         }
1421         retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1422         /* Special case for dialog window procedure */
1423         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1424             return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1425         return retval;
1426     }
1427     switch(offset)
1428     {
1429         case GWL_USERDATA:   return wndPtr->userdata;
1430         case GWL_STYLE:      return wndPtr->dwStyle;
1431         case GWL_EXSTYLE:    return wndPtr->dwExStyle;
1432         case GWL_ID:         return wndPtr->wIDmenu;
1433         case GWL_WNDPROC:    return (LONG)WINPROC_GetProc( wndPtr->winproc,
1434                                                            type );
1435         case GWL_HWNDPARENT: return wndPtr->parent ?
1436                                         (HWND32)wndPtr->parent->hwndSelf : 0;
1437         case GWL_HINSTANCE:  return (HINSTANCE32)wndPtr->hInstance;
1438         default:
1439             fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1440     }
1441     return 0;
1442 }
1443
1444
1445 /**********************************************************************
1446  *           WIN_SetWindowLong
1447  *
1448  * Helper function for SetWindowLong().
1449  */
1450 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1451                                WINDOWPROCTYPE type )
1452 {
1453     LONG *ptr, retval;
1454     WND * wndPtr = WIN_FindWndPtr( hwnd );
1455     if (!wndPtr) return 0;
1456     if (offset >= 0)
1457     {
1458         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1459         {
1460             fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1461             return 0;
1462         }
1463         ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1464         /* Special case for dialog window procedure */
1465         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1466         {
1467             retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1468             WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1469             return retval;
1470         }
1471     }
1472     else switch(offset)
1473     {
1474         case GWL_ID:
1475         case GWL_HINSTANCE:
1476             return SetWindowWord( hwnd, offset, (WORD)newval );
1477         case GWL_WNDPROC:
1478             retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1479             WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1480             return retval;
1481         case GWL_STYLE:
1482             ptr = &wndPtr->dwStyle;
1483             /* Some bits can't be changed this way */
1484             newval &= ~(WS_VISIBLE | WS_CHILD);
1485             newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1486             break;
1487         case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1488         case GWL_EXSTYLE:  ptr = &wndPtr->dwExStyle; break;
1489         default:
1490             fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1491             return 0;
1492     }
1493     retval = *ptr;
1494     *ptr = newval;
1495     return retval;
1496 }
1497
1498
1499 /**********************************************************************
1500  *           GetWindowLong16    (USER.135)
1501  */
1502 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1503 {
1504     return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1505 }
1506
1507
1508 /**********************************************************************
1509  *           GetWindowLong32A    (USER32.304)
1510  */
1511 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1512 {
1513     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1514 }
1515
1516
1517 /**********************************************************************
1518  *           GetWindowLong32W    (USER32.305)
1519  */
1520 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1521 {
1522     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1523 }
1524
1525
1526 /**********************************************************************
1527  *           SetWindowLong16    (USER.136)
1528  */
1529 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1530 {
1531     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1532 }
1533
1534
1535 /**********************************************************************
1536  *           SetWindowLong32A    (USER32.516)
1537  */
1538 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1539 {
1540     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1541 }
1542
1543
1544 /**********************************************************************
1545  *           SetWindowLong32W    (USER32.517)
1546  */
1547 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1548 {
1549     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1550 }
1551
1552
1553 /*******************************************************************
1554  *           GetWindowText16    (USER.36)
1555  */
1556 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1557 {
1558     return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1559 }
1560
1561
1562 /*******************************************************************
1563  *           GetWindowText32A    (USER32.308)
1564  */
1565 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1566 {
1567     return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1568                                   (LPARAM)lpString );
1569 }
1570
1571
1572 /*******************************************************************
1573  *           GetWindowText32W    (USER32.311)
1574  */
1575 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1576 {
1577     return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1578                                   (LPARAM)lpString );
1579 }
1580
1581
1582 /*******************************************************************
1583  *           SetWindowText16    (USER.37)
1584  */
1585 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1586 {
1587     SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1588 }
1589
1590
1591 /*******************************************************************
1592  *           SetWindowText32A    (USER32.)
1593  */
1594 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1595 {
1596     SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1597 }
1598
1599
1600 /*******************************************************************
1601  *           SetWindowText32W    (USER32.)
1602  */
1603 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1604 {
1605     SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1606 }
1607
1608
1609 /*******************************************************************
1610  *         GetWindowTextLength16    (USER.38)
1611  */
1612 INT16 GetWindowTextLength16( HWND16 hwnd )
1613 {
1614     return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1615 }
1616
1617
1618 /*******************************************************************
1619  *         GetWindowTextLength32A   (USER32.309)
1620  */
1621 INT32 GetWindowTextLength32A( HWND32 hwnd )
1622 {
1623     return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1624 }
1625
1626 /*******************************************************************
1627  *         GetWindowTextLength32W   (USER32.309)
1628  */
1629 INT32 GetWindowTextLength32W( HWND32 hwnd )
1630 {
1631     return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1632 }
1633
1634 /*******************************************************************
1635  *         IsWindow   (USER.47) (USER32.347)
1636  */
1637 BOOL16 IsWindow( HWND32 hwnd )
1638 {
1639     WND * wndPtr = WIN_FindWndPtr( hwnd );
1640     return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1641 }
1642
1643
1644 /*****************************************************************
1645  *         GetParent16   (USER.46)
1646  */
1647 HWND16 GetParent16( HWND16 hwnd )
1648 {
1649     return (HWND16)GetParent32( hwnd );
1650 }
1651
1652
1653 /*****************************************************************
1654  *         GetParent32   (USER32.277)
1655  */
1656 HWND32 GetParent32( HWND32 hwnd )
1657 {
1658     WND *wndPtr = WIN_FindWndPtr(hwnd);
1659     if (!wndPtr) return 0;
1660     wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1661     return wndPtr ? wndPtr->hwndSelf : 0;
1662 }
1663
1664
1665 /*****************************************************************
1666  *         WIN_GetTopParent
1667  *
1668  * Get the top-level parent for a child window.
1669  */
1670 HWND32 WIN_GetTopParent( HWND32 hwnd )
1671 {
1672     WND *wndPtr = WIN_FindWndPtr( hwnd );
1673     while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1674     return wndPtr ? wndPtr->hwndSelf : 0;
1675 }
1676
1677
1678 /*****************************************************************
1679  *         SetParent              (USER.233)
1680  */
1681 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1682 {
1683     HWND oldParent;
1684
1685     WND *wndPtr = WIN_FindWndPtr(hwndChild);
1686     WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1687     if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1688
1689     oldParent = wndPtr->parent->hwndSelf;
1690
1691     WIN_UnlinkWindow(hwndChild);
1692     if (hwndNewParent) wndPtr->parent = pWndParent;
1693     WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1694     
1695     if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1696     
1697     return oldParent;
1698 }
1699
1700
1701
1702 /*******************************************************************
1703  *         IsChild    (USER.48)
1704  */
1705 BOOL IsChild( HWND parent, HWND child )
1706 {
1707     WND * wndPtr = WIN_FindWndPtr( child );
1708     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1709     {
1710         wndPtr = wndPtr->parent;
1711         if (wndPtr->hwndSelf == parent) return TRUE;
1712     }
1713     return FALSE;
1714 }
1715
1716
1717 /***********************************************************************
1718  *           IsWindowVisible   (USER.49) (USER32.350)
1719  */
1720 BOOL IsWindowVisible( HWND hwnd )
1721 {
1722     WND *wndPtr = WIN_FindWndPtr( hwnd );
1723     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1724     {
1725         if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1726         wndPtr = wndPtr->parent;
1727     }
1728     return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1729 }
1730
1731 /***********************************************************************
1732  *           WIN_IsWindowDrawable
1733  * 
1734  * hwnd is drawable when it is visible, all parents are not 
1735  * minimized, and it is itself not minimized unless we are 
1736  * trying to draw icon and the default class icon is set.
1737  */
1738 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1739 {
1740   HWND   hwnd= wnd->hwndSelf;
1741   BOOL32 yes = TRUE;
1742
1743   while(wnd && yes)
1744   { 
1745     if( wnd->dwStyle & WS_MINIMIZE )
1746         if( wnd->hwndSelf != hwnd ) break;
1747         else if( icon && wnd->class->hIcon ) break;
1748
1749     yes = yes && (wnd->dwStyle & WS_VISIBLE);
1750     wnd = wnd->parent; }      
1751   return (!wnd && yes);
1752 }
1753
1754 /*******************************************************************
1755  *         GetTopWindow    (USER.229)
1756  */
1757 HWND GetTopWindow( HWND hwnd )
1758 {
1759     WND * wndPtr = WIN_FindWndPtr( hwnd );
1760     if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1761     else return 0;
1762 }
1763
1764
1765 /*******************************************************************
1766  *         GetWindow    (USER.262)
1767  */
1768 HWND GetWindow( HWND hwnd, WORD rel )
1769 {
1770     WND * wndPtr = WIN_FindWndPtr( hwnd );
1771     if (!wndPtr) return 0;
1772     switch(rel)
1773     {
1774     case GW_HWNDFIRST:
1775         if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1776         else return 0;
1777         
1778     case GW_HWNDLAST:
1779         if (!wndPtr->parent) return 0;  /* Desktop window */
1780         while (wndPtr->next) wndPtr = wndPtr->next;
1781         return wndPtr->hwndSelf;
1782         
1783     case GW_HWNDNEXT:
1784         if (!wndPtr->next) return 0;
1785         return wndPtr->next->hwndSelf;
1786         
1787     case GW_HWNDPREV:
1788         if (!wndPtr->parent) return 0;  /* Desktop window */
1789         wndPtr = wndPtr->parent->child;  /* First sibling */
1790         if (wndPtr->hwndSelf == hwnd) return 0;  /* First in list */
1791         while (wndPtr->next)
1792         {
1793             if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1794             wndPtr = wndPtr->next;
1795         }
1796         return 0;
1797         
1798     case GW_OWNER:
1799         return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1800
1801     case GW_CHILD:
1802         return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1803     }
1804     return 0;
1805 }
1806
1807
1808 /*******************************************************************
1809  *         GetNextWindow    (USER.230)
1810  */
1811 HWND GetNextWindow( HWND hwnd, WORD flag )
1812 {
1813     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1814     return GetWindow( hwnd, flag );
1815 }
1816
1817 /*******************************************************************
1818  *         ShowOwnedPopups  (USER.265)
1819  */
1820 void ShowOwnedPopups( HWND owner, BOOL fShow )
1821 {
1822     WND *pWnd = pWndDesktop->child;
1823     while (pWnd)
1824     {
1825         if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1826             (pWnd->dwStyle & WS_POPUP))
1827             ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1828         pWnd = pWnd->next;
1829     }
1830 }
1831
1832
1833 /*******************************************************************
1834  *         GetLastActivePopup    (USER.287)
1835  */
1836 HWND GetLastActivePopup(HWND hwnd)
1837 {
1838     WND *wndPtr;
1839     wndPtr = WIN_FindWndPtr(hwnd);
1840     if (wndPtr == NULL) return hwnd;
1841     return wndPtr->hwndLastActive;
1842 }
1843
1844
1845 /*******************************************************************
1846  *           WIN_BuildWinArray
1847  *
1848  * Build an array of pointers to all children of a given window.
1849  * The array must be freed with HeapFree(SystemHeap).
1850  */
1851 WND **WIN_BuildWinArray( WND *wndPtr )
1852 {
1853     WND **list, **ppWnd;
1854     WND *pWnd;
1855     INT32 count;
1856
1857     /* First count the windows */
1858
1859     if (!wndPtr) wndPtr = pWndDesktop;
1860     for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1861     count++;  /* For the terminating NULL */
1862
1863     /* Now build the list of all windows */
1864
1865     if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1866         return NULL;
1867     for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1868         *ppWnd++ = pWnd;
1869     *ppWnd = NULL;
1870     return list;
1871 }
1872
1873
1874 /*******************************************************************
1875  *           EnumWindows16   (USER.54)
1876  */
1877 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1878 {
1879     WND **list, **ppWnd;
1880
1881     /* We have to build a list of all windows first, to avoid */
1882     /* unpleasant side-effects, for instance if the callback  */
1883     /* function changes the Z-order of the windows.           */
1884
1885     if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1886
1887     /* Now call the callback function for every window */
1888
1889     for (ppWnd = list; *ppWnd; ppWnd++)
1890     {
1891         /* Make sure that the window still exists */
1892         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1893         if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1894     }
1895     HeapFree( SystemHeap, 0, list );
1896     return TRUE;
1897 }
1898
1899
1900 /*******************************************************************
1901  *           EnumWindows32   (USER32.192)
1902  */
1903 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1904 {
1905     return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1906 }
1907
1908
1909 /**********************************************************************
1910  *           EnumTaskWindows16   (USER.225)
1911  */
1912 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1913 {
1914     WND **list, **ppWnd;
1915     HQUEUE16 hQueue = GetTaskQueue( hTask );
1916
1917     /* This function is the same as EnumWindows(),    */
1918     /* except for an added check on the window queue. */
1919
1920     if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1921
1922     /* Now call the callback function for every window */
1923
1924     for (ppWnd = list; *ppWnd; ppWnd++)
1925     {
1926         /* Make sure that the window still exists */
1927         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1928         if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
1929         if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1930     }
1931     HeapFree( SystemHeap, 0, list );
1932     return TRUE;
1933 }
1934
1935
1936 /**********************************************************************
1937  *           EnumThreadWindows   (USER32.189)
1938  */
1939 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1940 {
1941     return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1942 }
1943
1944
1945 /**********************************************************************
1946  *           WIN_EnumChildWindows
1947  *
1948  * Helper function for EnumChildWindows().
1949  */
1950 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1951                                     LPARAM lParam )
1952 {
1953     WND **childList;
1954     BOOL16 ret = FALSE;
1955
1956     while (*ppWnd)
1957     {
1958         /* Make sure that the window still exists */
1959         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1960         /* Build children list first */
1961         if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1962         if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1963         ret = WIN_EnumChildWindows( childList, func, lParam );
1964         HeapFree( SystemHeap, 0, childList );
1965         if (!ret) return FALSE;
1966         ppWnd++;
1967     }
1968     return TRUE;
1969 }
1970
1971
1972 /**********************************************************************
1973  *           EnumChildWindows16   (USER.55)
1974  */
1975 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1976 {
1977     WND **list, *pParent;
1978
1979     if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1980     if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1981     WIN_EnumChildWindows( list, func, lParam );
1982     HeapFree( SystemHeap, 0, list );
1983     return TRUE;
1984 }
1985
1986
1987 /**********************************************************************
1988  *           EnumChildWindows32   (USER32.177)
1989  */
1990 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1991 {
1992     return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1993                                        lParam );
1994 }
1995
1996
1997 /*******************************************************************
1998  *           AnyPopup   (USER.52)
1999  */
2000 BOOL AnyPopup(void)
2001 {
2002     WND *wndPtr;
2003     for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2004         if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2005     return FALSE;
2006 }
2007
2008 /*******************************************************************
2009  *                      FlashWindow             [USER.105]
2010  */
2011 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
2012 {
2013     WND *wndPtr = WIN_FindWndPtr(hWnd);
2014
2015     dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2016
2017     if (!wndPtr) return FALSE;
2018
2019     if (wndPtr->dwStyle & WS_MINIMIZE)
2020     {
2021         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2022         {
2023             HDC32 hDC = GetDC32(hWnd);
2024             
2025             if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2026                 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2027             
2028             ReleaseDC32( hWnd, hDC );
2029             wndPtr->flags |= WIN_NCACTIVATED;
2030         }
2031         else
2032         {
2033             PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2034                                           RDW_UPDATENOW | RDW_FRAME, 0 );
2035             wndPtr->flags &= ~WIN_NCACTIVATED;
2036         }
2037         return TRUE;
2038     }
2039     else
2040     {
2041         WPARAM16 wparam;
2042         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2043         else wparam = (hWnd == GetActiveWindow());
2044
2045         SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2046         return wparam;
2047     }
2048 }
2049
2050
2051 /*******************************************************************
2052  *           SetSysModalWindow16   (USER.188)
2053  */
2054 HWND16 SetSysModalWindow16( HWND16 hWnd )
2055 {
2056     HWND hWndOldModal = hwndSysModal;
2057     hwndSysModal = hWnd;
2058     dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2059     return hWndOldModal;
2060 }
2061
2062
2063 /*******************************************************************
2064  *           GetSysModalWindow16   (USER.52)
2065  */
2066 HWND16 GetSysModalWindow16(void)
2067 {
2068     return hwndSysModal;
2069 }
2070
2071
2072 /*******************************************************************
2073  *                      DRAG_QueryUpdate
2074  *
2075  * recursively find a child that contains spDragInfo->pt point 
2076  * and send WM_QUERYDROPOBJECT
2077  */
2078 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2079 {
2080  BOOL16         wParam,bResult = 0;
2081  POINT16        pt;
2082  LPDRAGINFO     ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2083  WND           *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2084  RECT16         tempRect;
2085
2086  if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2087
2088  pt             = ptrDragInfo->pt;
2089
2090  GetWindowRect16(hQueryWnd,&tempRect); 
2091
2092  if( !PtInRect16(&tempRect,pt) ||
2093      (ptrQueryWnd->dwStyle & WS_DISABLED) )
2094         return 0;
2095
2096  if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) ) 
2097    {
2098      tempRect = ptrQueryWnd->rectClient;
2099      if(ptrQueryWnd->dwStyle & WS_CHILD)
2100         MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2101
2102      if( PtInRect16(&tempRect,pt) )
2103         {
2104          wParam = 0;
2105          
2106          for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2107              if( ptrWnd->dwStyle & WS_VISIBLE )
2108              {
2109                  GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2110
2111                  if( PtInRect16(&tempRect,pt) ) 
2112                      break;
2113              }
2114
2115          if(ptrWnd)
2116          {
2117             dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2118                         ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2119                         ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2120             if( !(ptrWnd->dwStyle & WS_DISABLED) )
2121                 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2122          }
2123
2124          if(bResult) return bResult;
2125         }
2126      else wParam = 1;
2127    }
2128  else wParam = 1;
2129
2130  ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2131
2132  ptrDragInfo->hScope = hQueryWnd;
2133
2134  bResult = ( bNoSend ) 
2135            ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2136            : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2137                           (WPARAM16)wParam ,(LPARAM) spDragInfo );
2138  if( !bResult ) 
2139       ptrDragInfo->pt = pt;
2140
2141  return bResult;
2142 }
2143
2144 /*******************************************************************
2145  *                      DragDetect ( USER.465 )
2146  *
2147  */
2148 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2149 {
2150   MSG16 msg;
2151   RECT16  rect;
2152
2153   rect.left = pt.x - wDragWidth;
2154   rect.right = pt.x + wDragWidth;
2155
2156   rect.top = pt.y - wDragHeight;
2157   rect.bottom = pt.y + wDragHeight;
2158
2159   SetCapture32(hWnd);
2160
2161   while(1)
2162    {
2163         while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2164          {
2165            if( msg.message == WM_LBUTTONUP )
2166                 {
2167                   ReleaseCapture();
2168                   return 0;
2169                 }
2170            if( msg.message == WM_MOUSEMOVE )
2171                 {
2172                   if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2173                     {
2174                       ReleaseCapture();
2175                       return 1;
2176                     }
2177                 }
2178          }
2179         WaitMessage();
2180    }
2181
2182   return 0;
2183 }
2184
2185 /******************************************************************************
2186  *                              DragObject ( USER.464 )
2187  *
2188  */
2189 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE16 hOfStruct,
2190                 WORD szList , HCURSOR16 hCursor)
2191 {
2192  MSG16          msg;
2193  LPDRAGINFO     lpDragInfo;
2194  SEGPTR         spDragInfo;
2195  HCURSOR16      hDragCursor=0, hOldCursor=0, hBummer=0;
2196  HGLOBAL16      hDragInfo  = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2197  WND           *wndPtr = WIN_FindWndPtr(hWnd);
2198  DWORD          dwRet = 0;
2199  short          dragDone = 0;
2200  HCURSOR16      hCurrentCursor = 0;
2201  HWND           hCurrentWnd = 0;
2202  BOOL16         b;
2203
2204  lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2205  spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2206
2207  if( !lpDragInfo || !spDragInfo ) return 0L;
2208
2209  hBummer = LoadCursor16(0,IDC_BUMMER);
2210
2211  if( !hBummer || !wndPtr )
2212    {
2213         GlobalFree16(hDragInfo);
2214         return 0L;
2215    }
2216
2217  if(hCursor)
2218    {
2219         if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2220           {
2221            GlobalFree16(hDragInfo);
2222            return 0L;
2223           }
2224
2225         if( hDragCursor == hCursor ) hDragCursor = 0;
2226         else hCursor = hDragCursor;
2227
2228         hOldCursor = SetCursor(hDragCursor);
2229    }
2230
2231  lpDragInfo->hWnd   = hWnd;
2232  lpDragInfo->hScope = 0;
2233  lpDragInfo->wFlags = wObj;
2234  lpDragInfo->hList  = szList; /* near pointer! */
2235  lpDragInfo->hOfStruct = hOfStruct;
2236  lpDragInfo->l = 0L; 
2237
2238  SetCapture32(hWnd);
2239  ShowCursor(1);
2240
2241  while( !dragDone )
2242   {
2243     WaitMessage();
2244
2245     if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2246          continue;
2247
2248    *(lpDragInfo+1) = *lpDragInfo;
2249
2250     lpDragInfo->pt = msg.pt;
2251
2252     /* update DRAGINFO struct */
2253     dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2254
2255     if( (b = DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE)) > 0 )
2256          hCurrentCursor = hCursor;
2257     else
2258         {
2259          hCurrentCursor = hBummer;
2260          lpDragInfo->hScope = 0;
2261         }
2262     if( hCurrentCursor )
2263         SetCursor(hCurrentCursor);
2264
2265     dprintf_msg(stddeb,"drag: got %04x\n", b);
2266
2267     /* send WM_DRAGLOOP */
2268     SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer) , 
2269                                     (LPARAM) spDragInfo );
2270     /* send WM_DRAGSELECT or WM_DRAGMOVE */
2271     if( hCurrentWnd != lpDragInfo->hScope )
2272         {
2273          if( hCurrentWnd )
2274            SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0, 
2275                        (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2276                                         HIWORD(spDragInfo)) );
2277          hCurrentWnd = lpDragInfo->hScope;
2278          if( hCurrentWnd )
2279            SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo); 
2280         }
2281     else
2282         if( hCurrentWnd )
2283            SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2284
2285
2286     /* check if we're done */
2287     if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2288         dragDone = TRUE;
2289   }
2290
2291  ReleaseCapture();
2292  ShowCursor(0);
2293
2294  if( hCursor )
2295    {
2296      SetCursor(hOldCursor);
2297      if( hDragCursor )
2298          DestroyCursor(hDragCursor);
2299    }
2300
2301  if( hCurrentCursor != hBummer ) 
2302         dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT, 
2303                                (WPARAM16)hWnd, (LPARAM)spDragInfo );
2304  GlobalFree16(hDragInfo);
2305
2306  return dwRet;
2307 }
2308