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