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