There were two copies of the DdeCmpStringHandles (A and W) and that
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996 Alex Korobka
6  */
7
8 #include <string.h>
9 #include "sysmetrics.h"
10 #include "heap.h"
11 #include "module.h"
12 #include "user.h"
13 #include "win.h"
14 #include "hook.h"
15 #include "message.h"
16 #include "queue.h"
17 #include "options.h"
18 #include "task.h"
19 #include "winpos.h"
20 #include "dce.h"
21 #include "nonclient.h"
22 #include "debug.h"
23 #include "x11drv.h"
24
25 #define HAS_DLGFRAME(style,exStyle) \
26     (((exStyle) & WS_EX_DLGMODALFRAME) || \
27      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
28
29 #define HAS_THICKFRAME(style) \
30     (((style) & WS_THICKFRAME) && \
31      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
32
33 #define  SWP_AGG_NOGEOMETRYCHANGE \
34     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
35 #define  SWP_AGG_NOPOSCHANGE \
36     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
37 #define  SWP_AGG_STATUSFLAGS \
38     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
39
40 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
41
42 #define PLACE_MIN               0x0001
43 #define PLACE_MAX               0x0002
44 #define PLACE_RECT              0x0004
45
46 #define SMC_NOCOPY              0x0001
47 #define SMC_NOPARENTERASE       0x0002
48 #define SMC_DRAWFRAME           0x0004
49 #define SMC_SETXPOS             0x0008
50
51 /* ----- internal variables ----- */
52
53 static HWND32 hwndActive      = 0;  /* Currently active window */
54 static HWND32 hwndPrevActive  = 0;  /* Previously active window */
55 static HWND32 hGlobalShellWindow=0; /*the shell*/
56
57 static LPCSTR atomInternalPos;
58
59 extern MESSAGEQUEUE* pActiveQueue;
60
61 /***********************************************************************
62  *           WINPOS_CreateInternalPosAtom
63  */
64 BOOL32 WINPOS_CreateInternalPosAtom()
65 {
66     LPSTR str = "SysIP";
67     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtom32A(str);
68     return (atomInternalPos) ? TRUE : FALSE;
69 }
70
71 /***********************************************************************
72  *           WINPOS_CheckInternalPos
73  *
74  * Called when a window is destroyed.
75  */
76 void WINPOS_CheckInternalPos( HWND32 hwnd )
77 {
78     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
79
80     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
81     if( hwnd == hwndActive )
82     {
83         hwndActive = 0; 
84         WARN(win, "\tattempt to activate destroyed window!\n");
85     }
86
87     if( lpPos )
88     {
89         if( IsWindow32(lpPos->hwndIconTitle) ) 
90             DestroyWindow32( lpPos->hwndIconTitle );
91         HeapFree( SystemHeap, 0, lpPos );
92     }
93 }
94
95 /***********************************************************************
96  *           WINPOS_FindIconPos
97  *
98  * Find a suitable place for an iconic window.
99  */
100 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
101 {
102     RECT16 rectParent;
103     short x, y, xspacing, yspacing;
104
105     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
106     if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
107         (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
108         return pt;  /* The icon already has a suitable position */
109
110     xspacing = SYSMETRICS_CXICONSPACING;
111     yspacing = SYSMETRICS_CYICONSPACING;
112
113     y = rectParent.bottom;
114     for (;;)
115     {
116         for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
117         {
118               /* Check if another icon already occupies this spot */
119             WND *childPtr = wndPtr->parent->child;
120             while (childPtr)
121             {
122                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
123                 {
124                     if ((childPtr->rectWindow.left < x + xspacing) &&
125                         (childPtr->rectWindow.right >= x) &&
126                         (childPtr->rectWindow.top <= y) &&
127                         (childPtr->rectWindow.bottom > y - yspacing))
128                         break;  /* There's a window in there */
129                 }
130                 childPtr = childPtr->next;
131             }
132             if (!childPtr) /* No window was found, so it's OK for us */
133             {
134                 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
135                 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
136                 return pt;
137             }
138         }
139         y -= yspacing;
140     }
141 }
142
143
144 /***********************************************************************
145  *           ArrangeIconicWindows16   (USER.170)
146  */
147 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent) 
148 {
149     return ArrangeIconicWindows32(parent);
150 }
151 /***********************************************************************
152  *           ArrangeIconicWindows32   (USER32.7)
153  */
154 UINT32 WINAPI ArrangeIconicWindows32( HWND32 parent )
155 {
156     RECT32 rectParent;
157     HWND32 hwndChild;
158     INT32 x, y, xspacing, yspacing;
159
160     GetClientRect32( parent, &rectParent );
161     x = rectParent.left;
162     y = rectParent.bottom;
163     xspacing = SYSMETRICS_CXICONSPACING;
164     yspacing = SYSMETRICS_CYICONSPACING;
165
166     hwndChild = GetWindow32( parent, GW_CHILD );
167     while (hwndChild)
168     {
169         if( IsIconic32( hwndChild ) )
170         {
171             WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
172             SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
173                             y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
174                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
175             if( IsWindow32(hwndChild) )
176                 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
177             if (x <= rectParent.right - xspacing) x += xspacing;
178             else
179             {
180                 x = rectParent.left;
181                 y -= yspacing;
182             }
183         }
184         hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
185     }
186     return yspacing;
187 }
188
189
190 /***********************************************************************
191  *             SwitchToThisWindow16   (USER.172)
192  */
193 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
194 {
195     SwitchToThisWindow32( hwnd, restore );
196 }
197
198
199 /***********************************************************************
200  *             SwitchToThisWindow32   (USER32.539)
201  */
202 void WINAPI SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
203 {
204     ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
205 }
206
207
208 /***********************************************************************
209  *           GetWindowRect16   (USER.32)
210  */
211 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
212 {
213     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
214     if (!wndPtr) return;
215     
216     CONV_RECT32TO16( &wndPtr->rectWindow, rect );
217     if (wndPtr->dwStyle & WS_CHILD)
218         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
219 }
220
221
222 /***********************************************************************
223  *           GetWindowRect32   (USER32.308)
224  */
225 BOOL32 WINAPI GetWindowRect32( HWND32 hwnd, LPRECT32 rect ) 
226 {
227     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
228     if (!wndPtr) return FALSE;
229     
230     *rect = wndPtr->rectWindow;
231     if (wndPtr->dwStyle & WS_CHILD)
232         MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
233     return TRUE;
234 }
235
236
237 /***********************************************************************
238  *           GetWindowRgn32 
239  */
240 BOOL32 WINAPI GetWindowRgn32 ( HWND32 hwnd, HRGN32 hrgn )
241
242 {
243   RECT32    rect;
244   WND * wndPtr = WIN_FindWndPtr( hwnd ); 
245   if (!wndPtr) return (ERROR);
246
247   FIXME (win, "GetWindowRgn32: doesn't really do regions\n"); 
248   
249   memset (&rect, 0, sizeof(rect));
250
251   GetWindowRect32 ( hwnd, &rect );
252
253   FIXME (win, "Check whether a valid region here\n");
254
255   SetRectRgn32 ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
256
257   return (SIMPLEREGION);
258 }
259
260 /***********************************************************************
261  *           SetWindowRgn32 
262  */
263 INT32 WINAPI SetWindowRgn32( HWND32 hwnd, HRGN32 hrgn,BOOL32 bRedraw)
264
265 {
266
267   FIXME (win, "SetWindowRgn32: stub\n"); 
268   return TRUE;
269 }
270
271 /***********************************************************************
272  *           SetWindowRgn16 
273  */
274 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
275
276 {
277
278   FIXME (win, "SetWindowRgn16: stub\n"); 
279   return TRUE;
280 }
281
282
283 /***********************************************************************
284  *           GetClientRect16   (USER.33)
285  */
286 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
287 {
288     WND * wndPtr = WIN_FindWndPtr( hwnd );
289
290     rect->left = rect->top = rect->right = rect->bottom = 0;
291     if (wndPtr) 
292     {
293         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
294         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
295     }
296 }
297
298
299 /***********************************************************************
300  *           GetClientRect32   (USER32.220)
301  */
302 void WINAPI GetClientRect32( HWND32 hwnd, LPRECT32 rect ) 
303 {
304     WND * wndPtr = WIN_FindWndPtr( hwnd );
305
306     rect->left = rect->top = rect->right = rect->bottom = 0;
307     if (wndPtr) 
308     {
309         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
310         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
311     }
312 }
313
314
315 /*******************************************************************
316  *         ClientToScreen16   (USER.28)
317  */
318 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
319 {
320     MapWindowPoints16( hwnd, 0, lppnt, 1 );
321 }
322
323
324 /*******************************************************************
325  *         ClientToScreen32   (USER32.52)
326  */
327 BOOL32 WINAPI ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
328 {
329     MapWindowPoints32( hwnd, 0, lppnt, 1 );
330     return TRUE;
331 }
332
333
334 /*******************************************************************
335  *         ScreenToClient16   (USER.29)
336  */
337 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
338 {
339     MapWindowPoints16( 0, hwnd, lppnt, 1 );
340 }
341
342
343 /*******************************************************************
344  *         ScreenToClient32   (USER32.447)
345  */
346 void WINAPI ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
347 {
348     MapWindowPoints32( 0, hwnd, lppnt, 1 );
349 }
350
351
352 /***********************************************************************
353  *           WINPOS_WindowFromPoint
354  *
355  * Find the window and hittest for a given point.
356  */
357 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
358 {
359     WND *wndPtr;
360     INT16 hittest = HTERROR;
361     POINT16 xy = pt;
362
363    *ppWnd = NULL;
364     wndPtr = wndScope->child;
365     if( wndScope->flags & WIN_MANAGED )
366     {
367         /* this prevents mouse clicks from going "through" scrollbars in managed mode */
368         if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
369             pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
370             goto hittest;
371     }
372     MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
373
374     for (;;)
375     {
376         while (wndPtr)
377         {
378             /* If point is in window, and window is visible, and it  */
379             /* is enabled (or it's a top-level window), then explore */
380             /* its children. Otherwise, go to the next window.       */
381
382             if ((wndPtr->dwStyle & WS_VISIBLE) &&
383                 (!(wndPtr->dwStyle & WS_DISABLED) ||
384                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
385                 (xy.x >= wndPtr->rectWindow.left) &&
386                 (xy.x < wndPtr->rectWindow.right) &&
387                 (xy.y >= wndPtr->rectWindow.top) &&
388                 (xy.y < wndPtr->rectWindow.bottom))
389             {
390                 *ppWnd = wndPtr;  /* Got a suitable window */
391
392                 /* If window is minimized or disabled, return at once */
393                 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
394                 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
395
396                 /* If point is not in client area, ignore the children */
397                 if ((xy.x < wndPtr->rectClient.left) ||
398                     (xy.x >= wndPtr->rectClient.right) ||
399                     (xy.y < wndPtr->rectClient.top) ||
400                     (xy.y >= wndPtr->rectClient.bottom)) break;
401
402                 xy.x -= wndPtr->rectClient.left;
403                 xy.y -= wndPtr->rectClient.top;
404                 wndPtr = wndPtr->child;
405             }
406             else wndPtr = wndPtr->next;
407         }
408
409 hittest:
410         /* If nothing found, try the scope window */
411         if (!*ppWnd) *ppWnd = wndScope;
412
413         /* Send the WM_NCHITTEST message (only if to the same task) */
414         if ((*ppWnd)->hmemTaskQ == GetFastQueue())
415         {
416             hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 
417                                                  0, MAKELONG( pt.x, pt.y ) );
418             if (hittest != HTTRANSPARENT) return hittest;  /* Found the window */
419         }
420         else return HTCLIENT;
421
422         /* If no children found in last search, make point relative to parent */
423         if (!wndPtr)
424         {
425             xy.x += (*ppWnd)->rectClient.left;
426             xy.y += (*ppWnd)->rectClient.top;
427         }
428
429         /* Restart the search from the next sibling */
430         wndPtr = (*ppWnd)->next;
431         *ppWnd = (*ppWnd)->parent;
432     }
433 }
434
435
436 /*******************************************************************
437  *         WindowFromPoint16   (USER.30)
438  */
439 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
440 {
441     WND *pWnd;
442     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
443     return pWnd->hwndSelf;
444 }
445
446
447 /*******************************************************************
448  *         WindowFromPoint32   (USER32.582)
449  */
450 HWND32 WINAPI WindowFromPoint32( POINT32 pt )
451 {
452     WND *pWnd;
453     POINT16 pt16;
454     CONV_POINT32TO16( &pt, &pt16 );
455     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
456     return (HWND32)pWnd->hwndSelf;
457 }
458
459
460 /*******************************************************************
461  *         ChildWindowFromPoint16   (USER.191)
462  */
463 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
464 {
465     POINT32 pt32;
466     CONV_POINT16TO32( &pt, &pt32 );
467     return (HWND16)ChildWindowFromPoint32( hwndParent, pt32 );
468 }
469
470
471 /*******************************************************************
472  *         ChildWindowFromPoint32   (USER32.49)
473  */
474 HWND32 WINAPI ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
475 {
476     /* pt is in the client coordinates */
477
478     WND* wnd = WIN_FindWndPtr(hwndParent);
479     RECT32 rect;
480
481     if( !wnd ) return 0;
482
483     /* get client rect fast */
484     rect.top = rect.left = 0;
485     rect.right = wnd->rectClient.right - wnd->rectClient.left;
486     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
487
488     if (!PtInRect32( &rect, pt )) return 0;
489
490     wnd = wnd->child;
491     while ( wnd )
492     {
493         if (PtInRect32( &wnd->rectWindow, pt )) return wnd->hwndSelf;
494         wnd = wnd->next;
495     }
496     return hwndParent;
497 }
498
499 /*******************************************************************
500  *         ChildWindowFromPointEx16   (USER.50)
501  */
502 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
503 {
504     POINT32 pt32;
505     CONV_POINT16TO32( &pt, &pt32 );
506     return (HWND16)ChildWindowFromPointEx32( hwndParent, pt32, uFlags );
507 }
508
509
510 /*******************************************************************
511  *         ChildWindowFromPointEx32   (USER32.50)
512  */
513 HWND32 WINAPI ChildWindowFromPointEx32( HWND32 hwndParent, POINT32 pt,
514                 UINT32 uFlags)
515 {
516     /* pt is in the client coordinates */
517
518     WND* wnd = WIN_FindWndPtr(hwndParent);
519     RECT32 rect;
520
521     if( !wnd ) return 0;
522
523     /* get client rect fast */
524     rect.top = rect.left = 0;
525     rect.right = wnd->rectClient.right - wnd->rectClient.left;
526     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
527
528     if (!PtInRect32( &rect, pt )) return 0;
529
530     wnd = wnd->child;
531     while ( wnd )
532     {
533         if (PtInRect32( &wnd->rectWindow, pt )) {
534                 if ( (uFlags & CWP_SKIPINVISIBLE) && 
535                                 !(wnd->dwStyle & WS_VISIBLE) )
536                         wnd = wnd->next;
537                 else if ( (uFlags & CWP_SKIPDISABLED) && 
538                                 (wnd->dwStyle & WS_DISABLED) )
539                         wnd = wnd->next;
540                 else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
541                                 (wnd->dwExStyle & WS_EX_TRANSPARENT) )
542                         wnd = wnd->next;
543                 else
544                         return wnd->hwndSelf;
545         }
546     }
547     return hwndParent;
548 }
549
550
551 /*******************************************************************
552  *         WINPOS_GetWinOffset
553  *
554  * Calculate the offset between the origin of the two windows. Used
555  * to implement MapWindowPoints.
556  */
557 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
558                                  POINT32 *offset )
559 {
560     WND * wndPtr;
561
562     offset->x = offset->y = 0;
563     if (hwndFrom == hwndTo ) return;
564
565       /* Translate source window origin to screen coords */
566     if (hwndFrom)
567     {
568         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
569         {
570             ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
571             return;
572         }
573         while (wndPtr->parent)
574         {
575             offset->x += wndPtr->rectClient.left;
576             offset->y += wndPtr->rectClient.top;
577             wndPtr = wndPtr->parent;
578         }
579     }
580
581       /* Translate origin to destination window coords */
582     if (hwndTo)
583     {
584         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
585         {
586             ERR(win,"bad hwndTo = %04x\n", hwndTo );
587             return;
588         }
589         while (wndPtr->parent)
590         {
591             offset->x -= wndPtr->rectClient.left;
592             offset->y -= wndPtr->rectClient.top;
593             wndPtr = wndPtr->parent;
594         }    
595     }
596 }
597
598
599 /*******************************************************************
600  *         MapWindowPoints16   (USER.258)
601  */
602 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
603                                LPPOINT16 lppt, UINT16 count )
604 {
605     POINT32 offset;
606
607     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
608     while (count--)
609     {
610         lppt->x += offset.x;
611         lppt->y += offset.y;
612         lppt++;
613     }
614 }
615
616
617 /*******************************************************************
618  *         MapWindowPoints32   (USER32.386)
619  */
620 void WINAPI MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
621                                LPPOINT32 lppt, UINT32 count )
622 {
623     POINT32 offset;
624
625     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
626     while (count--)
627     {
628         lppt->x += offset.x;
629         lppt->y += offset.y;
630         lppt++;
631     }
632 }
633
634
635 /***********************************************************************
636  *           IsIconic16   (USER.31)
637  */
638 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
639 {
640     return IsIconic32(hWnd);
641 }
642
643
644 /***********************************************************************
645  *           IsIconic32   (USER32.345)
646  */
647 BOOL32 WINAPI IsIconic32(HWND32 hWnd)
648 {
649     WND * wndPtr = WIN_FindWndPtr(hWnd);
650     if (wndPtr == NULL) return FALSE;
651     return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
652 }
653  
654  
655 /***********************************************************************
656  *           IsZoomed   (USER.272)
657  */
658 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
659 {
660     return IsZoomed32(hWnd);
661 }
662
663
664 /***********************************************************************
665  *           IsZoomed   (USER32.352)
666  */
667 BOOL32 WINAPI IsZoomed32(HWND32 hWnd)
668 {
669     WND * wndPtr = WIN_FindWndPtr(hWnd);
670     if (wndPtr == NULL) return FALSE;
671     return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
672 }
673
674
675 /*******************************************************************
676  *         GetActiveWindow    (USER.60)
677  */
678 HWND16 WINAPI GetActiveWindow16(void)
679 {
680     return (HWND16)hwndActive;
681 }
682
683 /*******************************************************************
684  *         GetActiveWindow    (USER32.205)
685  */
686 HWND32 WINAPI GetActiveWindow32(void)
687 {
688     return (HWND32)hwndActive;
689 }
690
691
692 /*******************************************************************
693  *         WINPOS_CanActivate
694  */
695 static BOOL32 WINPOS_CanActivate(WND* pWnd)
696 {
697     if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD)) 
698         == WS_VISIBLE) ) return TRUE;
699     return FALSE;
700 }
701
702
703 /*******************************************************************
704  *         SetActiveWindow16    (USER.59)
705  */
706 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
707 {
708     return SetActiveWindow32(hwnd);
709 }
710
711
712 /*******************************************************************
713  *         SetActiveWindow32    (USER32.463)
714  */
715 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
716 {
717     HWND32 prev = hwndActive;
718     WND *wndPtr = WIN_FindWndPtr( hwnd );
719
720     if ( !WINPOS_CanActivate(wndPtr) ) return 0;
721
722     WINPOS_SetActiveWindow( hwnd, 0, 0 );
723     return prev;
724 }
725
726
727 /*******************************************************************
728  *         GetForegroundWindow16    (USER.608)
729  */
730 HWND16 WINAPI GetForegroundWindow16(void)
731 {
732     return (HWND16)GetForegroundWindow32();
733 }
734
735
736 /*******************************************************************
737  *         SetForegroundWindow16    (USER.609)
738  */
739 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
740 {
741     return SetForegroundWindow32( hwnd );
742 }
743
744
745 /*******************************************************************
746  *         GetForegroundWindow32    (USER32.241)
747  */
748 HWND32 WINAPI GetForegroundWindow32(void)
749 {
750     return GetActiveWindow32();
751 }
752
753
754 /*******************************************************************
755  *         SetForegroundWindow32    (USER32.482)
756  */
757 BOOL32 WINAPI SetForegroundWindow32( HWND32 hwnd )
758 {
759     SetActiveWindow32( hwnd );
760     return TRUE;
761 }
762
763
764 /*******************************************************************
765  *         GetShellWindow16    (USER.600)
766  */
767 HWND16 WINAPI GetShellWindow16(void)
768 {
769     return GetShellWindow32();
770 }
771
772 /*******************************************************************
773  *         SetShellWindow32    (USER32.504)
774  */
775 HWND32 WINAPI SetShellWindow32(HWND32 hwndshell)
776 {   WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
777
778     hGlobalShellWindow = hwndshell;
779     return hGlobalShellWindow;
780 }
781
782
783 /*******************************************************************
784  *         GetShellWindow32    (USER32.287)
785  */
786 HWND32 WINAPI GetShellWindow32(void)
787 {   WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
788
789     return hGlobalShellWindow;
790 }
791
792
793 /***********************************************************************
794  *           BringWindowToTop16   (USER.45)
795  */
796 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
797 {
798     return BringWindowToTop32(hwnd);
799 }
800
801
802 /***********************************************************************
803  *           BringWindowToTop32   (USER32.11)
804  */
805 BOOL32 WINAPI BringWindowToTop32( HWND32 hwnd )
806 {
807     return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
808 }
809
810
811 /***********************************************************************
812  *           MoveWindow16   (USER.56)
813  */
814 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
815                             BOOL16 repaint )
816 {
817     return MoveWindow32(hwnd,x,y,cx,cy,repaint);
818 }
819
820
821 /***********************************************************************
822  *           MoveWindow32   (USER32.399)
823  */
824 BOOL32 WINAPI MoveWindow32( HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy,
825                             BOOL32 repaint )
826 {    
827     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
828     if (!repaint) flags |= SWP_NOREDRAW;
829     TRACE(win, "%04x %d,%d %dx%d %d\n", 
830             hwnd, x, y, cx, cy, repaint );
831     return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
832 }
833
834 /***********************************************************************
835  *           WINPOS_InitInternalPos
836  */
837 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT32 pt, 
838                                              LPRECT32 restoreRect )
839 {
840     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( wnd->hwndSelf,
841                                                       atomInternalPos );
842     if( !lpPos )
843     {
844         /* this happens when the window is minimized/maximized 
845          * for the first time (rectWindow is not adjusted yet) */
846
847         lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
848         if( !lpPos ) return NULL;
849
850         SetProp32A( wnd->hwndSelf, atomInternalPos, (HANDLE32)lpPos );
851         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
852         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
853         *(UINT32*)&lpPos->ptIconPos = *(UINT32*)&lpPos->ptMaxPos = 0xFFFFFFFF;
854     }
855
856     if( wnd->dwStyle & WS_MINIMIZE ) 
857         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
858     else if( wnd->dwStyle & WS_MAXIMIZE ) 
859         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
860     else if( restoreRect ) 
861         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
862
863     return lpPos;
864 }
865
866 /***********************************************************************
867  *           WINPOS_RedrawIconTitle
868  */
869 BOOL32 WINPOS_RedrawIconTitle( HWND32 hWnd )
870 {
871     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( hWnd, atomInternalPos );
872     if( lpPos )
873     {
874         if( lpPos->hwndIconTitle )
875         {
876             SendMessage32A( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
877             InvalidateRect32( lpPos->hwndIconTitle, NULL, TRUE );
878             return TRUE;
879         }
880     }
881     return FALSE;
882 }
883
884 /***********************************************************************
885  *           WINPOS_ShowIconTitle
886  */
887 BOOL32 WINPOS_ShowIconTitle( WND* pWnd, BOOL32 bShow )
888 {
889     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( pWnd->hwndSelf, atomInternalPos );
890
891     if( lpPos && !(pWnd->flags & WIN_MANAGED))
892     {
893         HWND16 hWnd = lpPos->hwndIconTitle;
894
895         TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
896
897         if( !hWnd )
898             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
899         if( bShow )
900         {
901             pWnd = WIN_FindWndPtr(hWnd);
902
903             if( !(pWnd->dwStyle & WS_VISIBLE) )
904             {
905                 SendMessage32A( hWnd, WM_SHOWWINDOW, TRUE, 0 );
906                 SetWindowPos32( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
907                                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
908             }
909         }
910         else ShowWindow32( hWnd, SW_HIDE );
911     }
912     return FALSE;
913 }
914
915 /*******************************************************************
916  *           WINPOS_GetMinMaxInfo
917  *
918  * Get the minimized and maximized information for a window.
919  */
920 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT32 *maxSize, POINT32 *maxPos,
921                            POINT32 *minTrack, POINT32 *maxTrack )
922 {
923     LPINTERNALPOS lpPos;
924     MINMAXINFO32 MinMax;
925     INT32 xinc, yinc;
926
927     /* Compute default values */
928
929     MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
930     MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
931     MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
932     MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
933     MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
934     MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
935
936     if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
937     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
938     {
939         xinc = SYSMETRICS_CXDLGFRAME;
940         yinc = SYSMETRICS_CYDLGFRAME;
941     }
942     else
943     {
944         xinc = yinc = 0;
945         if (HAS_THICKFRAME(wndPtr->dwStyle))
946         {
947             xinc += SYSMETRICS_CXFRAME;
948             yinc += SYSMETRICS_CYFRAME;
949         }
950         if (wndPtr->dwStyle & WS_BORDER)
951         {
952             xinc += SYSMETRICS_CXBORDER;
953             yinc += SYSMETRICS_CYBORDER;
954         }
955     }
956     MinMax.ptMaxSize.x += 2 * xinc;
957     MinMax.ptMaxSize.y += 2 * yinc;
958
959     lpPos = (LPINTERNALPOS)GetProp32A( wndPtr->hwndSelf, atomInternalPos );
960     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
961         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
962     else
963     {
964         MinMax.ptMaxPosition.x = -xinc;
965         MinMax.ptMaxPosition.y = -yinc;
966     }
967
968     SendMessage32A( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
969
970       /* Some sanity checks */
971
972     TRACE(win,"%d %d / %d %d / %d %d / %d %d\n",
973                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
974                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
975                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
976                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
977     MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
978                                    MinMax.ptMinTrackSize.x );
979     MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
980                                    MinMax.ptMinTrackSize.y );
981
982     if (maxSize) *maxSize = MinMax.ptMaxSize;
983     if (maxPos) *maxPos = MinMax.ptMaxPosition;
984     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
985     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
986 }
987
988 /***********************************************************************
989  *           WINPOS_MinMaximize
990  *
991  * Fill in lpRect and return additional flags to be used with SetWindowPos().
992  * This function assumes that 'cmd' is different from the current window
993  * state.
994  */
995 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
996 {
997     UINT16 swpFlags = 0;
998     POINT32 pt;
999     POINT32 size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1000     LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1001                                                   &wndPtr->rectWindow );
1002
1003     TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1004
1005     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1006     {
1007         if( wndPtr->dwStyle & WS_MINIMIZE )
1008         {
1009             if( !SendMessage32A( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1010                 return (SWP_NOSIZE | SWP_NOMOVE);
1011             swpFlags |= SWP_NOCOPYBITS;
1012         }
1013         switch( cmd )
1014         {
1015             case SW_MINIMIZE:
1016                  if( wndPtr->dwStyle & WS_MAXIMIZE)
1017                  {
1018                      wndPtr->flags |= WIN_RESTORE_MAX;
1019                      wndPtr->dwStyle &= ~WS_MAXIMIZE;
1020                  }
1021                  else
1022                      wndPtr->flags &= ~WIN_RESTORE_MAX;
1023                  wndPtr->dwStyle |= WS_MINIMIZE;
1024
1025                  lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1026
1027                  SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1028                                     SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1029                  swpFlags |= SWP_NOCOPYBITS;
1030                  break;
1031
1032             case SW_MAXIMIZE:
1033                 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1034                 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1035                 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1036
1037                  if( wndPtr->dwStyle & WS_MINIMIZE )
1038                  {
1039                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1040                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1041                  }
1042                  wndPtr->dwStyle |= WS_MAXIMIZE;
1043
1044                  SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1045                                     size.x, size.y );
1046                  break;
1047
1048             case SW_RESTORE:
1049                  if( wndPtr->dwStyle & WS_MINIMIZE )
1050                  {
1051                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1052                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1053                      if( wndPtr->flags & WIN_RESTORE_MAX)
1054                      {
1055                          /* Restore to maximized position */
1056                          CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1057                          WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1058                          CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1059                          wndPtr->dwStyle |= WS_MAXIMIZE;
1060                          SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1061                          break;
1062                      }
1063                  } 
1064                  else 
1065                      if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1066                      else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1067
1068                  /* Restore to normal position */
1069
1070                 *lpRect = lpPos->rectNormal; 
1071                  lpRect->right -= lpRect->left; 
1072                  lpRect->bottom -= lpRect->top;
1073
1074                  break;
1075         }
1076     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1077     return swpFlags;
1078 }
1079
1080 /***********************************************************************
1081  *           ShowWindowAsync32   (USER32.535)
1082  *
1083  * doesn't wait; returns immediately.
1084  * used by threads to toggle windows in other (possibly hanging) threads
1085  */
1086 BOOL32 WINAPI ShowWindowAsync32( HWND32 hwnd, INT32 cmd )
1087 {
1088     /* FIXME: does ShowWindow32() return immediately ? */
1089     return ShowWindow32(hwnd, cmd);
1090 }
1091
1092
1093 /***********************************************************************
1094  *           ShowWindow16   (USER.42)
1095  */
1096 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1097 {    
1098     return ShowWindow32(hwnd,cmd);
1099 }
1100
1101
1102 /***********************************************************************
1103  *           ShowWindow32   (USER32.534)
1104  */
1105 BOOL32 WINAPI ShowWindow32( HWND32 hwnd, INT32 cmd ) 
1106 {    
1107     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1108     BOOL32      wasVisible, showFlag;
1109     RECT16      newPos = {0, 0, 0, 0};
1110     int         swp = 0;
1111
1112     if (!wndPtr) return FALSE;
1113
1114     TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1115
1116     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1117
1118     switch(cmd)
1119     {
1120         case SW_HIDE:
1121             if (!wasVisible) return FALSE;
1122             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
1123                         SWP_NOACTIVATE | SWP_NOZORDER;
1124             break;
1125
1126         case SW_SHOWMINNOACTIVE:
1127             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1128             /* fall through */
1129         case SW_SHOWMINIMIZED:
1130             swp |= SWP_SHOWWINDOW;
1131             /* fall through */
1132         case SW_MINIMIZE:
1133             swp |= SWP_FRAMECHANGED;
1134             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1135                  swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1136             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1137             break;
1138
1139         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1140             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1141             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1142                  swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1143             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1144             break;
1145
1146         case SW_SHOWNA:
1147             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1148             /* fall through */
1149         case SW_SHOW:
1150             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1151             break;
1152
1153         case SW_SHOWNOACTIVATE:
1154             swp |= SWP_NOZORDER;
1155             if (GetActiveWindow32()) swp |= SWP_NOACTIVATE;
1156             /* fall through */
1157         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1158         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1159         case SW_RESTORE:
1160             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1161
1162             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1163                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1164             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1165             break;
1166     }
1167
1168     showFlag = (cmd != SW_HIDE);
1169     if (showFlag != wasVisible)
1170     {
1171         SendMessage32A( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1172         if (!IsWindow32( hwnd )) return wasVisible;
1173     }
1174
1175     if ((wndPtr->dwStyle & WS_CHILD) &&
1176         !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
1177         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1178     {
1179         /* Don't call SetWindowPos32() on invisible child windows */
1180         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1181         else wndPtr->dwStyle |= WS_VISIBLE;
1182     }
1183     else
1184     {
1185         /* We can't activate a child window */
1186         if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1187         SetWindowPos32( hwnd, HWND_TOP, 
1188                         newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1189         if (!IsWindow32( hwnd )) return wasVisible;
1190         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1191     }
1192
1193     if (wndPtr->flags & WIN_NEED_SIZE)
1194     {
1195         /* should happen only in CreateWindowEx() */
1196         int wParam = SIZE_RESTORED;
1197
1198         wndPtr->flags &= ~WIN_NEED_SIZE;
1199         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1200         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1201         SendMessage32A( hwnd, WM_SIZE, wParam,
1202                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1203                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1204         SendMessage32A( hwnd, WM_MOVE, 0,
1205                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1206     }
1207
1208     return wasVisible;
1209 }
1210
1211
1212 /***********************************************************************
1213  *           GetInternalWindowPos16   (USER.460)
1214  */
1215 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1216                                       LPPOINT16 ptIcon )
1217 {
1218     WINDOWPLACEMENT16 wndpl;
1219     if (GetWindowPlacement16( hwnd, &wndpl )) 
1220     {
1221         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1222         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1223         return wndpl.showCmd;
1224     }
1225     return 0;
1226 }
1227
1228
1229 /***********************************************************************
1230  *           GetInternalWindowPos32   (USER32.245)
1231  */
1232 UINT32 WINAPI GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd,
1233                                       LPPOINT32 ptIcon )
1234 {
1235     WINDOWPLACEMENT32 wndpl;
1236     if (GetWindowPlacement32( hwnd, &wndpl ))
1237     {
1238         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1239         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1240         return wndpl.showCmd;
1241     }
1242     return 0;
1243 }
1244
1245 /***********************************************************************
1246  *           GetWindowPlacement16   (USER.370)
1247  */
1248 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1249 {
1250     WND *pWnd = WIN_FindWndPtr( hwnd );
1251     if( pWnd )
1252     {
1253         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1254                              *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1255         wndpl->length  = sizeof(*wndpl);
1256         if( pWnd->dwStyle & WS_MINIMIZE )
1257             wndpl->showCmd = SW_SHOWMINIMIZED;
1258         else 
1259             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1260                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1261         if( pWnd->flags & WIN_RESTORE_MAX )
1262             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1263         else
1264             wndpl->flags = 0;
1265         wndpl->ptMinPosition = lpPos->ptIconPos;
1266         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1267         wndpl->rcNormalPosition = lpPos->rectNormal;
1268         return TRUE;
1269     }
1270     return FALSE;
1271 }
1272
1273
1274 /***********************************************************************
1275  *           GetWindowPlacement32   (USER32.307)
1276  *
1277  * Win95:
1278  * Fails if wndpl->length of Win95 (!) apps is invalid.
1279  */
1280 BOOL32 WINAPI GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *pwpl32 )
1281 {
1282     if( pwpl32 )
1283     {
1284         WINDOWPLACEMENT16 wpl;
1285         wpl.length = sizeof(wpl);
1286         if( GetWindowPlacement16( hwnd, &wpl ) )
1287         {
1288             pwpl32->length = sizeof(*pwpl32);
1289             pwpl32->flags = wpl.flags;
1290             pwpl32->showCmd = wpl.showCmd;
1291             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1292             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1293             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1294             return TRUE;
1295         }
1296     }
1297     return FALSE;
1298 }
1299
1300
1301 /***********************************************************************
1302  *           WINPOS_SetPlacement
1303  */
1304 static BOOL32 WINPOS_SetPlacement( HWND32 hwnd, const WINDOWPLACEMENT16 *wndpl,
1305                                                 UINT32 flags )
1306 {
1307     WND *pWnd = WIN_FindWndPtr( hwnd );
1308     if( pWnd )
1309     {
1310         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1311                              *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1312
1313         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1314         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1315         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1316
1317         if( pWnd->dwStyle & WS_MINIMIZE )
1318         {
1319             WINPOS_ShowIconTitle( pWnd, FALSE );
1320             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1321                 SetWindowPos32( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1322                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1323         } 
1324         else if( pWnd->dwStyle & WS_MAXIMIZE )
1325         {
1326             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1327                 SetWindowPos32( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1328                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1329         }
1330         else if( flags & PLACE_RECT )
1331                 SetWindowPos32( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1332                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1333                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1334                                 SWP_NOZORDER | SWP_NOACTIVATE );
1335
1336         ShowWindow32( hwnd, wndpl->showCmd );
1337         if( IsWindow32(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1338         {
1339             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1340
1341             /* SDK: ...valid only the next time... */
1342             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1343         }
1344         return TRUE;
1345     }
1346     return FALSE;
1347 }
1348
1349
1350 /***********************************************************************
1351  *           SetWindowPlacement16   (USER.371)
1352  */
1353 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1354 {
1355     return WINPOS_SetPlacement( hwnd, wndpl,
1356                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1357 }
1358
1359 /***********************************************************************
1360  *           SetWindowPlacement32   (USER32.519)
1361  *
1362  * Win95:
1363  * Fails if wndpl->length of Win95 (!) apps is invalid.
1364  */
1365 BOOL32 WINAPI SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *pwpl32 )
1366 {
1367     if( pwpl32 )
1368     {
1369         WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16), 
1370                 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1371                 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1372                 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1373                 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1374                 pwpl32->rcNormalPosition.bottom } };
1375
1376         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1377     }
1378     return FALSE;
1379 }
1380
1381
1382 /***********************************************************************
1383  *           SetInternalWindowPos16   (USER.461)
1384  */
1385 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1386                                     LPRECT16 rect, LPPOINT16 pt )
1387 {
1388     if( IsWindow16(hwnd) )
1389     {
1390         WINDOWPLACEMENT16 wndpl;
1391         UINT32 flags;
1392
1393         wndpl.length  = sizeof(wndpl);
1394         wndpl.showCmd = showCmd;
1395         wndpl.flags = flags = 0;
1396
1397         if( pt )
1398         {
1399             flags |= PLACE_MIN;
1400             wndpl.flags |= WPF_SETMINPOSITION;
1401             wndpl.ptMinPosition = *pt;
1402         }
1403         if( rect )
1404         {
1405             flags |= PLACE_RECT;
1406             wndpl.rcNormalPosition = *rect;
1407         }
1408         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1409     }
1410 }
1411
1412
1413 /***********************************************************************
1414  *           SetInternalWindowPos32   (USER32.483)
1415  */
1416 void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
1417                                     LPRECT32 rect, LPPOINT32 pt )
1418 {
1419     if( IsWindow32(hwnd) )
1420     {
1421         WINDOWPLACEMENT16 wndpl;
1422         UINT32 flags;
1423
1424         wndpl.length  = sizeof(wndpl);
1425         wndpl.showCmd = showCmd;
1426         wndpl.flags = flags = 0;
1427
1428         if( pt )
1429         {
1430             flags |= PLACE_MIN;
1431             wndpl.flags |= WPF_SETMINPOSITION;
1432             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1433         }
1434         if( rect )
1435         {
1436             flags |= PLACE_RECT;
1437             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1438         }
1439         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1440     }
1441 }
1442
1443 /*******************************************************************
1444  *         WINPOS_SetActiveWindow
1445  *
1446  * SetActiveWindow() back-end. This is the only function that
1447  * can assign active status to a window. It must be called only
1448  * for the top level windows.
1449  */
1450 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
1451 {
1452     CBTACTIVATESTRUCT16* cbtStruct;
1453     WND*     wndPtr, *wndTemp;
1454     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1455     WORD     wIconized = 0;
1456
1457     /* paranoid checks */
1458     if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
1459
1460 /*  if (wndPtr && (GetFastQueue() != wndPtr->hmemTaskQ))
1461  *      return 0;
1462  */
1463     wndPtr = WIN_FindWndPtr(hWnd);
1464     hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
1465
1466     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1467         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1468     else
1469         TRACE(win,"no current active window.\n");
1470
1471     /* call CBT hook chain */
1472     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1473     {
1474         LRESULT wRet;
1475         cbtStruct->fMouse     = fMouse;
1476         cbtStruct->hWndActive = hwndActive;
1477         wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1478                                  (LPARAM)SEGPTR_GET(cbtStruct) );
1479         SEGPTR_FREE(cbtStruct);
1480         if (wRet) return wRet;
1481     }
1482
1483     /* set prev active wnd to current active wnd and send notification */
1484     if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
1485     {
1486         if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1487         {
1488             if (GetSysModalWindow16() != hWnd) return 0;
1489             /* disregard refusal if hWnd is sysmodal */
1490         }
1491
1492 #if 1
1493         SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1494                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1495                         (LPARAM)hWnd );
1496 #else
1497         /* FIXME: must be SendMessage16() because 32A doesn't do
1498          * intertask at this time */
1499         SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1500                                 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1501 #endif
1502
1503         /* check if something happened during message processing */
1504         if( hwndPrevActive != hwndActive ) return 0;
1505     }
1506
1507     /* set active wnd */
1508     hwndActive = hWnd;
1509
1510     /* send palette messages */
1511     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1512         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1513
1514     /* if prev wnd is minimized redraw icon title */
1515     if( IsIconic32( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1516
1517     /* managed windows will get ConfigureNotify event */  
1518     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1519     {
1520         /* check Z-order and bring hWnd to the top */
1521         for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1522             if (wndTemp->dwStyle & WS_VISIBLE) break;
1523
1524         if( wndTemp != wndPtr )
1525             SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0, 
1526                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1527         if (!IsWindow32(hWnd)) return 0;
1528     }
1529
1530     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1531
1532     /* send WM_ACTIVATEAPP if necessary */
1533     if (hOldActiveQueue != hNewActiveQueue)
1534     {
1535         WND **list, **ppWnd;
1536
1537         if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1538         {
1539             for (ppWnd = list; *ppWnd; ppWnd++)
1540             {
1541                 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1542
1543                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1544                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1545                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1546             }
1547             HeapFree( SystemHeap, 0, list );
1548         }
1549
1550         pActiveQueue = (hNewActiveQueue)
1551                        ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1552
1553         if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1554         {
1555             for (ppWnd = list; *ppWnd; ppWnd++)
1556             {
1557                 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1558
1559                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1560                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1561                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1562             }
1563             HeapFree( SystemHeap, 0, list );
1564         }
1565         if (!IsWindow32(hWnd)) return 0;
1566     }
1567
1568     if (hWnd)
1569     {
1570         /* walk up to the first unowned window */
1571         wndTemp = wndPtr;
1572         while (wndTemp->owner) wndTemp = wndTemp->owner;
1573         /* and set last active owned popup */
1574         wndTemp->hwndLastActive = hWnd;
1575
1576         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1577         SendMessage32A( hWnd, WM_NCACTIVATE, TRUE, 0 );
1578 #if 1
1579         SendMessage32A( hWnd, WM_ACTIVATE,
1580                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1581                  (LPARAM)hwndPrevActive );
1582 #else
1583         SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1584                       MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1585 #endif
1586
1587         if( !IsWindow32(hWnd) ) return 0;
1588     }
1589
1590     /* change focus if possible */
1591     if( fChangeFocus && GetFocus32() )
1592         if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1593             FOCUS_SwitchFocus( GetFocus32(),
1594                                (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1595                                0:
1596                                hwndActive
1597             );
1598
1599     if( !hwndPrevActive && wndPtr )
1600         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1601
1602     /* if active wnd is minimized redraw icon title */
1603     if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1604
1605     return (hWnd == hwndActive);
1606 }
1607
1608 /*******************************************************************
1609  *         WINPOS_ActivateOtherWindow
1610  *
1611  *  Activates window other than pWnd.
1612  */
1613 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1614 {
1615   BOOL32        bRet = 0;
1616   WND*          pWndTo = NULL;
1617
1618   if( pWnd->hwndSelf == hwndPrevActive )
1619       hwndPrevActive = 0;
1620
1621   if( hwndActive != pWnd->hwndSelf && 
1622     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1623       return 0;
1624
1625   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1626       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1627   {
1628       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1629
1630       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1631
1632       while( !WINPOS_CanActivate(pWndTo) ) 
1633       {
1634          /* by now owned windows should've been taken care of */
1635
1636           pWndTo = pWndPtr->next;
1637           pWndPtr = pWndTo;
1638           if( !pWndTo ) break;
1639       }
1640   }
1641
1642   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1643
1644   /* switch desktop queue to current active */
1645   if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1646
1647   hwndPrevActive = 0;
1648   return bRet;  
1649 }
1650
1651 /*******************************************************************
1652  *         WINPOS_ChangeActiveWindow
1653  *
1654  */
1655 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1656 {
1657     WND *wndPtr = WIN_FindWndPtr(hWnd);
1658
1659     if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1660
1661     if( !wndPtr ) return FALSE;
1662
1663     /* child windows get WM_CHILDACTIVATE message */
1664     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1665         return SendMessage32A(hWnd, WM_CHILDACTIVATE, 0, 0L);
1666
1667         /* owned popups imply owner activation - not sure */
1668     if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1669         (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
1670         !(wndPtr->owner->dwStyle & WS_DISABLED ))
1671     {
1672         if (!(wndPtr = wndPtr->owner)) return FALSE;
1673         hWnd = wndPtr->hwndSelf;
1674     }
1675
1676     if( hWnd == hwndActive ) return FALSE;
1677
1678     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1679         return FALSE;
1680
1681     /* switch desktop queue to current active */
1682     if( wndPtr->parent == WIN_GetDesktop())
1683         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1684
1685     return TRUE;
1686 }
1687
1688
1689 /***********************************************************************
1690  *           WINPOS_SendNCCalcSize
1691  *
1692  * Send a WM_NCCALCSIZE message to a window.
1693  * All parameters are read-only except newClientRect.
1694  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1695  * when calcValidRect is TRUE.
1696  */
1697 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1698                             RECT32 *newWindowRect, RECT32 *oldWindowRect,
1699                             RECT32 *oldClientRect, WINDOWPOS32 *winpos,
1700                             RECT32 *newClientRect )
1701 {
1702     NCCALCSIZE_PARAMS32 params;
1703     WINDOWPOS32 winposCopy;
1704     LONG result;
1705
1706     params.rgrc[0] = *newWindowRect;
1707     if (calcValidRect)
1708     {
1709         winposCopy = *winpos;
1710         params.rgrc[1] = *oldWindowRect;
1711         params.rgrc[2] = *oldClientRect;
1712         params.lppos = &winposCopy;
1713     }
1714     result = SendMessage32A( hwnd, WM_NCCALCSIZE, calcValidRect,
1715                              (LPARAM)&params );
1716     TRACE(win, "%d,%d-%d,%d\n",
1717                  params.rgrc[0].left, params.rgrc[0].top,
1718                  params.rgrc[0].right, params.rgrc[0].bottom );
1719     *newClientRect = params.rgrc[0];
1720     return result;
1721 }
1722
1723
1724 /***********************************************************************
1725  *           WINPOS_HandleWindowPosChanging16
1726  *
1727  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1728  */
1729 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1730 {
1731     POINT32 maxSize, minTrack;
1732     if (winpos->flags & SWP_NOSIZE) return 0;
1733     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1734         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1735     {
1736         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1737         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1738         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1739         if (!(wndPtr->dwStyle & WS_MINIMIZE))
1740         {
1741             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1742             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1743         }
1744     }
1745     return 0;
1746 }
1747
1748
1749 /***********************************************************************
1750  *           WINPOS_HandleWindowPosChanging32
1751  *
1752  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1753  */
1754 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1755 {
1756     POINT32 maxSize;
1757     if (winpos->flags & SWP_NOSIZE) return 0;
1758     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1759         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1760     {
1761         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1762         winpos->cx = MIN( winpos->cx, maxSize.x );
1763         winpos->cy = MIN( winpos->cy, maxSize.y );
1764     }
1765     return 0;
1766 }
1767
1768
1769 /***********************************************************************
1770  *           WINPOS_MoveWindowZOrder
1771  *
1772  * Move a window in Z order, invalidating everything that needs it.
1773  * Only necessary for windows without associated X window.
1774  */
1775 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1776 {
1777     BOOL32 movingUp;
1778     WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1779
1780     /* We have two possible cases:
1781      * - The window is moving up: we have to invalidate all areas
1782      *   of the window that were covered by other windows
1783      * - The window is moving down: we have to invalidate areas
1784      *   of other windows covered by this one.
1785      */
1786
1787     if (hwndAfter == HWND_TOP)
1788     {
1789         movingUp = TRUE;
1790     }
1791     else if (hwndAfter == HWND_BOTTOM)
1792     {
1793         if (!wndPtr->next) return;  /* Already at the bottom */
1794         movingUp = FALSE;
1795     }
1796     else
1797     {
1798         if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1799         if (wndPtr->next == pWndAfter) return;  /* Already placed right */
1800
1801           /* Determine which window we encounter first in Z-order */
1802         pWndCur = wndPtr->parent->child;
1803         while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1804             pWndCur = pWndCur->next;
1805         movingUp = (pWndCur == pWndAfter);
1806     }
1807
1808     if (movingUp)
1809     {
1810         WND *pWndPrevAfter = wndPtr->next;
1811         WIN_UnlinkWindow( hwnd );
1812         WIN_LinkWindow( hwnd, hwndAfter );
1813         pWndCur = wndPtr->next;
1814         while (pWndCur != pWndPrevAfter)
1815         {
1816             RECT32 rect = { pWndCur->rectWindow.left,
1817                             pWndCur->rectWindow.top,
1818                             pWndCur->rectWindow.right,
1819                             pWndCur->rectWindow.bottom };
1820             OffsetRect32( &rect, -wndPtr->rectClient.left,
1821                           -wndPtr->rectClient.top );
1822             PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1823                               RDW_FRAME | RDW_ERASE, 0 );
1824             pWndCur = pWndCur->next;
1825         }
1826     }
1827     else  /* Moving down */
1828     {
1829         pWndCur = wndPtr->next;
1830         WIN_UnlinkWindow( hwnd );
1831         WIN_LinkWindow( hwnd, hwndAfter );
1832         while (pWndCur != wndPtr)
1833         {
1834             RECT32 rect = { pWndCur->rectWindow.left,
1835                             pWndCur->rectWindow.top,
1836                             pWndCur->rectWindow.right,
1837                             pWndCur->rectWindow.bottom };
1838             OffsetRect32( &rect, -pWndCur->rectClient.left,
1839                           -pWndCur->rectClient.top );
1840             PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1841                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1842             pWndCur = pWndCur->next;
1843         }
1844     }
1845 }
1846
1847 /***********************************************************************
1848  *           WINPOS_ReorderOwnedPopups
1849  *
1850  * fix Z order taking into account owned popups -
1851  * basically we need to maintain them above the window that owns them
1852  */
1853 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1854 {
1855  WND*   w = WIN_GetDesktop()->child;
1856
1857   if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1858   {
1859    /* implement "local z-order" between the top and owner window */
1860
1861      HWND32 hwndLocalPrev = HWND_TOP;
1862
1863      if( hwndInsertAfter != HWND_TOP )
1864      {
1865         while( w != wndPtr->owner )
1866         {
1867           if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1868           if( hwndLocalPrev == hwndInsertAfter ) break;
1869           w = w->next;
1870         }
1871         hwndInsertAfter = hwndLocalPrev;
1872      }
1873
1874   }
1875   else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1876
1877   w = WIN_GetDesktop()->child;
1878   while( w )
1879   {
1880     if( w == wndPtr ) break;
1881
1882     if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1883     {
1884       SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1885                      SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1886       hwndInsertAfter = w->hwndSelf;
1887     }
1888     w = w->next;
1889   }
1890
1891   return hwndInsertAfter;
1892 }
1893
1894 /***********************************************************************
1895  *           WINPOS_SizeMoveClean
1896  *
1897  * Make window look nice without excessive repainting
1898  *
1899  * the pain:
1900  *
1901  * visible regions are in window coordinates
1902  * update regions are in window client coordinates
1903  * client and window rectangles are in parent client coordinates
1904  *
1905  * FIXME: Move visible and update regions to the same coordinate system
1906  *       (either parent client or window). This is a lot of work though.
1907  */
1908 static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn,
1909                                     LPRECT32 lpOldWndRect,
1910                                     LPRECT32 lpOldClientRect, UINT32 uFlags )
1911 {
1912  HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1913  HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1914  int  other, my;
1915
1916  TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
1917               Wnd->rectWindow.left, Wnd->rectWindow.top,
1918               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1919               lpOldWndRect->left, lpOldWndRect->top,
1920               lpOldWndRect->right, lpOldWndRect->bottom);
1921  TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1922               Wnd->rectClient.left, Wnd->rectClient.top,
1923               Wnd->rectClient.right, Wnd->rectClient.bottom,
1924               lpOldClientRect->left, lpOldClientRect->top,
1925               lpOldClientRect->right,lpOldClientRect->bottom );
1926
1927  if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1928      (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1929      uFlags |= SMC_DRAWFRAME;
1930
1931  CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1932
1933  if( !(uFlags & SMC_NOCOPY) )
1934    CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
1935
1936  /* map regions to the parent client area */
1937  
1938  OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1939  OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1940
1941  /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1942
1943  other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1944
1945  /* map visible region to the Wnd client area */
1946
1947  OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1948                          Wnd->rectWindow.top - Wnd->rectClient.top );
1949
1950  /* substract previously invalidated region from the Wnd visible region */
1951
1952  my =  (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1953                                              Wnd->hrgnUpdate, RGN_DIFF)
1954                              : COMPLEXREGION;
1955
1956  if( uFlags & SMC_NOCOPY )      /* invalidate Wnd visible region */
1957    {
1958      if (my != NULLREGION)
1959          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1960           RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1961      else if(uFlags & SMC_DRAWFRAME)
1962          Wnd->flags |= WIN_NEEDS_NCPAINT;
1963    }
1964  else                   /* bitblt old client area */
1965    { 
1966      HDC32 hDC;
1967      int   update;
1968      HRGN32 updateRgn;
1969      int   xfrom,yfrom,xto,yto,width,height;
1970
1971      if( uFlags & SMC_DRAWFRAME )
1972        {
1973          /* copy only client area, frame will be redrawn anyway */
1974
1975          xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1976          xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1977          width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1978          updateRgn = CreateRectRgn32( 0, 0, width, height );
1979          CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1980          SetRectRgn32( updateRgn, 0, 0, Wnd->rectClient.right - xto,
1981                        Wnd->rectClient.bottom - yto );
1982        }
1983      else
1984        {
1985          xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1986          xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1987          width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1988          updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1989                                       yto - Wnd->rectClient.top,
1990                                 Wnd->rectWindow.right - Wnd->rectClient.left,
1991                                 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1992        }
1993
1994      CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1995
1996      /* substract new visRgn from target rect to get a region that won't be copied */
1997
1998      update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1999
2000      /* Blt valid bits using parent window DC */
2001
2002      if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
2003        {
2004          
2005          /* compute clipping region in parent client coordinates */
2006
2007          OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
2008          CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
2009
2010          hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
2011                           DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
2012                           DCX_CACHE | DCX_CLIPSIBLINGS);
2013
2014          BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
2015          ReleaseDC32( Wnd->parent->hwndSelf, hDC); 
2016        }
2017
2018      if( update != NULLREGION )
2019          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
2020                          RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2021      else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
2022      DeleteObject32( updateRgn );
2023    }
2024
2025  /* erase uncovered areas */
2026
2027  if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2028       PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2029                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2030  DeleteObject32(dirtyRgn);
2031  DeleteObject32(newVisRgn);
2032  return uFlags;
2033 }
2034
2035 /***********************************************************************
2036  *           SetWindowPos   (USER.232)
2037  */
2038 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2039                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2040 {
2041     return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2042 }
2043
2044 /***********************************************************************
2045  *           SetWindowPos   (USER32.520)
2046  */
2047 BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter,
2048                               INT32 x, INT32 y, INT32 cx, INT32 cy, WORD flags)
2049 {
2050     WINDOWPOS32 winpos;
2051     WND *       wndPtr;
2052     RECT32      newWindowRect, newClientRect, oldWindowRect;
2053     HRGN32      visRgn = 0;
2054     HWND32      tempInsertAfter= 0;
2055     int         result = 0;
2056     UINT32      uFlags = 0;
2057     BOOL32      resync = FALSE;
2058
2059     TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
2060                                                  hwnd, x, y, x+cx, y+cy, flags);  
2061       /* Check window handle */
2062
2063     if (hwnd == GetDesktopWindow32()) return FALSE;
2064     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2065
2066     if(wndPtr->dwStyle & WS_VISIBLE)
2067         flags &= ~SWP_SHOWWINDOW;
2068     else
2069     {
2070         uFlags |= SMC_NOPARENTERASE; 
2071         flags &= ~SWP_HIDEWINDOW;
2072         if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2073     }
2074
2075 /*     Check for windows that may not be resized 
2076        FIXME: this should be done only for Windows 3.0 programs 
2077        if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2078            flags |= SWP_NOSIZE | SWP_NOMOVE;
2079 */
2080       /* Check dimensions */
2081
2082     if (cx <= 0) cx = 1;
2083     if (cy <= 0) cy = 1;
2084
2085       /* Check flags */
2086
2087     if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
2088     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2089         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2090         flags |= SWP_NOSIZE;    /* Already the right size */
2091     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2092         flags |= SWP_NOMOVE;    /* Already the right position */
2093
2094       /* Check hwndInsertAfter */
2095
2096     if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2097     {
2098           /* Ignore TOPMOST flags when activating a window */
2099           /* _and_ moving it in Z order. */
2100         if ((hwndInsertAfter == HWND_TOPMOST) ||
2101             (hwndInsertAfter == HWND_NOTOPMOST))
2102             hwndInsertAfter = HWND_TOP; 
2103     }
2104       /* TOPMOST not supported yet */
2105     if ((hwndInsertAfter == HWND_TOPMOST) ||
2106         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2107
2108       /* hwndInsertAfter must be a sibling of the window */
2109     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2110        {
2111          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2112
2113          if( wndPtr ) {
2114            if( wnd->parent != wndPtr->parent ) return FALSE;
2115            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2116          }
2117        }
2118     else if (!((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2119     {
2120          /* FIXME: the following optimization is no good for "X-ed" windows */
2121        if (hwndInsertAfter == HWND_TOP)
2122            flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2123        else /* HWND_BOTTOM */
2124            flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2125     }
2126
2127       /* Fill the WINDOWPOS structure */
2128
2129     winpos.hwnd = hwnd;
2130     winpos.hwndInsertAfter = hwndInsertAfter;
2131     winpos.x = x;
2132     winpos.y = y;
2133     winpos.cx = cx;
2134     winpos.cy = cy;
2135     winpos.flags = flags;
2136     
2137       /* Send WM_WINDOWPOSCHANGING message */
2138
2139     if (!(winpos.flags & SWP_NOSENDCHANGING))
2140         SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2141
2142       /* Calculate new position and size */
2143
2144     newWindowRect = wndPtr->rectWindow;
2145     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2146                                                     : wndPtr->rectClient;
2147
2148     if (!(winpos.flags & SWP_NOSIZE))
2149     {
2150         newWindowRect.right  = newWindowRect.left + winpos.cx;
2151         newWindowRect.bottom = newWindowRect.top + winpos.cy;
2152     }
2153     if (!(winpos.flags & SWP_NOMOVE))
2154     {
2155         newWindowRect.left    = winpos.x;
2156         newWindowRect.top     = winpos.y;
2157         newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
2158         newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2159
2160         OffsetRect32( &newClientRect, winpos.x - wndPtr->rectWindow.left, 
2161                                       winpos.y - wndPtr->rectWindow.top );
2162     }
2163
2164     winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2165
2166       /* Reposition window in Z order */
2167
2168     if (!(winpos.flags & SWP_NOZORDER))
2169     {
2170         /* reorder owned popups if hwnd is top-level window 
2171          */
2172         if( wndPtr->parent == WIN_GetDesktop() )
2173             hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2174                                                          wndPtr, winpos.flags );
2175
2176         if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2177         {
2178             WIN_UnlinkWindow( winpos.hwnd );
2179             WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2180         }
2181         else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2182     }
2183
2184     if ( !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window && !(winpos.flags & SWP_NOREDRAW) && 
2185         ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED)) 
2186                       != (SWP_NOMOVE | SWP_NOSIZE)) )
2187           visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
2188
2189
2190       /* Send WM_NCCALCSIZE message to get new client area */
2191     if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2192     {
2193          result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2194                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2195                                     &winpos, &newClientRect );
2196
2197          /* FIXME: WVR_ALIGNxxx */
2198
2199          if( newClientRect.left != wndPtr->rectClient.left ||
2200              newClientRect.top != wndPtr->rectClient.top )
2201              winpos.flags &= ~SWP_NOCLIENTMOVE;
2202
2203          if( (newClientRect.right - newClientRect.left !=
2204               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2205              (newClientRect.bottom - newClientRect.top !=
2206               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2207              winpos.flags &= ~SWP_NOCLIENTSIZE;
2208     }
2209     else
2210       if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2211                                     newClientRect.top != wndPtr->rectClient.top) )
2212             winpos.flags &= ~SWP_NOCLIENTMOVE;
2213
2214     /* Update active DCEs 
2215      * TODO: Optimize conditions that trigger DCE update.
2216      */
2217
2218     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2219                                          wndPtr->dwStyle & WS_VISIBLE) || 
2220         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2221     {
2222         RECT32 rect;
2223
2224         UnionRect32(&rect, &newWindowRect, &wndPtr->rectWindow);
2225         DCE_InvalidateDCE(wndPtr, &rect);
2226     }
2227
2228     /* change geometry */
2229
2230     oldWindowRect = wndPtr->rectWindow;
2231
2232     if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2233     {
2234         RECT32 oldClientRect = wndPtr->rectClient;
2235
2236         tempInsertAfter = winpos.hwndInsertAfter;
2237
2238         winpos.hwndInsertAfter = hwndInsertAfter;
2239
2240         /* postpone geometry change */
2241
2242         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2243         {
2244               wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2245               winpos.hwndInsertAfter = tempInsertAfter;
2246         }
2247         else  uFlags |= SMC_SETXPOS;
2248
2249         wndPtr->rectWindow = newWindowRect;
2250         wndPtr->rectClient = newClientRect;
2251
2252         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2253         {
2254           if( (oldClientRect.left - oldWindowRect.left !=
2255                newClientRect.left - newWindowRect.left) ||
2256               (oldClientRect.top - oldWindowRect.top !=
2257                newClientRect.top - newWindowRect.top) ||
2258               (winpos.flags & SWP_NOCOPYBITS) )
2259           {
2260               /* if the client area moved as a result of WM_NCCALCSIZE returning 
2261                * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2262                *
2263                * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS 
2264                */
2265
2266               PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2267                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2268           }
2269           else
2270               if( winpos.flags & SWP_FRAMECHANGED )
2271               {
2272                 WORD wErase = 0;
2273                 RECT32 rect;
2274
2275                 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2276                 {
2277                     rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2278                     rect.left = oldClientRect.right - newClientRect.left;
2279                     rect.right = newClientRect.right - newClientRect.left;
2280                     wErase = 1;
2281                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2282                                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2283                 }
2284                 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2285                 {
2286                     rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2287                     rect.top = oldClientRect.bottom - newClientRect.top;
2288                     rect.bottom = newClientRect.bottom - newClientRect.top;
2289                     wErase = 1;
2290                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2291                                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2292                 }
2293                 if( !wErase ) /* just update the nonclient area */
2294                     wndPtr->flags |= WIN_NEEDS_NCPAINT; 
2295               }
2296         }
2297         uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2298     }
2299     else /* not an X window */
2300     {
2301         RECT32 oldClientRect = wndPtr->rectClient;
2302
2303         wndPtr->rectWindow = newWindowRect;
2304         wndPtr->rectClient = newClientRect;
2305
2306         if( oldClientRect.bottom - oldClientRect.top ==
2307             newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2308
2309         if( oldClientRect.right - oldClientRect.left ==
2310             newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2311
2312         if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2313         {
2314             uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) || 
2315                         (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2316             uFlags |=  (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2317
2318             if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2319                 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
2320                                                               &oldClientRect, uFlags);
2321             else
2322             { 
2323                 /* adjust the frame and do not erase the parent */
2324
2325                 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2326                 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2327             }
2328         }
2329         DeleteObject32(visRgn);
2330     }
2331
2332     if (flags & SWP_SHOWWINDOW)
2333     {
2334         wndPtr->dwStyle |= WS_VISIBLE;
2335         if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2336         {
2337             HWND32 focus, curr;
2338
2339             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2340             if( uFlags & SMC_SETXPOS )
2341             {
2342               winpos.hwndInsertAfter = tempInsertAfter;
2343             }
2344
2345             if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2346
2347             /* If focus was set to an unmapped window, reset X focus now */
2348             focus = curr = GetFocus32();
2349             while (curr) {
2350                 if (curr == hwnd) {
2351                     SetFocus32( 0 );
2352                     SetFocus32( focus );
2353                     break;
2354                 }
2355                 curr = GetParent32(curr);
2356             }
2357         }
2358         else
2359         {
2360             if (!(flags & SWP_NOREDRAW))
2361                 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2362                                 RDW_INVALIDATE | RDW_ALLCHILDREN |
2363                                 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2364         }
2365     }
2366     else if (flags & SWP_HIDEWINDOW)
2367     {
2368         wndPtr->dwStyle &= ~WS_VISIBLE;
2369
2370         if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2371         {
2372             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2373             if( uFlags & SMC_SETXPOS )
2374             {
2375               winpos.hwndInsertAfter = tempInsertAfter;
2376             }
2377         }
2378         else
2379         {
2380             if (!(flags & SWP_NOREDRAW))
2381                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2382                                     0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2383                                        RDW_ERASE | RDW_ERASENOW, 0 );
2384             uFlags |= SMC_NOPARENTERASE;
2385         }
2386
2387         if ((winpos.hwnd == GetFocus32()) ||
2388             IsChild32( winpos.hwnd, GetFocus32()))
2389         {
2390             /* Revert focus to parent */
2391             SetFocus32( GetParent32(winpos.hwnd) );
2392         }
2393         if (hwnd == CARET_GetHwnd()) DestroyCaret32();
2394
2395         if (winpos.hwnd == hwndActive)
2396             WINPOS_ActivateOtherWindow( wndPtr );
2397     }
2398
2399       /* Activate the window */
2400
2401     if (!(flags & SWP_NOACTIVATE))
2402             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2403     
2404       /* Repaint the window */
2405
2406     if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2407         EVENT_Synchronize();  /* Wait for all expose events */
2408
2409     if (!GetCapture32())
2410         EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2411
2412     if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2413         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2414     else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2415         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2416
2417       /* And last, send the WM_WINDOWPOSCHANGED message */
2418
2419     TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2420
2421     if ( resync ||
2422         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2423          !(winpos.flags & SWP_NOSENDCHANGING)) )
2424     {
2425         SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2426         if (resync) EVENT_Synchronize ();
2427     }
2428
2429     return TRUE;
2430 }
2431
2432                                         
2433 /***********************************************************************
2434  *           BeginDeferWindowPos16   (USER.259)
2435  */
2436 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2437 {
2438     return BeginDeferWindowPos32( count );
2439 }
2440
2441
2442 /***********************************************************************
2443  *           BeginDeferWindowPos32   (USER32.9)
2444  */
2445 HDWP32 WINAPI BeginDeferWindowPos32( INT32 count )
2446 {
2447     HDWP32 handle;
2448     DWP *pDWP;
2449
2450     if (count <= 0) return 0;
2451     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2452     if (!handle) return 0;
2453     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2454     pDWP->actualCount    = 0;
2455     pDWP->suggestedCount = count;
2456     pDWP->valid          = TRUE;
2457     pDWP->wMagic         = DWP_MAGIC;
2458     pDWP->hwndParent     = 0;
2459     return handle;
2460 }
2461
2462
2463 /***********************************************************************
2464  *           DeferWindowPos16   (USER.260)
2465  */
2466 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2467                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2468                                 UINT16 flags )
2469 {
2470     return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2471                              x, y, cx, cy, flags );
2472 }
2473
2474
2475 /***********************************************************************
2476  *           DeferWindowPos32   (USER32.128)
2477  */
2478 HDWP32 WINAPI DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2479                                 INT32 x, INT32 y, INT32 cx, INT32 cy,
2480                                 UINT32 flags )
2481 {
2482     DWP *pDWP;
2483     int i;
2484     HDWP32 newhdwp = hdwp;
2485     /* HWND32 parent; */
2486     WND *pWnd;
2487
2488     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2489     if (!pDWP) return 0;
2490     if (hwnd == GetDesktopWindow32()) return 0;
2491
2492     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2493         USER_HEAP_FREE( hdwp );
2494         return 0;
2495     }
2496         
2497 /* Numega Bounds Checker Demo dislikes the following code.
2498    In fact, I've not been able to find any "same parent" requirement in any docu
2499    [AM 980509]
2500  */
2501 #if 0
2502     /* All the windows of a DeferWindowPos() must have the same parent */
2503     parent = pWnd->parent->hwndSelf;
2504     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2505     else if (parent != pDWP->hwndParent)
2506     {
2507         USER_HEAP_FREE( hdwp );
2508         return 0;
2509     }
2510 #endif
2511
2512     for (i = 0; i < pDWP->actualCount; i++)
2513     {
2514         if (pDWP->winPos[i].hwnd == hwnd)
2515         {
2516               /* Merge with the other changes */
2517             if (!(flags & SWP_NOZORDER))
2518             {
2519                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2520             }
2521             if (!(flags & SWP_NOMOVE))
2522             {
2523                 pDWP->winPos[i].x = x;
2524                 pDWP->winPos[i].y = y;
2525             }                
2526             if (!(flags & SWP_NOSIZE))
2527             {
2528                 pDWP->winPos[i].cx = cx;
2529                 pDWP->winPos[i].cy = cy;
2530             }
2531             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2532                                                SWP_NOZORDER | SWP_NOREDRAW |
2533                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
2534                                                SWP_NOOWNERZORDER);
2535             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2536                                               SWP_FRAMECHANGED);
2537             return hdwp;
2538         }
2539     }
2540     if (pDWP->actualCount >= pDWP->suggestedCount)
2541     {
2542         newhdwp = USER_HEAP_REALLOC( hdwp,
2543                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2544         if (!newhdwp) return 0;
2545         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2546         pDWP->suggestedCount++;
2547     }
2548     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2549     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2550     pDWP->winPos[pDWP->actualCount].x = x;
2551     pDWP->winPos[pDWP->actualCount].y = y;
2552     pDWP->winPos[pDWP->actualCount].cx = cx;
2553     pDWP->winPos[pDWP->actualCount].cy = cy;
2554     pDWP->winPos[pDWP->actualCount].flags = flags;
2555     pDWP->actualCount++;
2556     return newhdwp;
2557 }
2558
2559
2560 /***********************************************************************
2561  *           EndDeferWindowPos16   (USER.261)
2562  */
2563 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2564 {
2565     return EndDeferWindowPos32( hdwp );
2566 }
2567
2568
2569 /***********************************************************************
2570  *           EndDeferWindowPos32   (USER32.173)
2571  */
2572 BOOL32 WINAPI EndDeferWindowPos32( HDWP32 hdwp )
2573 {
2574     DWP *pDWP;
2575     WINDOWPOS32 *winpos;
2576     BOOL32 res = TRUE;
2577     int i;
2578
2579     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2580     if (!pDWP) return FALSE;
2581     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2582     {
2583         if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2584                                     winpos->x, winpos->y, winpos->cx,
2585                                     winpos->cy, winpos->flags ))) break;
2586     }
2587     USER_HEAP_FREE( hdwp );
2588     return res;
2589 }
2590
2591
2592 /***********************************************************************
2593  *           TileChildWindows   (USER.199)
2594  */
2595 void WINAPI TileChildWindows( HWND16 parent, WORD action )
2596 {
2597     FIXME(win, "(%04x, %d): stub\n", parent, action);
2598 }
2599
2600 /***********************************************************************
2601  *           CascageChildWindows   (USER.198)
2602  */
2603 void WINAPI CascadeChildWindows( HWND16 parent, WORD action )
2604 {
2605     FIXME(win, "(%04x, %d): stub\n", parent, action);
2606 }
2607 /***********************************************************************
2608  *           GetProgmanWindow                   [USER32.289]
2609  */
2610 HRESULT WINAPI GetProgmanWindow ( )
2611 {       FIXME(win,"stub\n");
2612         return 0;
2613 }
2614 /***********************************************************************
2615  *           GetTaskmanWindow                   [USER32.304]
2616  */
2617 HRESULT WINAPI GetTaskmanWindow ( )
2618 {       FIXME(win,"stub\n");
2619         return 0;
2620 }
2621 /***********************************************************************
2622  *           SetProgmanWindow                   [USER32.522]
2623  */
2624 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2625 {       FIXME(win,"0x%08lx stub\n",x);
2626         return 0;
2627 }
2628 /***********************************************************************
2629  *           SetShellWindowEx                   [USER32.531]
2630  */
2631 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2632 {       FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2633         return 0;
2634 }
2635 /***********************************************************************
2636  *           SetTaskmanWindow                   [USER32.537]
2637  */
2638 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2639 {       FIXME(win,"0x%08lx stub\n",x);
2640         return 0;
2641 }