Release 970720
[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     if (className)
1176     {
1177         /* If the atom doesn't exist, then no class */
1178         /* with this name exists either. */
1179         if (!(atom = GlobalFindAtom16( className ))) return 0;
1180     }
1181     return WIN_FindWindow( parent, child, atom, title );
1182 }
1183
1184
1185 /***********************************************************************
1186  *           FindWindow32A   (USER32.197)
1187  */
1188 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1189 {
1190     return FindWindowEx32A( 0, 0, className, title );
1191 }
1192
1193
1194 /***********************************************************************
1195  *           FindWindowEx32A   (USER32.198)
1196  */
1197 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1198                         LPCSTR className, LPCSTR title )
1199 {
1200     ATOM atom = 0;
1201
1202     if (className)
1203     {
1204         /* If the atom doesn't exist, then no class */
1205         /* with this name exists either. */
1206         if (!(atom = GlobalFindAtom32A( className ))) return 0;
1207     }
1208     return WIN_FindWindow( 0, 0, atom, title );
1209 }
1210
1211
1212 /***********************************************************************
1213  *           FindWindowEx32W   (USER32.199)
1214  */
1215 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1216                         LPCWSTR className, LPCWSTR title )
1217 {
1218     ATOM atom = 0;
1219     char *buffer;
1220     HWND32 hwnd;
1221
1222     if (className)
1223     {
1224         /* If the atom doesn't exist, then no class */
1225         /* with this name exists either. */
1226         if (!(atom = GlobalFindAtom32W( className ))) return 0;
1227     }
1228     buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1229     hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1230     HeapFree( GetProcessHeap(), 0, buffer );
1231     return hwnd;
1232 }
1233
1234
1235 /***********************************************************************
1236  *           FindWindow32W   (USER32.200)
1237  */
1238 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1239 {
1240     return FindWindowEx32W( 0, 0, className, title );
1241 }
1242
1243
1244 /**********************************************************************
1245  *           WIN_GetDesktop
1246  */
1247 WND *WIN_GetDesktop(void)
1248 {
1249     return pWndDesktop;
1250 }
1251
1252
1253 /**********************************************************************
1254  *           GetDesktopWindow16   (USER.286)
1255  */
1256 HWND16 GetDesktopWindow16(void)
1257 {
1258     return (HWND16)pWndDesktop->hwndSelf;
1259 }
1260
1261
1262 /**********************************************************************
1263  *           GetDesktopWindow32   (USER32.231)
1264  */
1265 HWND32 GetDesktopWindow32(void)
1266 {
1267     return pWndDesktop->hwndSelf;
1268 }
1269
1270
1271 /**********************************************************************
1272  *           GetDesktopHwnd   (USER.278)
1273  *
1274  * Exactly the same thing as GetDesktopWindow(), but not documented.
1275  * Don't ask me why...
1276  */
1277 HWND16 GetDesktopHwnd(void)
1278 {
1279     return (HWND16)pWndDesktop->hwndSelf;
1280 }
1281
1282
1283 /*******************************************************************
1284  *           EnableWindow16   (USER.34)
1285  */
1286 BOOL16 EnableWindow16( HWND16 hwnd, BOOL16 enable )
1287 {
1288     return EnableWindow32( hwnd, enable );
1289 }
1290
1291
1292 /*******************************************************************
1293  *           EnableWindow32   (USER32.171)
1294  */
1295 BOOL32 EnableWindow32( HWND32 hwnd, BOOL32 enable )
1296 {
1297     WND *wndPtr;
1298
1299     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1300     if (enable && (wndPtr->dwStyle & WS_DISABLED))
1301     {
1302           /* Enable window */
1303         wndPtr->dwStyle &= ~WS_DISABLED;
1304         SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1305         return TRUE;
1306     }
1307     else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1308     {
1309           /* Disable window */
1310         wndPtr->dwStyle |= WS_DISABLED;
1311         if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1312             SetFocus32( 0 );  /* A disabled window can't have the focus */
1313         if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1314             ReleaseCapture();  /* A disabled window can't capture the mouse */
1315         SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1316         return FALSE;
1317     }
1318     return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1319 }
1320
1321
1322 /***********************************************************************
1323  *           IsWindowEnabled16   (USER.35)
1324  */ 
1325 BOOL16 IsWindowEnabled16(HWND16 hWnd)
1326 {
1327     return IsWindowEnabled32(hWnd);
1328 }
1329
1330
1331 /***********************************************************************
1332  *           IsWindowEnabled32   (USER32.348)
1333  */ 
1334 BOOL32 IsWindowEnabled32(HWND32 hWnd)
1335 {
1336     WND * wndPtr; 
1337
1338     if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1339     return !(wndPtr->dwStyle & WS_DISABLED);
1340 }
1341
1342
1343 /***********************************************************************
1344  *           IsWindowUnicode   (USER32.349)
1345  */
1346 BOOL32 IsWindowUnicode( HWND32 hwnd )
1347 {
1348     WND * wndPtr; 
1349
1350     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1351     return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1352 }
1353
1354
1355 /**********************************************************************
1356  *           GetWindowWord16    (USER.133)
1357  */
1358 WORD GetWindowWord16( HWND16 hwnd, INT16 offset )
1359 {
1360     return GetWindowWord32( hwnd, offset );
1361 }
1362
1363
1364 /**********************************************************************
1365  *           GetWindowWord32    (USER32.313)
1366  */
1367 WORD GetWindowWord32( HWND32 hwnd, INT32 offset )
1368 {
1369     WND * wndPtr = WIN_FindWndPtr( hwnd );
1370     if (!wndPtr) return 0;
1371     if (offset >= 0)
1372     {
1373         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1374         {
1375             fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1376             return 0;
1377         }
1378         return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1379     }
1380     switch(offset)
1381     {
1382     case GWW_ID:         return wndPtr->wIDmenu;
1383     case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1384     case GWW_HINSTANCE:  return (WORD)wndPtr->hInstance;
1385     default:
1386         fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1387         return 0;
1388     }
1389 }
1390
1391
1392 /**********************************************************************
1393  *           WIN_GetWindowInstance
1394  */
1395 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1396 {
1397     WND * wndPtr = WIN_FindWndPtr( hwnd );
1398     if (!wndPtr) return (HINSTANCE16)0;
1399     return wndPtr->hInstance;
1400 }
1401
1402
1403 /**********************************************************************
1404  *           SetWindowWord16    (USER.134)
1405  */
1406 WORD SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1407 {
1408     return SetWindowWord32( hwnd, offset, newval );
1409 }
1410
1411
1412 /**********************************************************************
1413  *           SetWindowWord32    (USER32.523)
1414  */
1415 WORD SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1416 {
1417     WORD *ptr, retval;
1418     WND * wndPtr = WIN_FindWndPtr( hwnd );
1419     if (!wndPtr) return 0;
1420     if (offset >= 0)
1421     {
1422         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1423         {
1424             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1425             return 0;
1426         }
1427         ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1428     }
1429     else switch(offset)
1430     {
1431         case GWW_ID:        ptr = (WORD *)&wndPtr->wIDmenu; break;
1432         case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1433         case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1434         default:
1435             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1436             return 0;
1437     }
1438     retval = *ptr;
1439     *ptr = newval;
1440     return retval;
1441 }
1442
1443
1444 /**********************************************************************
1445  *           WIN_GetWindowLong
1446  *
1447  * Helper function for GetWindowLong().
1448  */
1449 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1450 {
1451     LONG retval;
1452     WND * wndPtr = WIN_FindWndPtr( hwnd );
1453     if (!wndPtr) return 0;
1454     if (offset >= 0)
1455     {
1456         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1457         {
1458             fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1459             return 0;
1460         }
1461         retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1462         /* Special case for dialog window procedure */
1463         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1464             return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1465         return retval;
1466     }
1467     switch(offset)
1468     {
1469         case GWL_USERDATA:   return wndPtr->userdata;
1470         case GWL_STYLE:      return wndPtr->dwStyle;
1471         case GWL_EXSTYLE:    return wndPtr->dwExStyle;
1472         case GWL_ID:         return wndPtr->wIDmenu;
1473         case GWL_WNDPROC:    return (LONG)WINPROC_GetProc( wndPtr->winproc,
1474                                                            type );
1475         case GWL_HWNDPARENT: return wndPtr->parent ?
1476                                         (HWND32)wndPtr->parent->hwndSelf : 0;
1477         case GWL_HINSTANCE:  return (HINSTANCE32)wndPtr->hInstance;
1478         default:
1479             fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1480     }
1481     return 0;
1482 }
1483
1484
1485 /**********************************************************************
1486  *           WIN_SetWindowLong
1487  *
1488  * Helper function for SetWindowLong().
1489  */
1490 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1491                                WINDOWPROCTYPE type )
1492 {
1493     LONG *ptr, retval;
1494     WND * wndPtr = WIN_FindWndPtr( hwnd );
1495     if (!wndPtr) return 0;
1496     if (offset >= 0)
1497     {
1498         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1499         {
1500             fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1501             return 0;
1502         }
1503         ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1504         /* Special case for dialog window procedure */
1505         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1506         {
1507             retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1508             WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, 
1509                              type, WIN_PROC_WINDOW );
1510             return retval;
1511         }
1512     }
1513     else switch(offset)
1514     {
1515         case GWL_ID:
1516         case GWL_HINSTANCE:
1517             return SetWindowWord32( hwnd, offset, (WORD)newval );
1518         case GWL_WNDPROC:
1519             retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1520             WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, 
1521                                                 type, WIN_PROC_WINDOW );
1522             return retval;
1523         case GWL_STYLE:
1524
1525             /* FIXME: WM_STYLE... messages for WIN_ISWIN32 windows */
1526
1527             ptr = &wndPtr->dwStyle;
1528             /* Some bits can't be changed this way */
1529             newval &= ~(WS_VISIBLE | WS_CHILD);
1530             newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1531             break;
1532         case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1533         case GWL_EXSTYLE:  ptr = &wndPtr->dwExStyle; break;
1534         default:
1535             fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1536             return 0;
1537     }
1538     retval = *ptr;
1539     *ptr = newval;
1540     return retval;
1541 }
1542
1543
1544 /**********************************************************************
1545  *           GetWindowLong16    (USER.135)
1546  */
1547 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1548 {
1549     return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1550 }
1551
1552
1553 /**********************************************************************
1554  *           GetWindowLong32A    (USER32.304)
1555  */
1556 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1557 {
1558     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1559 }
1560
1561
1562 /**********************************************************************
1563  *           GetWindowLong32W    (USER32.305)
1564  */
1565 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1566 {
1567     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1568 }
1569
1570
1571 /**********************************************************************
1572  *           SetWindowLong16    (USER.136)
1573  */
1574 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1575 {
1576     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1577 }
1578
1579
1580 /**********************************************************************
1581  *           SetWindowLong32A    (USER32.516)
1582  */
1583 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1584 {
1585     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1586 }
1587
1588
1589 /**********************************************************************
1590  *           SetWindowLong32W    (USER32.517)
1591  */
1592 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1593 {
1594     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1595 }
1596
1597
1598 /*******************************************************************
1599  *           GetWindowText16    (USER.36)
1600  */
1601 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1602 {
1603     return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1604 }
1605
1606
1607 /*******************************************************************
1608  *           GetWindowText32A    (USER32.308)
1609  */
1610 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1611 {
1612     return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1613                                   (LPARAM)lpString );
1614 }
1615
1616
1617 /*******************************************************************
1618  *           GetWindowText32W    (USER32.311)
1619  */
1620 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1621 {
1622     return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1623                                   (LPARAM)lpString );
1624 }
1625
1626
1627 /*******************************************************************
1628  *           SetWindowText16    (USER.37)
1629  */
1630 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1631 {
1632     SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1633 }
1634
1635
1636 /*******************************************************************
1637  *           SetWindowText32A    (USER32.)
1638  */
1639 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1640 {
1641     SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1642 }
1643
1644
1645 /*******************************************************************
1646  *           SetWindowText32W    (USER32.)
1647  */
1648 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1649 {
1650     SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1651 }
1652
1653
1654 /*******************************************************************
1655  *         GetWindowTextLength16    (USER.38)
1656  */
1657 INT16 GetWindowTextLength16( HWND16 hwnd )
1658 {
1659     return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1660 }
1661
1662
1663 /*******************************************************************
1664  *         GetWindowTextLength32A   (USER32.309)
1665  */
1666 INT32 GetWindowTextLength32A( HWND32 hwnd )
1667 {
1668     return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1669 }
1670
1671 /*******************************************************************
1672  *         GetWindowTextLength32W   (USER32.309)
1673  */
1674 INT32 GetWindowTextLength32W( HWND32 hwnd )
1675 {
1676     return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1677 }
1678
1679
1680 /*******************************************************************
1681  *         IsWindow16   (USER.47)
1682  */
1683 BOOL16 IsWindow16( HWND16 hwnd )
1684 {
1685     return IsWindow32( hwnd );
1686 }
1687
1688
1689 /*******************************************************************
1690  *         IsWindow32   (USER32.347)
1691  */
1692 BOOL32 IsWindow32( HWND32 hwnd )
1693 {
1694     WND * wndPtr = WIN_FindWndPtr( hwnd );
1695     return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1696 }
1697
1698
1699 /*****************************************************************
1700  *         GetParent16   (USER.46)
1701  */
1702 HWND16 GetParent16( HWND16 hwnd )
1703 {
1704     return (HWND16)GetParent32( hwnd );
1705 }
1706
1707
1708 /*****************************************************************
1709  *         GetParent32   (USER32.277)
1710  */
1711 HWND32 GetParent32( HWND32 hwnd )
1712 {
1713     WND *wndPtr = WIN_FindWndPtr(hwnd);
1714     if (!wndPtr) return 0;
1715     wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1716     return wndPtr ? wndPtr->hwndSelf : 0;
1717 }
1718
1719
1720 /*****************************************************************
1721  *         WIN_GetTopParent
1722  *
1723  * Get the top-level parent for a child window.
1724  */
1725 HWND32 WIN_GetTopParent( HWND32 hwnd )
1726 {
1727     WND *wndPtr = WIN_FindWndPtr( hwnd );
1728     while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1729     return wndPtr ? wndPtr->hwndSelf : 0;
1730 }
1731
1732
1733 /*****************************************************************
1734  *         SetParent16   (USER.233)
1735  */
1736 HWND16 SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1737 {
1738     return SetParent32( hwndChild, hwndNewParent );
1739 }
1740
1741
1742 /*****************************************************************
1743  *         SetParent32   (USER32.494)
1744  */
1745 HWND32 SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1746 {
1747     HWND32 oldParent;
1748
1749     WND *wndPtr = WIN_FindWndPtr( hwndChild );
1750     WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1751     if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1752
1753     oldParent = wndPtr->parent->hwndSelf;
1754
1755     WIN_UnlinkWindow(hwndChild);
1756     if (hwndNewParent) wndPtr->parent = pWndParent;
1757     WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1758     
1759     if (IsWindowVisible32(hwndChild)) UpdateWindow32(hwndChild);
1760     
1761     return oldParent;
1762 }
1763
1764
1765 /*******************************************************************
1766  *         IsChild16    (USER.48)
1767  */
1768 BOOL16 IsChild16( HWND16 parent, HWND16 child )
1769 {
1770     return IsChild32(parent,child);
1771 }
1772
1773
1774 /*******************************************************************
1775  *         IsChild32    (USER32.338)
1776  */
1777 BOOL32 IsChild32( HWND32 parent, HWND32 child )
1778 {
1779     WND * wndPtr = WIN_FindWndPtr( child );
1780     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1781     {
1782         wndPtr = wndPtr->parent;
1783         if (wndPtr->hwndSelf == parent) return TRUE;
1784     }
1785     return FALSE;
1786 }
1787
1788
1789 /***********************************************************************
1790  *           IsWindowVisible16   (USER.49)
1791  */
1792 BOOL16 IsWindowVisible16( HWND16 hwnd )
1793 {
1794     return IsWindowVisible32(hwnd);
1795 }
1796
1797
1798 /***********************************************************************
1799  *           IsWindowVisible32   (USER32.350)
1800  */
1801 BOOL32 IsWindowVisible32( HWND32 hwnd )
1802 {
1803     WND *wndPtr = WIN_FindWndPtr( hwnd );
1804     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1805     {
1806         if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1807         wndPtr = wndPtr->parent;
1808     }
1809     return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1810 }
1811
1812
1813 /***********************************************************************
1814  *           WIN_IsWindowDrawable
1815  *
1816  * hwnd is drawable when it is visible, all parents are not
1817  * minimized, and it is itself not minimized unless we are
1818  * trying to draw its default class icon.
1819  */
1820 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1821 {
1822   if( (wnd->dwStyle & WS_MINIMIZE &&
1823        icon && wnd->class->hIcon) ||
1824      !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1825   for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1826     if( wnd->dwStyle & WS_MINIMIZE ||
1827       !(wnd->dwStyle & WS_VISIBLE) ) break;
1828   return (wnd == NULL);
1829 }
1830
1831
1832 /*******************************************************************
1833  *         GetTopWindow16    (USER.229)
1834  */
1835 HWND16 GetTopWindow16( HWND16 hwnd )
1836 {
1837     return GetTopWindow32(hwnd);
1838 }
1839
1840
1841 /*******************************************************************
1842  *         GetTopWindow32    (USER.229)
1843  */
1844 HWND32 GetTopWindow32( HWND32 hwnd )
1845 {
1846     WND * wndPtr = WIN_FindWndPtr( hwnd );
1847     if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1848     else return 0;
1849 }
1850
1851
1852 /*******************************************************************
1853  *         GetWindow16    (USER.262)
1854  */
1855 HWND16 GetWindow16( HWND16 hwnd, WORD rel )
1856 {
1857     return GetWindow32( hwnd,rel );
1858 }
1859
1860
1861 /*******************************************************************
1862  *         GetWindow32    (USER32.301)
1863  */
1864 HWND32 GetWindow32( HWND32 hwnd, WORD rel )
1865 {
1866     WND * wndPtr = WIN_FindWndPtr( hwnd );
1867     if (!wndPtr) return 0;
1868     switch(rel)
1869     {
1870     case GW_HWNDFIRST:
1871         if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1872         else return 0;
1873         
1874     case GW_HWNDLAST:
1875         if (!wndPtr->parent) return 0;  /* Desktop window */
1876         while (wndPtr->next) wndPtr = wndPtr->next;
1877         return wndPtr->hwndSelf;
1878         
1879     case GW_HWNDNEXT:
1880         if (!wndPtr->next) return 0;
1881         return wndPtr->next->hwndSelf;
1882         
1883     case GW_HWNDPREV:
1884         if (!wndPtr->parent) return 0;  /* Desktop window */
1885         wndPtr = wndPtr->parent->child;  /* First sibling */
1886         if (wndPtr->hwndSelf == hwnd) return 0;  /* First in list */
1887         while (wndPtr->next)
1888         {
1889             if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1890             wndPtr = wndPtr->next;
1891         }
1892         return 0;
1893         
1894     case GW_OWNER:
1895         return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1896
1897     case GW_CHILD:
1898         return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1899     }
1900     return 0;
1901 }
1902
1903
1904 /*******************************************************************
1905  *         GetNextWindow16    (USER.230)
1906  */
1907 HWND16 GetNextWindow16( HWND16 hwnd, WORD flag )
1908 {
1909     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1910     return GetWindow16( hwnd, flag );
1911 }
1912
1913 /*******************************************************************
1914  *         ShowOwnedPopups16  (USER.265)
1915  */
1916 void ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
1917 {
1918     ShowOwnedPopups32( owner, fShow );
1919 }
1920
1921
1922 /*******************************************************************
1923  *         ShowOwnedPopups32  (USER32.530)
1924  */
1925 BOOL32 ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
1926 {
1927     WND *pWnd = pWndDesktop->child;
1928     while (pWnd)
1929     {
1930         if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1931             (pWnd->dwStyle & WS_POPUP))
1932             ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1933         pWnd = pWnd->next;
1934     }
1935     return TRUE;
1936 }
1937
1938
1939 /*******************************************************************
1940  *         GetLastActivePopup16   (USER.287)
1941  */
1942 HWND16 GetLastActivePopup16( HWND16 hwnd )
1943 {
1944     return GetLastActivePopup32( hwnd );
1945 }
1946
1947 /*******************************************************************
1948  *         GetLastActivePopup32   (USER32.255)
1949  */
1950 HWND32 GetLastActivePopup32( HWND32 hwnd )
1951 {
1952     WND *wndPtr;
1953     wndPtr = WIN_FindWndPtr(hwnd);
1954     if (wndPtr == NULL) return hwnd;
1955     return wndPtr->hwndLastActive;
1956 }
1957
1958
1959 /*******************************************************************
1960  *           WIN_BuildWinArray
1961  *
1962  * Build an array of pointers to the children of a given window.
1963  * The array must be freed with HeapFree(SystemHeap). Return NULL
1964  * when no windows are found.
1965  */
1966 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
1967 {
1968     WND **list, **ppWnd;
1969     WND *pWnd;
1970     UINT32 count, skipOwned, skipHidden;
1971     DWORD skipFlags;
1972
1973     skipHidden = bwaFlags & BWA_SKIPHIDDEN;
1974     skipOwned = bwaFlags & BWA_SKIPOWNED;
1975     skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
1976     if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
1977
1978     /* First count the windows */
1979
1980     if (!wndPtr) wndPtr = pWndDesktop;
1981     for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) 
1982     {
1983         if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
1984         if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
1985     }
1986
1987     if( count )
1988     {
1989         /* Now build the list of all windows */
1990
1991         if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
1992         {
1993             for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
1994             {
1995                 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
1996                 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
1997                 {
1998                    *ppWnd++ = pWnd;
1999                     count++;
2000                 }
2001             }
2002            *ppWnd = NULL;
2003         }
2004         else count = 0;
2005     } else list = NULL;
2006
2007     if( pTotal ) *pTotal = count;
2008     return list;
2009 }
2010
2011
2012 /*******************************************************************
2013  *           EnumWindows16   (USER.54)
2014  */
2015 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2016 {
2017     WND **list, **ppWnd;
2018
2019     /* We have to build a list of all windows first, to avoid */
2020     /* unpleasant side-effects, for instance if the callback  */
2021     /* function changes the Z-order of the windows.           */
2022
2023     if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2024
2025     /* Now call the callback function for every window */
2026
2027     for (ppWnd = list; *ppWnd; ppWnd++)
2028     {
2029         /* Make sure that the window still exists */
2030         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2031         if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2032     }
2033     HeapFree( SystemHeap, 0, list );
2034     return TRUE;
2035 }
2036
2037
2038 /*******************************************************************
2039  *           EnumWindows32   (USER32.192)
2040  */
2041 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2042 {
2043     return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2044 }
2045
2046
2047 /**********************************************************************
2048  *           EnumTaskWindows16   (USER.225)
2049  */
2050 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
2051 {
2052     WND **list, **ppWnd;
2053     HQUEUE16 hQueue = GetTaskQueue( hTask );
2054
2055     /* This function is the same as EnumWindows(),    */
2056     /* except for an added check on the window queue. */
2057
2058     if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2059
2060     /* Now call the callback function for every window */
2061
2062     for (ppWnd = list; *ppWnd; ppWnd++)
2063     {
2064         /* Make sure that the window still exists */
2065         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2066         if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
2067         if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2068     }
2069     HeapFree( SystemHeap, 0, list );
2070     return TRUE;
2071 }
2072
2073
2074 /**********************************************************************
2075  *           EnumThreadWindows   (USER32.189)
2076  */
2077 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2078 {
2079     THDB        *tdb = (THDB*)id;
2080
2081     return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2082 }
2083
2084
2085 /**********************************************************************
2086  *           WIN_EnumChildWindows
2087  *
2088  * Helper function for EnumChildWindows().
2089  */
2090 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2091                                     LPARAM lParam )
2092 {
2093     WND **childList;
2094     BOOL16 ret = FALSE;
2095
2096     for ( ; *ppWnd; ppWnd++)
2097     {
2098         /* Make sure that the window still exists */
2099         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2100         /* Build children list first */
2101         if (!(childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL )))
2102             return FALSE;
2103         if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
2104         ret = WIN_EnumChildWindows( childList, func, lParam );
2105         HeapFree( SystemHeap, 0, childList );
2106         if (!ret) return FALSE;
2107     }
2108     return TRUE;
2109 }
2110
2111
2112 /**********************************************************************
2113  *           EnumChildWindows16   (USER.55)
2114  */
2115 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
2116 {
2117     WND **list, *pParent;
2118
2119     if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2120     if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2121     WIN_EnumChildWindows( list, func, lParam );
2122     HeapFree( SystemHeap, 0, list );
2123     return TRUE;
2124 }
2125
2126
2127 /**********************************************************************
2128  *           EnumChildWindows32   (USER32.177)
2129  */
2130 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
2131 {
2132     return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2133                                        lParam );
2134 }
2135
2136
2137 /*******************************************************************
2138  *           AnyPopup16   (USER.52)
2139  */
2140 BOOL16 AnyPopup16(void)
2141 {
2142     return AnyPopup32();
2143 }
2144
2145
2146 /*******************************************************************
2147  *           AnyPopup32   (USER32.3)
2148  */
2149 BOOL32 AnyPopup32(void)
2150 {
2151     WND *wndPtr;
2152     for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2153         if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2154     return FALSE;
2155 }
2156
2157
2158 /*******************************************************************
2159  *            FlashWindow16   (USER.105)
2160  */
2161 BOOL16 FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2162 {
2163     return FlashWindow32( hWnd, bInvert );
2164 }
2165
2166
2167 /*******************************************************************
2168  *            FlashWindow32   (USER32.201)
2169  */
2170 BOOL32 FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2171 {
2172     WND *wndPtr = WIN_FindWndPtr(hWnd);
2173
2174     dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2175
2176     if (!wndPtr) return FALSE;
2177
2178     if (wndPtr->dwStyle & WS_MINIMIZE)
2179     {
2180         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2181         {
2182             HDC32 hDC = GetDC32(hWnd);
2183             
2184             if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2185                 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2186             
2187             ReleaseDC32( hWnd, hDC );
2188             wndPtr->flags |= WIN_NCACTIVATED;
2189         }
2190         else
2191         {
2192             PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2193                                           RDW_UPDATENOW | RDW_FRAME, 0 );
2194             wndPtr->flags &= ~WIN_NCACTIVATED;
2195         }
2196         return TRUE;
2197     }
2198     else
2199     {
2200         WPARAM16 wparam;
2201         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2202         else wparam = (hWnd == GetActiveWindow32());
2203
2204         SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2205         return wparam;
2206     }
2207 }
2208
2209
2210 /*******************************************************************
2211  *           SetSysModalWindow16   (USER.188)
2212  */
2213 HWND16 SetSysModalWindow16( HWND16 hWnd )
2214 {
2215     HWND32 hWndOldModal = hwndSysModal;
2216     hwndSysModal = hWnd;
2217     dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2218     return hWndOldModal;
2219 }
2220
2221
2222 /*******************************************************************
2223  *           GetSysModalWindow16   (USER.52)
2224  */
2225 HWND16 GetSysModalWindow16(void)
2226 {
2227     return hwndSysModal;
2228 }
2229
2230
2231 /*******************************************************************
2232  *                      DRAG_QueryUpdate
2233  *
2234  * recursively find a child that contains spDragInfo->pt point 
2235  * and send WM_QUERYDROPOBJECT
2236  */
2237 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2238 {
2239  BOOL16         wParam,bResult = 0;
2240  POINT32        pt;
2241  LPDRAGINFO     ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2242  WND           *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2243  RECT32         tempRect;
2244
2245  if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2246
2247  CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2248
2249  GetWindowRect32(hQueryWnd,&tempRect); 
2250
2251  if( !PtInRect32(&tempRect,pt) ||
2252      (ptrQueryWnd->dwStyle & WS_DISABLED) )
2253         return 0;
2254
2255  if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) ) 
2256    {
2257      tempRect = ptrQueryWnd->rectClient;
2258      if(ptrQueryWnd->dwStyle & WS_CHILD)
2259         MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2260                            (LPPOINT32)&tempRect, 2 );
2261
2262      if (PtInRect32( &tempRect, pt))
2263         {
2264          wParam = 0;
2265          
2266          for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2267              if( ptrWnd->dwStyle & WS_VISIBLE )
2268              {
2269                  GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2270                  if (PtInRect32( &tempRect, pt )) break;
2271              }
2272
2273          if(ptrWnd)
2274          {
2275             dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2276                         ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2277                         ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2278             if( !(ptrWnd->dwStyle & WS_DISABLED) )
2279                 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2280          }
2281
2282          if(bResult) return bResult;
2283         }
2284      else wParam = 1;
2285    }
2286  else wParam = 1;
2287
2288  ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2289
2290  ptrDragInfo->hScope = hQueryWnd;
2291
2292  bResult = ( bNoSend ) 
2293            ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2294            : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2295                           (WPARAM16)wParam ,(LPARAM) spDragInfo );
2296  if( !bResult ) 
2297      CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2298
2299  return bResult;
2300 }
2301
2302
2303 /*******************************************************************
2304  *             DragDetect   (USER.465)
2305  */
2306 BOOL16 DragDetect16( HWND16 hWnd, POINT16 pt )
2307 {
2308     POINT32 pt32;
2309     CONV_POINT16TO32( &pt, &pt32 );
2310     return DragDetect32( hWnd, pt32 );
2311 }
2312
2313 /*******************************************************************
2314  *             DragDetect32   (USER32.150)
2315  */
2316 BOOL32 DragDetect32( HWND32 hWnd, POINT32 pt )
2317 {
2318     MSG16 msg;
2319     RECT16  rect;
2320
2321     rect.left = pt.x - wDragWidth;
2322     rect.right = pt.x + wDragWidth;
2323
2324     rect.top = pt.y - wDragHeight;
2325     rect.bottom = pt.y + wDragHeight;
2326
2327     SetCapture32(hWnd);
2328
2329     while(1)
2330     {
2331         while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2332         {
2333             if( msg.message == WM_LBUTTONUP )
2334             {
2335                 ReleaseCapture();
2336                 return 0;
2337             }
2338             if( msg.message == WM_MOUSEMOVE )
2339             {
2340                 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2341                 {
2342                     ReleaseCapture();
2343                     return 1;
2344                 }
2345             }
2346         }
2347         WaitMessage();
2348     }
2349     return 0;
2350 }
2351
2352 /******************************************************************************
2353  *             DragObject16   (USER.464)
2354  */
2355 DWORD DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2356                     HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2357 {
2358     MSG16       msg;
2359     LPDRAGINFO  lpDragInfo;
2360     SEGPTR      spDragInfo;
2361     HCURSOR16   hDragCursor=0, hOldCursor=0, hBummer=0;
2362     HGLOBAL16   hDragInfo  = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2363     WND        *wndPtr = WIN_FindWndPtr(hWnd);
2364     HCURSOR16   hCurrentCursor = 0;
2365     HWND16      hCurrentWnd = 0;
2366
2367     lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2368     spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2369
2370     if( !lpDragInfo || !spDragInfo ) return 0L;
2371
2372     hBummer = LoadCursor16(0, IDC_BUMMER);
2373
2374     if( !hBummer || !wndPtr )
2375     {
2376         GlobalFree16(hDragInfo);
2377         return 0L;
2378     }
2379
2380     if(hCursor)
2381     {
2382         if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2383         {
2384             GlobalFree16(hDragInfo);
2385             return 0L;
2386         }
2387
2388         if( hDragCursor == hCursor ) hDragCursor = 0;
2389         else hCursor = hDragCursor;
2390
2391         hOldCursor = SetCursor32(hDragCursor);
2392     }
2393
2394     lpDragInfo->hWnd   = hWnd;
2395     lpDragInfo->hScope = 0;
2396     lpDragInfo->wFlags = wObj;
2397     lpDragInfo->hList  = szList; /* near pointer! */
2398     lpDragInfo->hOfStruct = hOfStruct;
2399     lpDragInfo->l = 0L; 
2400
2401     SetCapture32(hWnd);
2402     ShowCursor32( TRUE );
2403
2404     do
2405     {
2406         do{  WaitMessage(); }
2407         while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2408
2409        *(lpDragInfo+1) = *lpDragInfo;
2410
2411         lpDragInfo->pt = msg.pt;
2412
2413         /* update DRAGINFO struct */
2414         dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2415
2416         if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2417             hCurrentCursor = hCursor;
2418         else
2419         {
2420             hCurrentCursor = hBummer;
2421             lpDragInfo->hScope = 0;
2422         }
2423         if( hCurrentCursor )
2424             SetCursor32(hCurrentCursor);
2425
2426         /* send WM_DRAGLOOP */
2427         SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer), 
2428                                           (LPARAM) spDragInfo );
2429         /* send WM_DRAGSELECT or WM_DRAGMOVE */
2430         if( hCurrentWnd != lpDragInfo->hScope )
2431         {
2432             if( hCurrentWnd )
2433                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0, 
2434                        (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2435                                         HIWORD(spDragInfo)) );
2436             hCurrentWnd = lpDragInfo->hScope;
2437             if( hCurrentWnd )
2438                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo); 
2439         }
2440         else
2441             if( hCurrentWnd )
2442                 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2443
2444     } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2445
2446     ReleaseCapture();
2447     ShowCursor32( FALSE );
2448
2449     if( hCursor )
2450     {
2451         SetCursor32( hOldCursor );
2452         if (hDragCursor) DestroyCursor32( hDragCursor );
2453     }
2454
2455     if( hCurrentCursor != hBummer ) 
2456         msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT, 
2457                                    (WPARAM16)hWnd, (LPARAM)spDragInfo );
2458     else
2459         msg.lParam = 0;
2460     GlobalFree16(hDragInfo);
2461
2462     return (DWORD)(msg.lParam);
2463 }
2464