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