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