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