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