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