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