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