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