Release 20010305.
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996, 1999 Alex Korobka
6  */
7
8 #include <string.h>
9 #include "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "options.h"
23 #include "winpos.h"
24 #include "dce.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
27 #include "input.h"
28
29 DEFAULT_DEBUG_CHANNEL(win);
30
31 #define HAS_DLGFRAME(style,exStyle) \
32     (((exStyle) & WS_EX_DLGMODALFRAME) || \
33      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34
35 #define HAS_THICKFRAME(style) \
36     (((style) & WS_THICKFRAME) && \
37      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38
39 #define  SWP_AGG_NOGEOMETRYCHANGE \
40     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
41 #define  SWP_AGG_NOPOSCHANGE \
42     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
43 #define  SWP_AGG_STATUSFLAGS \
44     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45
46 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
47
48 #define PLACE_MIN               0x0001
49 #define PLACE_MAX               0x0002
50 #define PLACE_RECT              0x0004
51
52 #define SWP_EX_NOCOPY           0x0001
53 #define SWP_EX_PAINTSELF        0x0002
54 #define SWP_EX_NONCLIENT        0x0004
55
56 #define MINMAX_NOSWP            0x00010000
57
58 /* ----- internal variables ----- */
59
60 static HWND hwndPrevActive  = 0;  /* Previously active window */
61 static HWND hGlobalShellWindow=0; /*the shell*/
62 static HWND hGlobalTaskmanWindow=0;
63 static HWND hGlobalProgmanWindow=0;
64
65 static LPCSTR atomInternalPos;
66
67 extern HQUEUE16 hActiveQueue;
68
69 /***********************************************************************
70  *           WINPOS_CreateInternalPosAtom
71  */
72 BOOL WINPOS_CreateInternalPosAtom()
73 {
74     LPSTR str = "SysIP";
75     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
76     return (atomInternalPos) ? TRUE : FALSE;
77 }
78
79 /***********************************************************************
80  *           WINPOS_CheckInternalPos
81  *
82  * Called when a window is destroyed.
83  */
84 void WINPOS_CheckInternalPos( WND* wndPtr )
85 {
86     LPINTERNALPOS lpPos;
87     MESSAGEQUEUE *pMsgQ = 0;
88     HWND hwnd = wndPtr->hwndSelf;
89
90     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
91
92     /* Retrieve the message queue associated with this window */
93     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
94     if ( !pMsgQ )
95     {
96         WARN("\tMessage queue not found. Exiting!\n" );
97         return;
98     }
99
100     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
101
102     if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
103     {
104         PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
105         WARN("\tattempt to activate destroyed window!\n");
106     }
107
108     if( lpPos )
109     {
110         if( IsWindow(lpPos->hwndIconTitle) ) 
111             DestroyWindow( lpPos->hwndIconTitle );
112         HeapFree( GetProcessHeap(), 0, lpPos );
113     }
114
115     QUEUE_Unlock( pMsgQ );
116     return;
117 }
118
119 /***********************************************************************
120  *           WINPOS_FindIconPos
121  *
122  * Find a suitable place for an iconic window.
123  */
124 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
125 {
126     RECT16 rectParent;
127     short x, y, xspacing, yspacing;
128
129     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
130     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
131         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
132         return pt;  /* The icon already has a suitable position */
133
134     xspacing = GetSystemMetrics(SM_CXICONSPACING);
135     yspacing = GetSystemMetrics(SM_CYICONSPACING);
136
137     y = rectParent.bottom;
138     for (;;)
139     {
140         x = rectParent.left;
141         do 
142         {
143               /* Check if another icon already occupies this spot */
144             WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
145             while (childPtr)
146             {
147                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
148                 {
149                     if ((childPtr->rectWindow.left < x + xspacing) &&
150                         (childPtr->rectWindow.right >= x) &&
151                         (childPtr->rectWindow.top <= y) &&
152                         (childPtr->rectWindow.bottom > y - yspacing))
153                         break;  /* There's a window in there */
154                 }
155                 WIN_UpdateWndPtr(&childPtr,childPtr->next);
156             }
157             WIN_ReleaseWndPtr(childPtr);
158             if (!childPtr) /* No window was found, so it's OK for us */
159             {
160                 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
161                 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
162                 return pt;
163             }
164             x += xspacing;
165         } while(x <= rectParent.right-xspacing);
166         y -= yspacing;
167     }
168 }
169
170
171 /***********************************************************************
172  *              ArrangeIconicWindows (USER.170)
173  */
174 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent) 
175 {
176     return ArrangeIconicWindows(parent);
177 }
178 /***********************************************************************
179  *              ArrangeIconicWindows (USER32.@)
180  */
181 UINT WINAPI ArrangeIconicWindows( HWND parent )
182 {
183     RECT rectParent;
184     HWND hwndChild;
185     INT x, y, xspacing, yspacing;
186
187     GetClientRect( parent, &rectParent );
188     x = rectParent.left;
189     y = rectParent.bottom;
190     xspacing = GetSystemMetrics(SM_CXICONSPACING);
191     yspacing = GetSystemMetrics(SM_CYICONSPACING);
192
193     hwndChild = GetWindow( parent, GW_CHILD );
194     while (hwndChild)
195     {
196         if( IsIconic( hwndChild ) )
197         {
198             WND *wndPtr = WIN_FindWndPtr(hwndChild);
199             
200             WINPOS_ShowIconTitle( wndPtr, FALSE );
201                
202             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
203                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
204                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
205             if( IsWindow(hwndChild) )
206                 WINPOS_ShowIconTitle(wndPtr , TRUE );
207             WIN_ReleaseWndPtr(wndPtr);
208
209             if (x <= rectParent.right - xspacing) x += xspacing;
210             else
211             {
212                 x = rectParent.left;
213                 y -= yspacing;
214             }
215         }
216         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
217     }
218     return yspacing;
219 }
220
221
222 /***********************************************************************
223  *              SwitchToThisWindow (USER.172)
224  */
225 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
226 {
227     SwitchToThisWindow( hwnd, restore );
228 }
229
230
231 /***********************************************************************
232  *              SwitchToThisWindow (USER32.@)
233  */
234 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
235 {
236     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
237 }
238
239
240 /***********************************************************************
241  *              GetWindowRect (USER.32)
242  */
243 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
244 {
245     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
246     if (!wndPtr) return;
247     
248     CONV_RECT32TO16( &wndPtr->rectWindow, rect );
249     if (wndPtr->dwStyle & WS_CHILD)
250         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
251     WIN_ReleaseWndPtr(wndPtr);
252 }
253
254
255 /***********************************************************************
256  *              GetWindowRect (USER32.@)
257  */
258 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
259 {
260     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
261     if (!wndPtr) return FALSE;
262     
263     *rect = wndPtr->rectWindow;
264     if (wndPtr->dwStyle & WS_CHILD)
265         MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
266     WIN_ReleaseWndPtr(wndPtr);
267     return TRUE;
268 }
269
270
271 /***********************************************************************
272  *              GetWindowRgn (USER32.@)
273  */
274 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
275 {
276     int nRet = ERROR;
277     WND *wndPtr = WIN_FindWndPtr( hwnd );
278     if (wndPtr)
279     {
280         if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
281         WIN_ReleaseWndPtr(wndPtr);
282     }
283     return nRet;
284 }
285
286 /***********************************************************************
287  *              SetWindowRgn (USER32.@)
288  */
289 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
290 {
291     int ret = FALSE;
292     RECT tempRect;
293
294     WND *wndPtr  = WIN_FindWndPtr(hwnd);
295
296     if (!wndPtr) return FALSE;
297
298     /* a region exists for this window */
299     if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
300     {
301         /* can't replace actual region with same region 
302            since we're now owner of that region 
303         */
304         SetLastError(ERROR_INVALID_HANDLE);
305         goto done;
306     }
307
308
309     /* we'd like to set it back to 0 */
310     if (hrgn == 0)
311     {
312         GetWindowRect(hwnd, &tempRect);
313     }
314     else
315     {
316         /* verify that region really exists */
317         if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
318     }
319
320
321     /* Size the window to the rectangle of the new region 
322        (if it isn't NULL) */
323     SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
324                   tempRect.right  - tempRect.left, tempRect.bottom - tempRect.top,
325                   SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
326                   SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
327
328     
329     if (wndPtr->hrgnWnd)
330     {
331         /* delete previous region */
332         DeleteObject(wndPtr->hrgnWnd);
333         wndPtr->hrgnWnd = 0;
334     }
335     else if (!hrgn)
336     {
337         /* if there was no previous region (stored in wndPtr->hrgnWnd) and 
338            the region to be set is also NULL, there is nothing more to do
339          */
340         ret = TRUE;
341         goto done;
342     }
343     
344     /* valid region handle */
345     wndPtr->hrgnWnd = hrgn;
346     wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
347
348     ret = TRUE;
349
350  done:
351     WIN_ReleaseWndPtr(wndPtr);
352     return ret;
353 }
354
355 /***********************************************************************
356  *              SetWindowRgn (USER.668)
357  */
358 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
359
360 {
361
362   FIXME("SetWindowRgn16: stub\n"); 
363   return TRUE;
364 }
365
366
367 /***********************************************************************
368  *              GetClientRect (USER.33)
369  */
370 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
371 {
372     WND * wndPtr = WIN_FindWndPtr( hwnd );
373
374     rect->left = rect->top = rect->right = rect->bottom = 0;
375     if (wndPtr) 
376     {
377         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
378         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
379     }
380     WIN_ReleaseWndPtr(wndPtr);
381 }
382
383
384 /***********************************************************************
385  *              GetClientRect (USER32.@)
386  */
387 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) 
388 {
389     WND * wndPtr = WIN_FindWndPtr( hwnd );
390
391     rect->left = rect->top = rect->right = rect->bottom = 0;
392     if (!wndPtr) return FALSE;
393     rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
394     rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
395
396     WIN_ReleaseWndPtr(wndPtr);
397     return TRUE;
398 }
399
400
401 /*******************************************************************
402  *              ClientToScreen (USER.28)
403  */
404 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
405 {
406     MapWindowPoints16( hwnd, 0, lppnt, 1 );
407 }
408
409
410 /*******************************************************************
411  *              ClientToScreen (USER32.@)
412  */
413 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
414 {
415     MapWindowPoints( hwnd, 0, lppnt, 1 );
416     return TRUE;
417 }
418
419
420 /*******************************************************************
421  *              ScreenToClient (USER.29)
422  */
423 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
424 {
425     MapWindowPoints16( 0, hwnd, lppnt, 1 );
426 }
427
428
429 /*******************************************************************
430  *              ScreenToClient (USER32.@)
431  */
432 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
433 {
434     MapWindowPoints( 0, hwnd, lppnt, 1 );
435     return TRUE;
436 }
437
438
439 /***********************************************************************
440  *           WINPOS_WindowFromPoint
441  *
442  * Find the window and hittest for a given point.
443  */
444 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
445 {
446     WND *wndPtr;
447     INT16 hittest = HTERROR;
448     INT16 retvalue;
449     POINT16 xy = pt;
450
451     TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
452    *ppWnd = NULL;
453     wndPtr = WIN_LockWndPtr(wndScope->child);
454
455     if( wndScope->dwStyle & WS_DISABLED )
456     {
457             retvalue = HTERROR;
458             goto end;
459     }
460    
461     if( wndScope->dwExStyle & WS_EX_MANAGED)
462     {
463         /* In managed mode we have to check wndScope first as it is also
464          * a window which received the mouse event. */
465
466         if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
467             pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
468             goto hittest;
469     }
470     MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
471
472     for (;;)
473     {
474         while (wndPtr)
475         {
476             /* If point is in window, and window is visible, and it  */
477             /* is enabled (or it's a top-level window), then explore */
478             /* its children. Otherwise, go to the next window.       */
479
480              if ((wndPtr->dwStyle & WS_VISIBLE) &&
481                 (!(wndPtr->dwStyle & WS_DISABLED) ||
482                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
483                 (wndPtr->hrgnWnd ?
484                 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
485                            xy.y - wndPtr->rectWindow.top) :
486                 ((xy.x >= wndPtr->rectWindow.left) &&
487                  (xy.x < wndPtr->rectWindow.right) &&
488                  (xy.y >= wndPtr->rectWindow.top) &&
489                  (xy.y < wndPtr->rectWindow.bottom))))
490             {
491                 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
492                 *ppWnd = wndPtr;  /* Got a suitable window */
493
494                 /* If window is minimized or disabled, return at once */
495                 if (wndPtr->dwStyle & WS_MINIMIZE)
496                 {
497                     retvalue = HTCAPTION;
498                     goto end;
499                 }
500                 if (wndPtr->dwStyle & WS_DISABLED)
501                 {
502                     retvalue = HTERROR;
503                     goto end;
504                 }
505
506                 /* If point is not in client area, ignore the children */
507                 if ((xy.x < wndPtr->rectClient.left) ||
508                     (xy.x >= wndPtr->rectClient.right) ||
509                     (xy.y < wndPtr->rectClient.top) ||
510                     (xy.y >= wndPtr->rectClient.bottom)) break;
511
512                 xy.x -= wndPtr->rectClient.left;
513                 xy.y -= wndPtr->rectClient.top;
514                 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
515             }
516             else
517             {
518                 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
519             }
520         }
521
522 hittest:
523         /* If nothing found, try the scope window */
524         if (!*ppWnd) *ppWnd = wndScope;
525
526         /* Send the WM_NCHITTEST message (only if to the same task) */
527         if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
528         {
529             hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 
530                                                  0, MAKELONG( pt.x, pt.y ) );
531             if (hittest != HTTRANSPARENT)
532             {
533                 retvalue = hittest;  /* Found the window */
534                 goto end;
535             }
536         }
537         else
538         {
539             retvalue = HTCLIENT;
540             goto end;
541         }
542
543         /* If no children found in last search, make point relative to parent */
544         if (!wndPtr)
545         {
546             xy.x += (*ppWnd)->rectClient.left;
547             xy.y += (*ppWnd)->rectClient.top;
548         }
549
550         /* Restart the search from the next sibling */
551         WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
552         *ppWnd = (*ppWnd)->parent;
553     }
554
555 end:
556     WIN_ReleaseWndPtr(wndPtr);
557     return retvalue;
558 }
559
560
561 /*******************************************************************
562  *              WindowFromPoint (USER.30)
563  */
564 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
565 {
566     WND *pWnd;
567     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
568     WIN_ReleaseDesktop();
569     return pWnd->hwndSelf;
570 }
571
572
573 /*******************************************************************
574  *              WindowFromPoint (USER32.@)
575  */
576 HWND WINAPI WindowFromPoint( POINT pt )
577 {
578     WND *pWnd;
579     POINT16 pt16;
580     CONV_POINT32TO16( &pt, &pt16 );
581     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
582     WIN_ReleaseDesktop();
583     return (HWND)pWnd->hwndSelf;
584 }
585
586
587 /*******************************************************************
588  *              ChildWindowFromPoint (USER.191)
589  */
590 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
591 {
592     POINT pt32;
593     CONV_POINT16TO32( &pt, &pt32 );
594     return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
595 }
596
597
598 /*******************************************************************
599  *              ChildWindowFromPoint (USER32.@)
600  */
601 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
602 {
603     /* pt is in the client coordinates */
604
605     WND* wnd = WIN_FindWndPtr(hwndParent);
606     RECT rect;
607     HWND retvalue;
608
609     if( !wnd ) return 0;
610
611     /* get client rect fast */
612     rect.top = rect.left = 0;
613     rect.right = wnd->rectClient.right - wnd->rectClient.left;
614     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
615
616     if (!PtInRect( &rect, pt ))
617     {
618         retvalue = 0;
619         goto end;
620     }
621     WIN_UpdateWndPtr(&wnd,wnd->child);
622     while ( wnd )
623     {
624         if (PtInRect( &wnd->rectWindow, pt ))
625         {
626             retvalue = wnd->hwndSelf;
627             goto end;
628         }
629         WIN_UpdateWndPtr(&wnd,wnd->next);
630     }
631     retvalue = hwndParent;
632 end:
633     WIN_ReleaseWndPtr(wnd);
634     return retvalue;
635 }
636
637 /*******************************************************************
638  *              ChildWindowFromPointEx (USER.399)
639  */
640 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
641 {
642     POINT pt32;
643     CONV_POINT16TO32( &pt, &pt32 );
644     return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
645 }
646
647
648 /*******************************************************************
649  *              ChildWindowFromPointEx (USER32.@)
650  */
651 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
652                 UINT uFlags)
653 {
654     /* pt is in the client coordinates */
655
656     WND* wnd = WIN_FindWndPtr(hwndParent);
657     RECT rect;
658     HWND retvalue;
659
660     if( !wnd ) return 0;
661
662     /* get client rect fast */
663     rect.top = rect.left = 0;
664     rect.right = wnd->rectClient.right - wnd->rectClient.left;
665     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
666
667     if (!PtInRect( &rect, pt ))
668     {
669         retvalue = 0;
670         goto end;
671     }
672     WIN_UpdateWndPtr(&wnd,wnd->child);
673
674     while ( wnd )
675     {
676         if (PtInRect( &wnd->rectWindow, pt )) {
677                 if ( (uFlags & CWP_SKIPINVISIBLE) && 
678                                 !(wnd->dwStyle & WS_VISIBLE) );
679                 else if ( (uFlags & CWP_SKIPDISABLED) && 
680                                 (wnd->dwStyle & WS_DISABLED) );
681                 else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
682                                 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
683                 else
684                 {
685                     retvalue = wnd->hwndSelf;
686                     goto end;
687                 }
688                 
689         }
690         WIN_UpdateWndPtr(&wnd,wnd->next);
691     }
692     retvalue = hwndParent;
693 end:
694     WIN_ReleaseWndPtr(wnd);
695     return retvalue;
696 }
697
698
699 /*******************************************************************
700  *         WINPOS_GetWinOffset
701  *
702  * Calculate the offset between the origin of the two windows. Used
703  * to implement MapWindowPoints.
704  */
705 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
706                                  POINT *offset )
707 {
708     WND * wndPtr = 0;
709
710     offset->x = offset->y = 0;
711     if (hwndFrom == hwndTo ) return;
712
713       /* Translate source window origin to screen coords */
714     if (hwndFrom)
715     {
716         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
717         {
718             ERR("bad hwndFrom = %04x\n",hwndFrom);
719             return;
720         }
721         while (wndPtr->parent)
722         {
723             offset->x += wndPtr->rectClient.left;
724             offset->y += wndPtr->rectClient.top;
725             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
726         }
727         WIN_ReleaseWndPtr(wndPtr);
728     }
729
730       /* Translate origin to destination window coords */
731     if (hwndTo)
732     {
733         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
734         {
735             ERR("bad hwndTo = %04x\n", hwndTo );
736             return;
737         }
738         while (wndPtr->parent)
739         {
740             offset->x -= wndPtr->rectClient.left;
741             offset->y -= wndPtr->rectClient.top;
742             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
743         }    
744         WIN_ReleaseWndPtr(wndPtr);
745     }
746 }
747
748
749 /*******************************************************************
750  *              MapWindowPoints (USER.258)
751  */
752 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
753                                LPPOINT16 lppt, UINT16 count )
754 {
755     POINT offset;
756
757     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
758     while (count--)
759     {
760         lppt->x += offset.x;
761         lppt->y += offset.y;
762         lppt++;
763     }
764 }
765
766
767 /*******************************************************************
768  *              MapWindowPoints (USER32.@)
769  */
770 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
771                                LPPOINT lppt, UINT count )
772 {
773     POINT offset;
774
775     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
776     while (count--)
777     {
778         lppt->x += offset.x;
779         lppt->y += offset.y;
780         lppt++;
781     }
782     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
783 }
784
785
786 /***********************************************************************
787  *              IsIconic (USER.31)
788  */
789 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
790 {
791     return IsIconic(hWnd);
792 }
793
794
795 /***********************************************************************
796  *              IsIconic (USER32.@)
797  */
798 BOOL WINAPI IsIconic(HWND hWnd)
799 {
800     BOOL retvalue;
801     WND * wndPtr = WIN_FindWndPtr(hWnd);
802     if (wndPtr == NULL) return FALSE;
803     retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
804     WIN_ReleaseWndPtr(wndPtr);
805     return retvalue;
806 }
807  
808  
809 /***********************************************************************
810  *              IsZoomed (USER.272)
811  */
812 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
813 {
814     return IsZoomed(hWnd);
815 }
816
817
818 /***********************************************************************
819  *              IsZoomed (USER32.@)
820  */
821 BOOL WINAPI IsZoomed(HWND hWnd)
822 {
823     BOOL retvalue;
824     WND * wndPtr = WIN_FindWndPtr(hWnd);
825     if (wndPtr == NULL) return FALSE;
826     retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
827     WIN_ReleaseWndPtr(wndPtr);
828     return retvalue;
829 }
830
831
832 /*******************************************************************
833  *              GetActiveWindow (USER.60)
834  */
835 HWND16 WINAPI GetActiveWindow16(void)
836 {
837     return (HWND16)GetActiveWindow();
838 }
839
840 /*******************************************************************
841  *              GetActiveWindow (USER32.@)
842  */
843 HWND WINAPI GetActiveWindow(void)
844 {
845     MESSAGEQUEUE *pCurMsgQ = 0;
846     HWND hwndActive = 0;
847
848     /* Get the messageQ for the current thread */
849     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
850 {
851         WARN("\tCurrent message queue not found. Exiting!\n" );
852         return 0;
853     }
854
855     /* Return the current active window from the perQ data of the current message Q */
856     hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
857
858     QUEUE_Unlock( pCurMsgQ );
859     return hwndActive;
860 }
861
862
863 /*******************************************************************
864  *         WINPOS_CanActivate
865  */
866 static BOOL WINPOS_CanActivate(WND* pWnd)
867 {
868     if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
869        == WS_VISIBLE ) ) return TRUE;
870     return FALSE;
871 }
872
873
874 /*******************************************************************
875  *              SetActiveWindow (USER.59)
876  */
877 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
878 {
879     return SetActiveWindow(hwnd);
880 }
881
882
883 /*******************************************************************
884  *              SetActiveWindow (USER32.@)
885  */
886 HWND WINAPI SetActiveWindow( HWND hwnd )
887 {
888     HWND prev = 0;
889     WND *wndPtr = WIN_FindWndPtr( hwnd );
890     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
891
892     if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
893     {
894         prev = 0;
895         goto end;
896     }
897
898     /* Get the messageQ for the current thread */
899     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
900     {
901         WARN("\tCurrent message queue not found. Exiting!\n" );
902         goto CLEANUP;
903     }
904     
905     /* Retrieve the message queue associated with this window */
906     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
907     if ( !pMsgQ )
908     {
909         WARN("\tWindow message queue not found. Exiting!\n" );
910         goto CLEANUP;
911     }
912
913     /* Make sure that the window is associated with the calling threads
914      * message queue. It must share the same perQ data.
915      */
916     
917     if ( pCurMsgQ->pQData != pMsgQ->pQData )
918         goto CLEANUP;
919     
920     /* Save current active window */
921     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
922     
923     WINPOS_SetActiveWindow( hwnd, 0, 0 );
924
925 CLEANUP:
926     /* Unlock the queues before returning */
927     if ( pMsgQ )
928         QUEUE_Unlock( pMsgQ );
929     if ( pCurMsgQ )
930         QUEUE_Unlock( pCurMsgQ );
931     
932 end:
933     WIN_ReleaseWndPtr(wndPtr);
934     return prev;
935 }
936
937
938 /*******************************************************************
939  *              GetForegroundWindow (USER.608)
940  */
941 HWND16 WINAPI GetForegroundWindow16(void)
942 {
943     return (HWND16)GetForegroundWindow();
944 }
945
946
947 /*******************************************************************
948  *              SetForegroundWindow (USER.609)
949  */
950 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
951 {
952     return SetForegroundWindow( hwnd );
953 }
954
955
956 /*******************************************************************
957  *              GetForegroundWindow (USER32.@)
958  */
959 HWND WINAPI GetForegroundWindow(void)
960 {
961     HWND hwndActive = 0;
962
963     /* Get the foreground window (active window of hActiveQueue) */
964     if ( hActiveQueue )
965     {
966         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
967         if ( pActiveQueue )
968             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
969
970         QUEUE_Unlock( pActiveQueue );
971     }
972
973     return hwndActive;
974 }
975
976 /*******************************************************************
977  *              SetForegroundWindow (USER32.@)
978  */
979 BOOL WINAPI SetForegroundWindow( HWND hwnd )
980 {
981     return WINPOS_ChangeActiveWindow( hwnd, FALSE );
982 }
983
984
985 /*******************************************************************
986  *              AllowSetForegroundWindow (USER32.@)
987  */
988 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
989 {
990     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
991      * implemented, then fix this function. */
992     return TRUE;
993 }
994
995
996 /*******************************************************************
997  *              LockSetForegroundWindow (USER32.@)
998  */
999 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1000 {
1001     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1002      * implemented, then fix this function. */
1003     return TRUE;
1004 }
1005
1006
1007 /*******************************************************************
1008  *              GetShellWindow (USER.600)
1009  */
1010 HWND16 WINAPI GetShellWindow16(void)
1011 {
1012     return GetShellWindow();
1013 }
1014
1015 /*******************************************************************
1016  *              SetShellWindow (USER32.@)
1017  */
1018 HWND WINAPI SetShellWindow(HWND hwndshell)
1019 {   WARN("(hWnd=%08x) semi stub\n",hwndshell );
1020
1021     hGlobalShellWindow = hwndshell;
1022     return hGlobalShellWindow;
1023 }
1024
1025
1026 /*******************************************************************
1027  *              GetShellWindow (USER32.@)
1028  */
1029 HWND WINAPI GetShellWindow(void)
1030 {   WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1031
1032     return hGlobalShellWindow;
1033 }
1034
1035
1036 /***********************************************************************
1037  *              BringWindowToTop (USER.45)
1038  */
1039 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1040 {
1041     return BringWindowToTop(hwnd);
1042 }
1043
1044
1045 /***********************************************************************
1046  *              BringWindowToTop (USER32.@)
1047  */
1048 BOOL WINAPI BringWindowToTop( HWND hwnd )
1049 {
1050     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1051 }
1052
1053
1054 /***********************************************************************
1055  *              MoveWindow (USER.56)
1056  */
1057 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1058                             BOOL16 repaint )
1059 {
1060     return MoveWindow(hwnd,x,y,cx,cy,repaint);
1061 }
1062
1063
1064 /***********************************************************************
1065  *              MoveWindow (USER32.@)
1066  */
1067 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1068                             BOOL repaint )
1069 {    
1070     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1071     if (!repaint) flags |= SWP_NOREDRAW;
1072     TRACE("%04x %d,%d %dx%d %d\n", 
1073             hwnd, x, y, cx, cy, repaint );
1074     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1075 }
1076
1077 /***********************************************************************
1078  *           WINPOS_InitInternalPos
1079  */
1080 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
1081                                              LPRECT restoreRect )
1082 {
1083     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1084                                                       atomInternalPos );
1085     if( !lpPos )
1086     {
1087         /* this happens when the window is minimized/maximized 
1088          * for the first time (rectWindow is not adjusted yet) */
1089
1090         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
1091         if( !lpPos ) return NULL;
1092
1093         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1094         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1095         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1096         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1097     }
1098
1099     if( wnd->dwStyle & WS_MINIMIZE ) 
1100         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1101     else if( wnd->dwStyle & WS_MAXIMIZE ) 
1102         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1103     else if( restoreRect ) 
1104         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1105
1106     return lpPos;
1107 }
1108
1109 /***********************************************************************
1110  *           WINPOS_RedrawIconTitle
1111  */
1112 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1113 {
1114     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1115     if( lpPos )
1116     {
1117         if( lpPos->hwndIconTitle )
1118         {
1119             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1120             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1121             return TRUE;
1122         }
1123     }
1124     return FALSE;
1125 }
1126
1127 /***********************************************************************
1128  *           WINPOS_ShowIconTitle
1129  */
1130 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1131 {
1132     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1133
1134     if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1135     {
1136         HWND16 hWnd = lpPos->hwndIconTitle;
1137
1138         TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1139
1140         if( !hWnd )
1141             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1142         if( bShow )
1143         {
1144             if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL) 
1145             {
1146                 if( !(pWnd->dwStyle & WS_VISIBLE) )
1147                 {
1148                    SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1149                    SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1150                                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1151                 }
1152                 WIN_ReleaseWndPtr(pWnd);
1153             }
1154         }
1155         else ShowWindow( hWnd, SW_HIDE );
1156     }
1157     return FALSE;
1158 }
1159
1160 /*******************************************************************
1161  *           WINPOS_GetMinMaxInfo
1162  *
1163  * Get the minimized and maximized information for a window.
1164  */
1165 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1166                            POINT *minTrack, POINT *maxTrack )
1167 {
1168     LPINTERNALPOS lpPos;
1169     MINMAXINFO MinMax;
1170     INT xinc, yinc;
1171
1172     /* Compute default values */
1173
1174     MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1175     MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1176     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1177     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1178     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1179     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1180
1181     if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1182     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1183     {
1184         xinc = GetSystemMetrics(SM_CXDLGFRAME);
1185         yinc = GetSystemMetrics(SM_CYDLGFRAME);
1186     }
1187     else
1188     {
1189         xinc = yinc = 0;
1190         if (HAS_THICKFRAME(wndPtr->dwStyle))
1191         {
1192             xinc += GetSystemMetrics(SM_CXFRAME);
1193             yinc += GetSystemMetrics(SM_CYFRAME);
1194         }
1195         if (wndPtr->dwStyle & WS_BORDER)
1196         {
1197             xinc += GetSystemMetrics(SM_CXBORDER);
1198             yinc += GetSystemMetrics(SM_CYBORDER);
1199         }
1200     }
1201     MinMax.ptMaxSize.x += 2 * xinc;
1202     MinMax.ptMaxSize.y += 2 * yinc;
1203
1204     lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1205     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1206         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1207     else
1208     {
1209         MinMax.ptMaxPosition.x = -xinc;
1210         MinMax.ptMaxPosition.y = -yinc;
1211     }
1212
1213     SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1214
1215       /* Some sanity checks */
1216
1217     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1218                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1219                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1220                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1221                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1222     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1223                                    MinMax.ptMinTrackSize.x );
1224     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1225                                    MinMax.ptMinTrackSize.y );
1226
1227     if (maxSize) *maxSize = MinMax.ptMaxSize;
1228     if (maxPos) *maxPos = MinMax.ptMaxPosition;
1229     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1230     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1231 }
1232
1233 /***********************************************************************
1234  *           WINPOS_MinMaximize
1235  *
1236  * Fill in lpRect and return additional flags to be used with SetWindowPos().
1237  * This function assumes that 'cmd' is different from the current window
1238  * state.
1239  */
1240 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1241 {
1242     UINT swpFlags = 0;
1243     POINT pt, size;
1244     LPINTERNALPOS lpPos;
1245
1246     TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1247
1248     size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1249     lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1250
1251     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1252     {
1253         if( wndPtr->dwStyle & WS_MINIMIZE )
1254         {
1255             if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1256                 return (SWP_NOSIZE | SWP_NOMOVE);
1257             swpFlags |= SWP_NOCOPYBITS;
1258         }
1259         switch( cmd )
1260         {
1261             case SW_MINIMIZE:
1262                  if( wndPtr->dwStyle & WS_MAXIMIZE)
1263                  {
1264                      wndPtr->flags |= WIN_RESTORE_MAX;
1265                      wndPtr->dwStyle &= ~WS_MAXIMIZE;
1266                  }
1267                  else
1268                      wndPtr->flags &= ~WIN_RESTORE_MAX;
1269                  wndPtr->dwStyle |= WS_MINIMIZE;
1270
1271                  if( wndPtr->flags & WIN_NATIVE )
1272                      if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1273                          swpFlags |= MINMAX_NOSWP;
1274
1275                  lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1276
1277                  SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1278                                     GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1279                  swpFlags |= SWP_NOCOPYBITS;
1280                  break;
1281
1282             case SW_MAXIMIZE:
1283                 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1284                 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1285                 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1286
1287                  if( wndPtr->dwStyle & WS_MINIMIZE )
1288                  {
1289                      if( wndPtr->flags & WIN_NATIVE )
1290                          wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1291
1292                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1293                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1294                  }
1295                  wndPtr->dwStyle |= WS_MAXIMIZE;
1296
1297                  SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1298                                     size.x, size.y );
1299                  break;
1300
1301             case SW_RESTORE:
1302                  if( wndPtr->dwStyle & WS_MINIMIZE )
1303                  {
1304                      if( wndPtr->flags & WIN_NATIVE )
1305                          wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1306
1307                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1308                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1309
1310                      if( wndPtr->flags & WIN_RESTORE_MAX)
1311                      {
1312                          /* Restore to maximized position */
1313                          CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1314                          WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1315                          CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1316                          wndPtr->dwStyle |= WS_MAXIMIZE;
1317                          SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1318                          break;
1319                      }
1320                  } 
1321                  else 
1322                      if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1323                      else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1324
1325                  /* Restore to normal position */
1326
1327                 *lpRect = lpPos->rectNormal; 
1328                  lpRect->right -= lpRect->left; 
1329                  lpRect->bottom -= lpRect->top;
1330
1331                  break;
1332         }
1333     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1334     return swpFlags;
1335 }
1336
1337 /***********************************************************************
1338  *              ShowWindowAsync (USER32.@)
1339  *
1340  * doesn't wait; returns immediately.
1341  * used by threads to toggle windows in other (possibly hanging) threads
1342  */
1343 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1344 {
1345     /* FIXME: does ShowWindow() return immediately ? */
1346     return ShowWindow(hwnd, cmd);
1347 }
1348
1349
1350 /***********************************************************************
1351  *              ShowWindow (USER.42)
1352  */
1353 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1354 {    
1355     return ShowWindow(hwnd,cmd);
1356 }
1357
1358
1359 /***********************************************************************
1360  *              ShowWindow (USER32.@)
1361  */
1362 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) 
1363 {    
1364     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1365     BOOL        wasVisible, showFlag;
1366     RECT16      newPos = {0, 0, 0, 0};
1367     UINT        swp = 0;
1368
1369     if (!wndPtr) return FALSE;
1370
1371     TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1372
1373     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1374
1375     switch(cmd)
1376     {
1377         case SW_HIDE:
1378             if (!wasVisible) goto END;;
1379             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
1380                         SWP_NOACTIVATE | SWP_NOZORDER;
1381             break;
1382
1383         case SW_SHOWMINNOACTIVE:
1384             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1385             /* fall through */
1386         case SW_SHOWMINIMIZED:
1387             swp |= SWP_SHOWWINDOW;
1388             /* fall through */
1389         case SW_MINIMIZE:
1390             swp |= SWP_FRAMECHANGED;
1391             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1392                  swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1393             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1394             break;
1395
1396         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1397             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1398             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1399                  swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1400             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1401             break;
1402
1403         case SW_SHOWNA:
1404             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1405             /* fall through */
1406         case SW_SHOW:
1407             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1408
1409             /*
1410              * ShowWindow has a little peculiar behavior that if the
1411              * window is already the topmost window, it will not
1412              * activate it.
1413              */
1414             if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1415               swp |= SWP_NOACTIVATE;
1416
1417             break;
1418
1419         case SW_SHOWNOACTIVATE:
1420             swp |= SWP_NOZORDER;
1421             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1422             /* fall through */
1423         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1424         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1425         case SW_RESTORE:
1426             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1427
1428             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1429                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1430             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1431             break;
1432     }
1433
1434     showFlag = (cmd != SW_HIDE);
1435     if (showFlag != wasVisible)
1436     {
1437         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1438         if (!IsWindow( hwnd )) goto END;
1439     }
1440
1441     if ((wndPtr->dwStyle & WS_CHILD) &&
1442         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1443         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1444     {
1445         /* Don't call SetWindowPos() on invisible child windows */
1446         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1447         else wndPtr->dwStyle |= WS_VISIBLE;
1448     }
1449     else
1450     {
1451         /* We can't activate a child window */
1452         if ((wndPtr->dwStyle & WS_CHILD) &&
1453             !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1454             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1455         if (!(swp & MINMAX_NOSWP))
1456         {
1457             SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, 
1458                                           newPos.right, newPos.bottom, LOWORD(swp) );
1459             if (cmd == SW_HIDE)
1460             {
1461                /* FIXME: This will cause the window to be activated irrespective
1462                 * of whether it is owned by the same thread. Has to be done
1463                 * asynchronously.
1464                 */
1465
1466                if (hwnd == GetActiveWindow())
1467                   WINPOS_ActivateOtherWindow(wndPtr);
1468
1469                /* Revert focus to parent */
1470                if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1471                   SetFocus( GetParent(hwnd) );
1472             }
1473         }
1474         if (!IsWindow( hwnd )) goto END;
1475         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1476     }
1477
1478     if (wndPtr->flags & WIN_NEED_SIZE)
1479     {
1480         /* should happen only in CreateWindowEx() */
1481         int wParam = SIZE_RESTORED;
1482
1483         wndPtr->flags &= ~WIN_NEED_SIZE;
1484         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1485         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1486         SendMessageA( hwnd, WM_SIZE, wParam,
1487                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1488                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1489         SendMessageA( hwnd, WM_MOVE, 0,
1490                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1491     }
1492
1493 END:
1494     WIN_ReleaseWndPtr(wndPtr);
1495     return wasVisible;
1496 }
1497
1498
1499 /***********************************************************************
1500  *              GetInternalWindowPos (USER.460)
1501  */
1502 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1503                                       LPPOINT16 ptIcon )
1504 {
1505     WINDOWPLACEMENT16 wndpl;
1506     if (GetWindowPlacement16( hwnd, &wndpl )) 
1507     {
1508         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1509         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1510         return wndpl.showCmd;
1511     }
1512     return 0;
1513 }
1514
1515
1516 /***********************************************************************
1517  *              GetInternalWindowPos (USER32.@)
1518  */
1519 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1520                                       LPPOINT ptIcon )
1521 {
1522     WINDOWPLACEMENT wndpl;
1523     if (GetWindowPlacement( hwnd, &wndpl ))
1524     {
1525         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1526         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1527         return wndpl.showCmd;
1528     }
1529     return 0;
1530 }
1531
1532 /***********************************************************************
1533  *              GetWindowPlacement (USER.370)
1534  */
1535 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1536 {
1537     WND *pWnd = WIN_FindWndPtr( hwnd );
1538     LPINTERNALPOS lpPos;
1539     
1540     if(!pWnd ) return FALSE;
1541
1542     lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1543                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1544         wndpl->length  = sizeof(*wndpl);
1545         if( pWnd->dwStyle & WS_MINIMIZE )
1546             wndpl->showCmd = SW_SHOWMINIMIZED;
1547         else 
1548             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1549                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1550         if( pWnd->flags & WIN_RESTORE_MAX )
1551             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1552         else
1553             wndpl->flags = 0;
1554         wndpl->ptMinPosition = lpPos->ptIconPos;
1555         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1556         wndpl->rcNormalPosition = lpPos->rectNormal;
1557
1558     WIN_ReleaseWndPtr(pWnd);
1559         return TRUE;
1560     }
1561
1562
1563 /***********************************************************************
1564  *              GetWindowPlacement (USER32.@)
1565  *
1566  * Win95:
1567  * Fails if wndpl->length of Win95 (!) apps is invalid.
1568  */
1569 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1570 {
1571     if( pwpl32 )
1572     {
1573         WINDOWPLACEMENT16 wpl;
1574         wpl.length = sizeof(wpl);
1575         if( GetWindowPlacement16( hwnd, &wpl ) )
1576         {
1577             pwpl32->length = sizeof(*pwpl32);
1578             pwpl32->flags = wpl.flags;
1579             pwpl32->showCmd = wpl.showCmd;
1580             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1581             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1582             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1583             return TRUE;
1584         }
1585     }
1586     return FALSE;
1587 }
1588
1589
1590 /***********************************************************************
1591  *           WINPOS_SetPlacement
1592  */
1593 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1594                                                 UINT flags )
1595 {
1596     WND *pWnd = WIN_FindWndPtr( hwnd );
1597     if( pWnd )
1598     {
1599         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1600                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1601
1602         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1603         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1604         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1605
1606         if( pWnd->dwStyle & WS_MINIMIZE )
1607         {
1608             WINPOS_ShowIconTitle( pWnd, FALSE );
1609             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1610                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1611                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1612         } 
1613         else if( pWnd->dwStyle & WS_MAXIMIZE )
1614         {
1615             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1616                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1617                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1618         }
1619         else if( flags & PLACE_RECT )
1620                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1621                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1622                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1623                                 SWP_NOZORDER | SWP_NOACTIVATE );
1624
1625         ShowWindow( hwnd, wndpl->showCmd );
1626         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1627         {
1628             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1629
1630             /* SDK: ...valid only the next time... */
1631             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1632         }
1633         WIN_ReleaseWndPtr(pWnd);
1634         return TRUE;
1635     }
1636     return FALSE;
1637 }
1638
1639
1640 /***********************************************************************
1641  *              SetWindowPlacement (USER.371)
1642  */
1643 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1644 {
1645     return WINPOS_SetPlacement( hwnd, wndpl,
1646                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1647 }
1648
1649 /***********************************************************************
1650  *              SetWindowPlacement (USER32.@)
1651  *
1652  * Win95:
1653  * Fails if wndpl->length of Win95 (!) apps is invalid.
1654  */
1655 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1656 {
1657     if( pwpl32 )
1658     {
1659         WINDOWPLACEMENT16 wpl;
1660
1661         wpl.length = sizeof(WINDOWPLACEMENT16);
1662         wpl.flags = pwpl32->flags;
1663         wpl.showCmd = pwpl32->showCmd;
1664         wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1665         wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1666         wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1667         wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1668         wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1669         wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1670         wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1671         wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1672
1673         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1674     }
1675     return FALSE;
1676 }
1677
1678
1679 /***********************************************************************
1680  *              SetInternalWindowPos (USER.461)
1681  */
1682 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1683                                     LPRECT16 rect, LPPOINT16 pt )
1684 {
1685     if( IsWindow16(hwnd) )
1686     {
1687         WINDOWPLACEMENT16 wndpl;
1688         UINT flags;
1689
1690         wndpl.length  = sizeof(wndpl);
1691         wndpl.showCmd = showCmd;
1692         wndpl.flags = flags = 0;
1693
1694         if( pt )
1695         {
1696             flags |= PLACE_MIN;
1697             wndpl.flags |= WPF_SETMINPOSITION;
1698             wndpl.ptMinPosition = *pt;
1699         }
1700         if( rect )
1701         {
1702             flags |= PLACE_RECT;
1703             wndpl.rcNormalPosition = *rect;
1704         }
1705         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1706     }
1707 }
1708
1709
1710 /***********************************************************************
1711  *              SetInternalWindowPos (USER32.@)
1712  */
1713 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1714                                     LPRECT rect, LPPOINT pt )
1715 {
1716     if( IsWindow(hwnd) )
1717     {
1718         WINDOWPLACEMENT16 wndpl;
1719         UINT flags;
1720
1721         wndpl.length  = sizeof(wndpl);
1722         wndpl.showCmd = showCmd;
1723         wndpl.flags = flags = 0;
1724
1725         if( pt )
1726         {
1727             flags |= PLACE_MIN;
1728             wndpl.flags |= WPF_SETMINPOSITION;
1729             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1730         }
1731         if( rect )
1732         {
1733             flags |= PLACE_RECT;
1734             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1735         }
1736         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1737     }
1738 }
1739
1740 /*******************************************************************
1741  *         WINPOS_SetActiveWindow
1742  *
1743  * SetActiveWindow() back-end. This is the only function that
1744  * can assign active status to a window. It must be called only
1745  * for the top level windows.
1746  */
1747 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1748 {
1749     CBTACTIVATESTRUCT16* cbtStruct;
1750     WND*     wndPtr=0, *wndTemp;
1751     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1752     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1753     WORD     wIconized = 0;
1754     HWND     hwndActive = 0;
1755     BOOL     bRet = 0;
1756
1757     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1758
1759     /* Get current active window from the active queue */
1760     if ( hActiveQueue )
1761     {
1762         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1763         if ( pOldActiveQueue )
1764             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1765     }
1766
1767     /* paranoid checks */
1768     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1769         goto CLEANUP_END;
1770
1771 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1772  *      return 0;
1773  */
1774     wndPtr = WIN_FindWndPtr(hWnd);
1775     hOldActiveQueue = hActiveQueue;
1776
1777     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1778     {
1779         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1780         WIN_ReleaseWndPtr(wndTemp);
1781     }
1782     else
1783         TRACE("no current active window.\n");
1784
1785     /* call CBT hook chain */
1786     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1787     {
1788         cbtStruct->fMouse     = fMouse;
1789         cbtStruct->hWndActive = hwndActive;
1790         bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1791                                      (LPARAM)SEGPTR_GET(cbtStruct) );
1792         SEGPTR_FREE(cbtStruct);
1793         if (bRet) goto CLEANUP_END;
1794     }
1795
1796     /* set prev active wnd to current active wnd and send notification */
1797     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1798     {
1799         MESSAGEQUEUE *pTempActiveQueue = 0;
1800         
1801         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1802         {
1803             if (GetSysModalWindow16() != hWnd) 
1804                 goto CLEANUP_END;
1805             /* disregard refusal if hWnd is sysmodal */
1806         }
1807
1808         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1809                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1810                         (LPARAM)hWnd );
1811
1812         /* check if something happened during message processing
1813          * (global active queue may have changed)
1814          */
1815         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1816         if(!pTempActiveQueue)
1817             goto CLEANUP_END;
1818
1819         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1820         QUEUE_Unlock( pTempActiveQueue );
1821         if( hwndPrevActive != hwndActive )
1822             goto CLEANUP_END;
1823     }
1824
1825     /* Set new active window in the message queue */
1826     hwndActive = hWnd;
1827     if ( wndPtr )
1828     {
1829         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1830         if ( pNewActiveQueue )
1831             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1832     }
1833     else /* have to do this or MDI frame activation goes to hell */
1834         if( pOldActiveQueue )
1835             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1836
1837     /* send palette messages */
1838     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1839         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1840
1841     /* if prev wnd is minimized redraw icon title */
1842     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1843
1844     /* managed windows will get ConfigureNotify event */  
1845     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1846     {
1847         /* check Z-order and bring hWnd to the top */
1848         for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1849         {
1850             if (wndTemp->dwStyle & WS_VISIBLE) break;
1851         }
1852         WIN_ReleaseDesktop();
1853         WIN_ReleaseWndPtr(wndTemp);
1854
1855         if( wndTemp != wndPtr )
1856             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1857                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1858         if (!IsWindow(hWnd))  
1859             goto CLEANUP;
1860     }
1861
1862     /* Get a handle to the new active queue */
1863     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1864
1865     /* send WM_ACTIVATEAPP if necessary */
1866     if (hOldActiveQueue != hNewActiveQueue)
1867     {
1868         WND **list, **ppWnd;
1869         WND *pDesktop = WIN_GetDesktop();
1870
1871         if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1872         {
1873             for (ppWnd = list; *ppWnd; ppWnd++)
1874             {
1875                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1876
1877                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1878                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1879                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1880             }
1881             WIN_ReleaseWinArray(list);
1882         }
1883
1884         hActiveQueue = hNewActiveQueue;
1885
1886         if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1887         {
1888             for (ppWnd = list; *ppWnd; ppWnd++)
1889             {
1890                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1891
1892                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1893                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1894                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1895             }
1896             WIN_ReleaseWinArray(list);
1897         }
1898         WIN_ReleaseDesktop();
1899         
1900         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1901     }
1902
1903     if (hWnd)
1904     {
1905         /* walk up to the first unowned window */
1906         wndTemp = WIN_LockWndPtr(wndPtr);
1907         while (wndTemp->owner)
1908         {
1909             WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1910         }
1911         /* and set last active owned popup */
1912         wndTemp->hwndLastActive = hWnd;
1913
1914         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1915         WIN_ReleaseWndPtr(wndTemp);
1916         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1917         SendMessageA( hWnd, WM_ACTIVATE,
1918                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1919                  (LPARAM)hwndPrevActive );
1920         if( !IsWindow(hWnd) ) goto CLEANUP;
1921     }
1922
1923     /* change focus if possible */
1924     if ( fChangeFocus )
1925     {
1926         if ( pNewActiveQueue )
1927         {
1928             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1929
1930             if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1931                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1932                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1933                                    0 : hwndActive );
1934         }
1935
1936         if ( pOldActiveQueue && 
1937              ( !pNewActiveQueue || 
1938                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1939         {
1940             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1941             if ( hOldFocus )
1942                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1943         }
1944     }
1945
1946     if( !hwndPrevActive && wndPtr )
1947         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1948
1949     /* if active wnd is minimized redraw icon title */
1950     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1951
1952     bRet = (hWnd == hwndActive);  /* Success? */
1953     
1954 CLEANUP: /* Unlock the message queues before returning */
1955
1956     if ( pNewActiveQueue )
1957         QUEUE_Unlock( pNewActiveQueue );
1958
1959 CLEANUP_END:
1960
1961     if ( pOldActiveQueue )
1962         QUEUE_Unlock( pOldActiveQueue );
1963
1964     WIN_ReleaseWndPtr(wndPtr);
1965     return bRet;
1966 }
1967
1968 /*******************************************************************
1969  *         WINPOS_ActivateOtherWindow
1970  *
1971  *  Activates window other than pWnd.
1972  */
1973 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1974 {
1975   BOOL  bRet = 0;
1976   WND*          pWndTo = NULL;
1977     HWND       hwndActive = 0;
1978
1979     /* Get current active window from the active queue */
1980     if ( hActiveQueue )
1981     {
1982         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1983         if ( pActiveQueue )
1984         {
1985             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1986             QUEUE_Unlock( pActiveQueue );
1987         }
1988     }
1989
1990   if( pWnd->hwndSelf == hwndPrevActive )
1991       hwndPrevActive = 0;
1992
1993   if( hwndActive != pWnd->hwndSelf && 
1994     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1995       return 0;
1996
1997   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1998       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1999   {
2000       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2001
2002       WIN_ReleaseWndPtr(pWndTo);
2003       pWndTo = WIN_FindWndPtr(hwndPrevActive);
2004
2005       while( !WINPOS_CanActivate(pWndTo) ) 
2006       {
2007          /* by now owned windows should've been taken care of */
2008           WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2009           WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2010           if( !pWndTo ) break;
2011       }
2012       WIN_ReleaseWndPtr(pWndPtr);
2013   }
2014
2015   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2016
2017   /* switch desktop queue to current active */
2018   if( pWndTo )
2019   {
2020       WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2021       WIN_ReleaseWndPtr(pWndTo);
2022       WIN_ReleaseDesktop();
2023   }
2024
2025   hwndPrevActive = 0;
2026   return bRet;  
2027 }
2028
2029 /*******************************************************************
2030  *         WINPOS_ChangeActiveWindow
2031  *
2032  */
2033 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2034 {
2035     WND *wndPtr, *wndTemp;
2036     BOOL retvalue;
2037     HWND hwndActive = 0;
2038
2039     /* Get current active window from the active queue */
2040     if ( hActiveQueue )
2041     {
2042         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2043         if ( pActiveQueue )
2044         {
2045             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2046             QUEUE_Unlock( pActiveQueue );
2047         }
2048     }
2049
2050     if (!hWnd)
2051         return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2052
2053     wndPtr = WIN_FindWndPtr(hWnd);
2054     if( !wndPtr ) return FALSE;
2055
2056     /* child windows get WM_CHILDACTIVATE message */
2057     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2058     {
2059         retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2060         goto end;
2061     }
2062
2063     if( hWnd == hwndActive )
2064     {
2065         retvalue = FALSE;
2066         goto end;
2067     }
2068
2069     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2070     {
2071         retvalue = FALSE;
2072         goto end;
2073     }
2074
2075     /* switch desktop queue to current active */
2076     wndTemp = WIN_GetDesktop();
2077     if( wndPtr->parent == wndTemp)
2078         wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2079     WIN_ReleaseDesktop();
2080
2081     retvalue = TRUE;
2082 end:
2083     WIN_ReleaseWndPtr(wndPtr);
2084     return retvalue;
2085 }
2086
2087
2088 /***********************************************************************
2089  *           WINPOS_SendNCCalcSize
2090  *
2091  * Send a WM_NCCALCSIZE message to a window.
2092  * All parameters are read-only except newClientRect.
2093  * oldWindowRect, oldClientRect and winpos must be non-NULL only
2094  * when calcValidRect is TRUE.
2095  */
2096 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2097                             RECT *newWindowRect, RECT *oldWindowRect,
2098                             RECT *oldClientRect, WINDOWPOS *winpos,
2099                             RECT *newClientRect )
2100 {
2101     NCCALCSIZE_PARAMS params;
2102     WINDOWPOS winposCopy;
2103     LONG result;
2104
2105     params.rgrc[0] = *newWindowRect;
2106     if (calcValidRect)
2107     {
2108         winposCopy = *winpos;
2109         params.rgrc[1] = *oldWindowRect;
2110         params.rgrc[2] = *oldClientRect;
2111         params.lppos = &winposCopy;
2112     }
2113     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2114                              (LPARAM)&params );
2115     TRACE("%d,%d-%d,%d\n",
2116                  params.rgrc[0].left, params.rgrc[0].top,
2117                  params.rgrc[0].right, params.rgrc[0].bottom );
2118
2119     /* If the application send back garbage, ignore it */
2120     if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2121         *newClientRect = params.rgrc[0];
2122
2123     return result;
2124 }
2125
2126
2127 /***********************************************************************
2128  *           WINPOS_HandleWindowPosChanging16
2129  *
2130  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2131  */
2132 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2133 {
2134     POINT maxSize, minTrack;
2135     if (winpos->flags & SWP_NOSIZE) return 0;
2136     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2137         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2138     {
2139         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2140         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2141         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2142         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2143         {
2144             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2145             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2146         }
2147     }
2148     return 0;
2149 }
2150
2151
2152 /***********************************************************************
2153  *           WINPOS_HandleWindowPosChanging
2154  *
2155  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2156  */
2157 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2158 {
2159     POINT maxSize, minTrack;
2160     if (winpos->flags & SWP_NOSIZE) return 0;
2161     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2162         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2163     {
2164         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2165         winpos->cx = min( winpos->cx, maxSize.x );
2166         winpos->cy = min( winpos->cy, maxSize.y );
2167         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2168         {
2169             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2170             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2171         }
2172     }
2173     return 0;
2174 }
2175
2176 /***********************************************************************
2177  *           SWP_DoOwnedPopups
2178  *
2179  * fix Z order taking into account owned popups -
2180  * basically we need to maintain them above the window that owns them
2181  *
2182  * FIXME: hide/show owned popups when owner visibility changes.
2183  */
2184 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2185 {
2186     WND*        w = WIN_LockWndPtr(pDesktop->child);
2187
2188     WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2189
2190     if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2191     {
2192         /* make sure this popup stays above the owner */
2193
2194         HWND hwndLocalPrev = HWND_TOP;
2195
2196         if( hwndInsertAfter != HWND_TOP )
2197         {
2198             while( w && w != wndPtr->owner )
2199             {
2200                 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2201                 if( hwndLocalPrev == hwndInsertAfter ) break;
2202                 WIN_UpdateWndPtr(&w,w->next);
2203             }
2204             hwndInsertAfter = hwndLocalPrev;
2205         }
2206     }
2207     else if( wndPtr->dwStyle & WS_CHILD )
2208         goto END; 
2209
2210     WIN_UpdateWndPtr(&w, pDesktop->child);
2211
2212     while( w )
2213     {
2214         if( w == wndPtr ) break; 
2215
2216         if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2217         {
2218             SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
2219                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2220             hwndInsertAfter = w->hwndSelf;
2221         }
2222         WIN_UpdateWndPtr(&w, w->next);
2223     }
2224
2225 END:
2226     WIN_ReleaseWndPtr(w);
2227     return hwndInsertAfter;
2228 }
2229
2230 /***********************************************************************
2231  *           SWP_CopyValidBits
2232  *
2233  * Make window look nice without excessive repainting
2234  *
2235  * visible and update regions are in window coordinates
2236  * client and window rectangles are in parent client coordinates
2237  *
2238  * Returns: uFlags and a dirty region in *pVisRgn.
2239  */
2240 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2241                                LPRECT lpOldWndRect,
2242                                LPRECT lpOldClientRect, UINT uFlags )
2243 {
2244  RECT r;
2245  HRGN newVisRgn, dirtyRgn;
2246  INT  my = COMPLEXREGION;
2247  DWORD dflags;
2248
2249  TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2250               Wnd->rectWindow.left, Wnd->rectWindow.top,
2251               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2252               lpOldWndRect->left, lpOldWndRect->top,
2253               lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2254  TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2255               Wnd->rectClient.left, Wnd->rectClient.top,
2256               Wnd->rectClient.right, Wnd->rectClient.bottom,
2257               lpOldClientRect->left, lpOldClientRect->top,
2258               lpOldClientRect->right,lpOldClientRect->bottom );
2259
2260  if( Wnd->hrgnUpdate == 1 )
2261      uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2262
2263  dflags = DCX_WINDOW;
2264  if(Wnd->dwStyle & WS_CLIPSIBLINGS)
2265      dflags |= DCX_CLIPSIBLINGS;
2266  newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, dflags, 0, 0);
2267
2268  dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2269
2270  if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2271      my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2272
2273  if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2274  {
2275 nocopy:
2276
2277      TRACE("\twon't copy anything!\n");
2278
2279      /* set dirtyRgn to the sum of old and new visible regions 
2280       * in parent client coordinates */
2281
2282      OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2283      OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2284
2285      CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2286  }
2287  else                   /* copy valid bits to a new location */
2288  {
2289      INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2290      HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2291
2292      /* subtract already invalid region inside Wnd from the dst region */
2293
2294      if( Wnd->hrgnUpdate )
2295          if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2296              goto nocopy;
2297
2298      /* check if entire window can be copied */
2299
2300      ow = lpOldWndRect->right - lpOldWndRect->left;
2301      oh = lpOldWndRect->bottom - lpOldWndRect->top;
2302      nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2303      nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2304
2305      ocw = lpOldClientRect->right - lpOldClientRect->left;
2306      och = lpOldClientRect->bottom - lpOldClientRect->top;
2307      ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
2308      nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
2309
2310      if(  (ocw != ncw) || (och != nch) ||
2311           ( ow !=  nw) || ( oh !=  nh) ||
2312           ((lpOldClientRect->top - lpOldWndRect->top)   != 
2313            (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2314           ((lpOldClientRect->left - lpOldWndRect->left) !=
2315            (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2316      {
2317          if(uFlags & SWP_EX_PAINTSELF)
2318          {
2319              /* movement relative to the window itself */
2320              dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2321                  (lpOldClientRect->left - lpOldWndRect->left) ;
2322              dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2323                  (lpOldClientRect->top - lpOldWndRect->top) ;
2324          }
2325          else
2326          {
2327              /* movement relative to the parent's client area */
2328              dx = Wnd->rectClient.left - lpOldClientRect->left;
2329              dy = Wnd->rectClient.top - lpOldClientRect->top;
2330          }
2331
2332         /* restrict valid bits to the common client rect */
2333
2334         r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2335         r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
2336         r.right = r.left + min( ocw, ncw );
2337         r.bottom = r.top + min( och, nch );
2338
2339         REGION_CropRgn( hrgnValid, hrgnValid, &r, 
2340                         (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2341         GetRgnBox( hrgnValid, &r );
2342         if( IsRectEmpty( &r ) )
2343             goto nocopy;
2344         r = *lpOldClientRect;
2345      }
2346      else
2347      {
2348          if(uFlags & SWP_EX_PAINTSELF) {
2349              /* 
2350               * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move 
2351               * relative to itself, only the client area can change.
2352               * if the client rect didn't change, there's nothing to do.
2353               */
2354              dx = 0;
2355              dy = 0;
2356          }
2357          else
2358          {
2359              dx = Wnd->rectWindow.left - lpOldWndRect->left;
2360              dy = Wnd->rectWindow.top -  lpOldWndRect->top;
2361              OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2362          }
2363         r = *lpOldWndRect;
2364      }
2365
2366      if( !(uFlags & SWP_EX_PAINTSELF) )
2367      {
2368         /* Move remaining regions to parent coordinates */
2369         OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2370         OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
2371      }
2372      else
2373         OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2374
2375      TRACE("\tcomputing dirty region!\n");
2376
2377      /* Compute combined dirty region (old + new - valid) */
2378      CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2379      CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2380
2381      /* Blt valid bits, r is the rect to copy  */
2382
2383      if( dx || dy )
2384      {
2385          RECT rClip;
2386          HDC hDC;
2387
2388          /* get DC and clip rect with drawable rect to avoid superfluous expose events
2389             from copying clipped areas */
2390
2391          if( uFlags & SWP_EX_PAINTSELF )
2392          {
2393              hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2394                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2395              rClip.right = nw; rClip.bottom = nh;
2396          }
2397          else
2398          {
2399              hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2400                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2401              rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2402              rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2403          }
2404          rClip.left = rClip.top = 0;    
2405
2406          if( oh > nh ) r.bottom = r.top  + nh;
2407          if( ow < nw ) r.right = r.left  + nw;
2408
2409          if( IntersectRect( &r, &r, &rClip ) )
2410          {
2411                 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2412
2413                  /* When you copy the bits without repainting, parent doesn't
2414                     get validated appropriately. Therefore, we have to validate
2415                     the parent with the windows' updated region when the
2416                     parent's update region is not empty. */
2417
2418                 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2419                 {
2420                   OffsetRect(&r, dx, dy);
2421                   ValidateRect(Wnd->parent->hwndSelf, &r);
2422                 }
2423          }
2424          ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
2425                      Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
2426      }
2427  }
2428
2429  /* *pVisRgn now points to the invalidated region */
2430
2431  DeleteObject(newVisRgn);
2432  DeleteObject(dirtyRgn);
2433  return uFlags;
2434 }
2435
2436 /***********************************************************************
2437  *           SWP_DoSimpleFrameChanged
2438  *
2439  * NOTE: old and new client rect origins are identical, only
2440  *       extents may have changed. Window extents are the same.
2441  */
2442 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2443 {
2444     INT  i = 0;
2445     RECT rect;
2446     HRGN hrgn = 0;
2447
2448     if( !(swpFlags & SWP_NOCLIENTSIZE) )
2449     {
2450         /* Client rect changed its position/size, most likely a scrollar
2451          * was added/removed.
2452          *
2453          * FIXME: WVR alignment flags 
2454          */
2455
2456         if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
2457         {
2458             i++;
2459             rect.top = 0; 
2460             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2461             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2462             if(!(uFlags & SWP_EX_NOCOPY))
2463                 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2464             else
2465             {
2466                 rect.left = 0;
2467                 goto redraw;
2468             }
2469         }
2470
2471         if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2472         {
2473             if( i )
2474                 hrgn = CreateRectRgnIndirect( &rect );
2475             rect.left = 0;
2476             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2477             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2478             if(!(uFlags & SWP_EX_NOCOPY))
2479                 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2480             else
2481                 rect.top = 0;
2482             if( i++ ) 
2483                 REGION_UnionRectWithRgn( hrgn, &rect );
2484         }
2485
2486         if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2487         {
2488             rect = wndPtr->rectWindow;
2489             OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2490                                wndPtr->rectWindow.top - wndPtr->rectClient.top );
2491             i++;
2492         }
2493     }
2494
2495     if( i )
2496     {
2497 redraw:
2498         PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2499                             RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2500     }
2501     else
2502     {
2503         WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2504     }
2505
2506     if( hrgn > 1 )
2507         DeleteObject( hrgn );
2508 }
2509
2510 /***********************************************************************
2511  *           SWP_DoWinPosChanging
2512  */
2513 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
2514                                   RECT* pNewWindowRect, RECT* pNewClientRect )
2515 {
2516       /* Send WM_WINDOWPOSCHANGING message */
2517
2518     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2519         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2520
2521       /* Calculate new position and size */
2522
2523     *pNewWindowRect = wndPtr->rectWindow;
2524     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2525                                                     : wndPtr->rectClient;
2526
2527     if (!(pWinpos->flags & SWP_NOSIZE))
2528     {
2529         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
2530         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2531     }
2532     if (!(pWinpos->flags & SWP_NOMOVE))
2533     {
2534         pNewWindowRect->left    = pWinpos->x;
2535         pNewWindowRect->top     = pWinpos->y;
2536         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
2537         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2538
2539         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2540                                     pWinpos->y - wndPtr->rectWindow.top );
2541     }
2542
2543     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2544     return TRUE;
2545 }
2546
2547 /***********************************************************************
2548  *           SWP_DoNCCalcSize
2549  */
2550 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2551                               RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2552 {
2553     UINT wvrFlags = 0;
2554
2555       /* Send WM_NCCALCSIZE message to get new client area */
2556     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2557     {
2558          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2559                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2560                                     pWinpos, pNewClientRect );
2561
2562          /* FIXME: WVR_ALIGNxxx */
2563
2564          if( pNewClientRect->left != wndPtr->rectClient.left ||
2565              pNewClientRect->top != wndPtr->rectClient.top )
2566              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2567
2568          if( (pNewClientRect->right - pNewClientRect->left !=
2569               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2570              (pNewClientRect->bottom - pNewClientRect->top !=
2571               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2572              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2573     }
2574     else
2575       if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2576                                 pNewClientRect->top != wndPtr->rectClient.top) )
2577             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2578     return wvrFlags;
2579 }
2580
2581 /***********************************************************************
2582  *              SetWindowPos (USER.232)
2583  */
2584 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2585                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2586 {
2587     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2588 }
2589
2590 /***********************************************************************
2591  *              SetWindowPos (USER32.@)
2592  */
2593 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2594                           INT x, INT y, INT cx, INT cy, UINT flags )
2595 {
2596     WINDOWPOS   winpos;
2597     WND *       wndPtr,*wndTemp;
2598     RECT        newWindowRect, newClientRect;
2599     RECT        oldWindowRect, oldClientRect;
2600     HRGN        visRgn = 0;
2601     UINT        wvrFlags = 0, uFlags = 0;
2602     BOOL        retvalue, resync = FALSE, bChangePos;
2603     HWND        hwndActive = 0;
2604
2605     /* Get current active window from the active queue */
2606     if ( hActiveQueue )
2607     {
2608         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2609         if ( pActiveQueue )
2610         {
2611             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2612             QUEUE_Unlock( pActiveQueue );
2613         }
2614     }
2615
2616     TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
2617                                                  hwnd, x, y, x+cx, y+cy, flags);  
2618
2619     bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2620     flags &= ~SWP_WINE_NOHOSTMOVE;
2621
2622
2623       /* ------------------------------------------------------------------------ CHECKS */
2624
2625       /* Check window handle */
2626
2627     if (hwnd == GetDesktopWindow()) return FALSE;
2628     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2629
2630     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2631                           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2632
2633       /* Fix redundant flags */
2634
2635     if(wndPtr->dwStyle & WS_VISIBLE)
2636         flags &= ~SWP_SHOWWINDOW;
2637     else
2638     {
2639         if (!(flags & SWP_SHOWWINDOW)) 
2640               flags |= SWP_NOREDRAW;
2641         flags &= ~SWP_HIDEWINDOW;
2642     }
2643
2644     if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2645
2646     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2647         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2648         flags |= SWP_NOSIZE;    /* Already the right size */
2649
2650     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2651         flags |= SWP_NOMOVE;    /* Already the right position */
2652
2653     if (hwnd == hwndActive)
2654         flags |= SWP_NOACTIVATE;   /* Already active */
2655     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2656     {
2657         if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2658         {
2659             flags &= ~SWP_NOZORDER;
2660             hwndInsertAfter = HWND_TOP;           
2661             goto Pos;
2662         }
2663     }
2664
2665       /* Check hwndInsertAfter */
2666
2667       /* FIXME: TOPMOST not supported yet */
2668     if ((hwndInsertAfter == HWND_TOPMOST) ||
2669         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2670
2671       /* hwndInsertAfter must be a sibling of the window */
2672     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2673     {
2674          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2675
2676          if( wnd ) {
2677              if( wnd->parent != wndPtr->parent )
2678              {
2679                  retvalue = FALSE;
2680                  WIN_ReleaseWndPtr(wnd);
2681                  goto END;
2682              }
2683             /* don't need to change the Zorder of hwnd if it's already inserted
2684              * after hwndInsertAfter or when inserting hwnd after itself.
2685              */
2686              if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2687          }
2688          WIN_ReleaseWndPtr(wnd);
2689     }
2690
2691 Pos:  /* ------------------------------------------------------------------------ MAIN part */
2692
2693       /* Fill the WINDOWPOS structure */
2694
2695     winpos.hwnd = hwnd;
2696     winpos.hwndInsertAfter = hwndInsertAfter;
2697     winpos.x = x;
2698     winpos.y = y;
2699     winpos.cx = cx;
2700     winpos.cy = cy;
2701     winpos.flags = flags;
2702     
2703     SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2704
2705     if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2706     {
2707         if( wndPtr->parent == WIN_GetDesktop() )
2708             hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2709                                         hwndInsertAfter, winpos.flags );
2710         WIN_ReleaseDesktop();
2711     }
2712
2713     if(!(wndPtr->flags & WIN_NATIVE) )
2714     {
2715         if( hwndInsertAfter == HWND_TOP )
2716            winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2717         else
2718         if( hwndInsertAfter == HWND_BOTTOM )
2719            winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2720         else
2721         if( !(winpos.flags & SWP_NOZORDER) )
2722            if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2723                winpos.flags |= SWP_NOZORDER;
2724
2725         if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2726             ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2727                           != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2728         {
2729             /* get a previous visible region for SWP_CopyValidBits() */
2730             DWORD dflags = DCX_WINDOW;
2731   
2732             if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2733                dflags |= DCX_CLIPSIBLINGS;
2734
2735             visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2736         }
2737     }
2738
2739     /* Common operations */
2740
2741     wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2742
2743     if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2744     {
2745         if ( WIN_UnlinkWindow( winpos.hwnd ) )
2746            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2747     }
2748
2749     /* Reset active DCEs */
2750
2751     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2752                                          wndPtr->dwStyle & WS_VISIBLE) || 
2753         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2754     {
2755         RECT rect;
2756
2757         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2758         DCE_InvalidateDCE(wndPtr, &rect);
2759     }
2760
2761     oldWindowRect = wndPtr->rectWindow;
2762     oldClientRect = wndPtr->rectClient;
2763
2764     /* Find out if we have to redraw the whole client rect */
2765
2766     if( oldClientRect.bottom - oldClientRect.top ==
2767         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2768
2769     if( oldClientRect.right - oldClientRect.left ==
2770         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2771
2772     if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2773            (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2774     {
2775         uFlags |= SWP_EX_NOCOPY;
2776     }
2777 /* 
2778  *  Use this later in CopyValidBits()
2779  *
2780     else if( 0  )
2781         uFlags |= SWP_EX_NONCLIENT; 
2782  */
2783
2784     /* FIXME: actually do something with WVR_VALIDRECTS */
2785
2786     wndPtr->rectWindow = newWindowRect;
2787     wndPtr->rectClient = newClientRect;
2788
2789     if (wndPtr->flags & WIN_NATIVE)     /* -------------------------------------------- hosted window */
2790     {
2791         BOOL bCallDriver = TRUE;
2792         HWND tempInsertAfter = winpos.hwndInsertAfter;
2793
2794         winpos.hwndInsertAfter = hwndInsertAfter;
2795
2796         if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2797         {
2798           /* This is the only place where we need to force repainting of the contents
2799              of windows created by the host window system, all other cases go through the
2800              expose event handling */
2801
2802             if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2803             {
2804                 cx = newWindowRect.right - newWindowRect.left;
2805                 cy = newWindowRect.bottom - newWindowRect.top;
2806
2807                 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2808                 winpos.hwndInsertAfter = tempInsertAfter;
2809                 bCallDriver = FALSE;
2810
2811                 if( winpos.flags & SWP_NOCLIENTMOVE )
2812                     SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2813                 else
2814                 {
2815                     /* client area moved but window extents remained the same, copy valid bits */
2816
2817                     visRgn = CreateRectRgn( 0, 0, cx, cy );
2818                     uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
2819                                                 uFlags | SWP_EX_PAINTSELF );
2820                 }
2821             }
2822         }
2823
2824         if( bCallDriver )
2825         {
2826             if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2827             {
2828                 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2829                     (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2830                    !(uFlags & SWP_EX_NOCOPY) )
2831                 {
2832                   /* The origin of the client rect didn't move so we can try to repaint
2833                    * only the nonclient area by setting bit gravity hint for the host window system.
2834                    */
2835
2836                     if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2837                     {
2838                         HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2839                                                      newWindowRect.bottom - newWindowRect.top);
2840                         RECT rcn = newClientRect;
2841                         RECT rco = oldClientRect;
2842
2843                         OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2844                         OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2845                         IntersectRect( &rcn, &rcn, &rco );
2846                         visRgn = CreateRectRgnIndirect( &rcn );
2847                         CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2848                         DeleteObject( hrgn );
2849                         uFlags = SWP_EX_PAINTSELF;
2850                     }
2851                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2852                 }
2853             }
2854
2855             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2856             wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2857             winpos.hwndInsertAfter = tempInsertAfter;
2858         }
2859
2860         if( winpos.flags & SWP_SHOWWINDOW )
2861         {
2862                 HWND focus, curr;
2863
2864                 wndPtr->dwStyle |= WS_VISIBLE;
2865
2866                 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE; 
2867
2868                 /* focus was set to unmapped window, reset host focus 
2869                  * since the window is now visible */
2870
2871                 focus = curr = GetFocus();
2872                 while (curr) 
2873                 {
2874                     if (curr == hwnd) 
2875                     {
2876                         WND *pFocus = WIN_FindWndPtr( focus );
2877                         if (pFocus)
2878                             pFocus->pDriver->pSetFocus(pFocus);
2879                         WIN_ReleaseWndPtr(pFocus);
2880                         break;
2881                     }
2882                     curr = GetParent(curr);
2883                 }
2884         }
2885     }
2886     else                                /* -------------------------------------------- emulated window */
2887     {
2888             if( winpos.flags & SWP_SHOWWINDOW )
2889             {
2890                 wndPtr->dwStyle |= WS_VISIBLE;
2891                 uFlags |= SWP_EX_PAINTSELF;
2892                 visRgn = 1; /* redraw the whole window */
2893             }
2894             else if( !(winpos.flags & SWP_NOREDRAW) )
2895             {
2896                 if( winpos.flags & SWP_HIDEWINDOW )
2897                 {
2898                     if( visRgn > 1 ) /* map to parent */
2899                         OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2900                     else
2901                         visRgn = 0;
2902                 }
2903                 else
2904                 {
2905                     if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2906                          uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
2907                                                             &oldClientRect, uFlags);
2908                     else
2909                     {
2910                         /* nothing moved, redraw frame if needed */
2911                          
2912                         if( winpos.flags & SWP_FRAMECHANGED )
2913                             SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2914                         if( visRgn )
2915                         {
2916                             DeleteObject( visRgn );
2917                             visRgn = 0;
2918                         } 
2919                     }
2920                 }
2921             }
2922     }
2923
2924     if( winpos.flags & SWP_HIDEWINDOW )
2925     {
2926         wndPtr->dwStyle &= ~WS_VISIBLE;
2927     }
2928
2929     if (hwnd == CARET_GetHwnd())
2930     {
2931         if( winpos.flags & SWP_HIDEWINDOW )
2932             HideCaret(hwnd); 
2933         else if (winpos.flags & SWP_SHOWWINDOW)
2934             ShowCaret(hwnd);
2935     }
2936
2937     /* ------------------------------------------------------------------------ FINAL */
2938
2939     if (wndPtr->flags & WIN_NATIVE)
2940         EVENT_Synchronize();  /* Synchronize with the host window system */
2941
2942     wndTemp = WIN_GetDesktop();
2943
2944     /* repaint invalidated region (if any) 
2945      *
2946      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2947      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
2948      */
2949
2950     if( visRgn )
2951     {
2952         if( !(winpos.flags & SWP_NOREDRAW) )
2953         {
2954  
2955             /*  Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2956                 its parent and sibling and so on, and then erase the parent window 
2957                 background if the parent is either a top-level window or its parent's parent  
2958                 is top-level window. Rely on the system to repaint other affected 
2959                 windows later on.  */ 
2960             if( uFlags & SWP_EX_PAINTSELF )
2961             {
2962                 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2963                                 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2964                                 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2965             }
2966             else
2967             {
2968                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2969                                 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, 
2970                                 RDW_EX_USEHRGN );
2971             }
2972
2973             if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2974                 {
2975                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, 
2976                                 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2977             }
2978         }
2979         if( visRgn != 1 )
2980             DeleteObject( visRgn );
2981     }
2982
2983     WIN_ReleaseDesktop();
2984
2985     if (!(flags & SWP_NOACTIVATE))
2986             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2987
2988       /* And last, send the WM_WINDOWPOSCHANGED message */
2989
2990     TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2991
2992     if ( resync ||
2993         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2994          !(winpos.flags & SWP_NOSENDCHANGING)) )
2995     {
2996         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2997         if (resync) EVENT_Synchronize();
2998     }
2999
3000     retvalue = TRUE;
3001 END:
3002     WIN_ReleaseWndPtr(wndPtr);
3003     return retvalue;
3004 }
3005
3006                                         
3007 /***********************************************************************
3008  *              BeginDeferWindowPos (USER.259)
3009  */
3010 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3011 {
3012     return BeginDeferWindowPos( count );
3013 }
3014
3015
3016 /***********************************************************************
3017  *              BeginDeferWindowPos (USER32.@)
3018  */
3019 HDWP WINAPI BeginDeferWindowPos( INT count )
3020 {
3021     HDWP handle;
3022     DWP *pDWP;
3023
3024     if (count < 0) 
3025     {
3026         SetLastError(ERROR_INVALID_PARAMETER);
3027         return 0;
3028     }
3029     /* Windows allows zero count, in which case it allocates context for 8 moves */
3030     if (count == 0) count = 8;
3031
3032     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3033     if (!handle) return 0;
3034     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3035     pDWP->actualCount    = 0;
3036     pDWP->suggestedCount = count;
3037     pDWP->valid          = TRUE;
3038     pDWP->wMagic         = DWP_MAGIC;
3039     pDWP->hwndParent     = 0;
3040     return handle;
3041 }
3042
3043
3044 /***********************************************************************
3045  *              DeferWindowPos (USER.260)
3046  */
3047 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3048                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
3049                                 UINT16 flags )
3050 {
3051     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3052                              x, y, cx, cy, flags );
3053 }
3054
3055
3056 /***********************************************************************
3057  *              DeferWindowPos (USER32.@)
3058  */
3059 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3060                                 INT x, INT y, INT cx, INT cy,
3061                                 UINT flags )
3062 {
3063     DWP *pDWP;
3064     int i;
3065     HDWP newhdwp = hdwp,retvalue;
3066     /* HWND parent; */
3067     WND *pWnd;
3068
3069     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3070     if (!pDWP) return 0;
3071     if (hwnd == GetDesktopWindow()) return 0;
3072
3073     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3074         USER_HEAP_FREE( hdwp );
3075         return 0;
3076     }
3077         
3078 /* Numega Bounds Checker Demo dislikes the following code.
3079    In fact, I've not been able to find any "same parent" requirement in any docu
3080    [AM 980509]
3081  */
3082 #if 0
3083     /* All the windows of a DeferWindowPos() must have the same parent */
3084     parent = pWnd->parent->hwndSelf;
3085     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3086     else if (parent != pDWP->hwndParent)
3087     {
3088         USER_HEAP_FREE( hdwp );
3089         retvalue = 0;
3090         goto END;
3091     }
3092 #endif
3093
3094     for (i = 0; i < pDWP->actualCount; i++)
3095     {
3096         if (pDWP->winPos[i].hwnd == hwnd)
3097         {
3098               /* Merge with the other changes */
3099             if (!(flags & SWP_NOZORDER))
3100             {
3101                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3102             }
3103             if (!(flags & SWP_NOMOVE))
3104             {
3105                 pDWP->winPos[i].x = x;
3106                 pDWP->winPos[i].y = y;
3107             }                
3108             if (!(flags & SWP_NOSIZE))
3109             {
3110                 pDWP->winPos[i].cx = cx;
3111                 pDWP->winPos[i].cy = cy;
3112             }
3113             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3114                                                SWP_NOZORDER | SWP_NOREDRAW |
3115                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
3116                                                SWP_NOOWNERZORDER);
3117             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3118                                               SWP_FRAMECHANGED);
3119             retvalue = hdwp;
3120             goto END;
3121         }
3122     }
3123     if (pDWP->actualCount >= pDWP->suggestedCount)
3124     {
3125         newhdwp = USER_HEAP_REALLOC( hdwp,
3126                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3127         if (!newhdwp)
3128         {
3129             retvalue = 0;
3130             goto END;
3131         }
3132         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3133         pDWP->suggestedCount++;
3134     }
3135     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3136     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3137     pDWP->winPos[pDWP->actualCount].x = x;
3138     pDWP->winPos[pDWP->actualCount].y = y;
3139     pDWP->winPos[pDWP->actualCount].cx = cx;
3140     pDWP->winPos[pDWP->actualCount].cy = cy;
3141     pDWP->winPos[pDWP->actualCount].flags = flags;
3142     pDWP->actualCount++;
3143     retvalue = newhdwp;
3144 END:
3145     WIN_ReleaseWndPtr(pWnd);
3146     return retvalue;
3147 }
3148
3149
3150 /***********************************************************************
3151  *              EndDeferWindowPos (USER.261)
3152  */
3153 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3154 {
3155     return EndDeferWindowPos( hdwp );
3156 }
3157
3158
3159 /***********************************************************************
3160  *              EndDeferWindowPos (USER32.@)
3161  */
3162 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3163 {
3164     DWP *pDWP;
3165     WINDOWPOS *winpos;
3166     BOOL res = TRUE;
3167     int i;
3168
3169     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3170     if (!pDWP) return FALSE;
3171     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3172     {
3173         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3174                                     winpos->x, winpos->y, winpos->cx,
3175                                     winpos->cy, winpos->flags ))) break;
3176     }
3177     USER_HEAP_FREE( hdwp );
3178     return res;
3179 }
3180
3181
3182 /***********************************************************************
3183  *              TileChildWindows (USER.199)
3184  */
3185 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3186 {
3187     FIXME("(%04x, %d): stub\n", parent, action);
3188 }
3189
3190 /***********************************************************************
3191  *              CascadeChildWindows (USER.198)
3192  */
3193 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3194 {
3195     FIXME("(%04x, %d): stub\n", parent, action);
3196 }
3197
3198 /***********************************************************************
3199  *              SetProgmanWindow (USER32.@)
3200  */
3201 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3202 {
3203         hGlobalProgmanWindow = hwnd;
3204         return hGlobalProgmanWindow;
3205 }
3206
3207 /***********************************************************************
3208  *              GetProgmanWindow (USER32.@)
3209  */
3210 HRESULT WINAPI GetProgmanWindow ( )
3211 {
3212         return hGlobalProgmanWindow;
3213 }
3214
3215 /***********************************************************************
3216  *              SetShellWindowEx (USER32.@)
3217  * hwndProgman =  Progman[Program Manager]
3218  *                |-> SHELLDLL_DefView
3219  * hwndListView = |   |-> SysListView32
3220  *                |   |   |-> tooltips_class32
3221  *                |   |
3222  *                |   |-> SysHeader32
3223  *                |   
3224  *                |-> ProxyTarget
3225  */
3226 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3227 {
3228         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3229         hGlobalShellWindow = hwndProgman;
3230         return hGlobalShellWindow;
3231
3232 }
3233
3234 /***********************************************************************
3235  *              SetTaskmanWindow (USER32.@)
3236  * NOTES
3237  *   hwnd = MSTaskSwWClass 
3238  *          |-> SysTabControl32
3239  */
3240 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3241 {
3242         hGlobalTaskmanWindow = hwnd;
3243         return hGlobalTaskmanWindow;
3244 }
3245
3246 /***********************************************************************
3247  *              GetTaskmanWindow (USER32.@)
3248  */
3249 HRESULT WINAPI GetTaskmanWindow ( )
3250 {       
3251         return hGlobalTaskmanWindow;
3252 }