Release 960902
[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  SWP_AGG_NOGEOMETRYCHANGE \
28     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
29 #define  SWP_AGG_NOPOSCHANGE \
30     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
31 #define  SWP_AGG_STATUSFLAGS \
32     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
33
34 #define SMC_NOCOPY              0x0001
35 #define SMC_NOPARENTERASE       0x0002
36 #define SMC_DRAWFRAME           0x0004
37 #define SMC_SETXPOS             0x0008
38
39 /* ----- external functions ----- */
40
41 extern void     FOCUS_SwitchFocus( HWND , HWND );
42 extern HRGN     DCE_GetVisRgn( HWND, WORD );
43 extern HWND     CARET_GetHwnd();
44 extern BOOL     DCE_InvalidateDCE(WND*, RECT16* );
45
46 /* ----- internal variables ----- */
47
48 static HWND hwndActive      = 0;  /* Currently active window */
49 static HWND hwndPrevActive  = 0;  /* Previously active window */
50
51 /***********************************************************************
52  *           WINPOS_FindIconPos
53  *
54  * Find a suitable place for an iconic window.
55  * The new position is stored into wndPtr->ptIconPos.
56  */
57 void WINPOS_FindIconPos( HWND hwnd )
58 {
59     RECT16 rectParent;
60     short x, y, xspacing, yspacing;
61     WND * wndPtr = WIN_FindWndPtr( hwnd );
62
63     if (!wndPtr || !wndPtr->parent) return;
64     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
65     if ((wndPtr->ptIconPos.x >= rectParent.left) &&
66         (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
67         (wndPtr->ptIconPos.y >= rectParent.top) &&
68         (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
69         return;  /* The icon already has a suitable position */
70
71     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
72     y = rectParent.bottom;
73     for (;;)
74     {
75         for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
76         {
77               /* Check if another icon already occupies this spot */
78             WND *childPtr = wndPtr->parent->child;
79             while (childPtr)
80             {
81                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
82                 {
83                     if ((childPtr->rectWindow.left < x + xspacing) &&
84                         (childPtr->rectWindow.right >= x) &&
85                         (childPtr->rectWindow.top <= y) &&
86                         (childPtr->rectWindow.bottom > y - yspacing))
87                         break;  /* There's a window in there */
88                 }
89                 childPtr = childPtr->next;
90             }
91             if (!childPtr)
92             {
93                   /* No window was found, so it's OK for us */
94                 wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
95                 wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
96                 return;
97             }
98         }
99         y -= yspacing;
100     }
101 }
102
103
104 /***********************************************************************
105  *           ArrangeIconicWindows   (USER.170)
106  */
107 UINT ArrangeIconicWindows( HWND parent )
108 {
109     RECT16 rectParent;
110     HWND hwndChild;
111     INT x, y, xspacing, yspacing;
112
113     GetClientRect16( parent, &rectParent );
114     x = rectParent.left;
115     y = rectParent.bottom;
116     xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
117     hwndChild = GetWindow( parent, GW_CHILD );
118     while (hwndChild)
119     {
120         if (IsIconic( hwndChild ))
121         {
122             SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
123                           y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
124                           SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
125             if (x <= rectParent.right - xspacing) x += xspacing;
126             else
127             {
128                 x = rectParent.left;
129                 y -= yspacing;
130             }
131         }
132         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
133     }
134     return yspacing;
135 }
136
137
138 /***********************************************************************
139  *           GetWindowRect16   (USER.32)
140  */
141 void GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
142 {
143     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
144     if (!wndPtr) return;
145     
146     *rect = wndPtr->rectWindow;
147     if (wndPtr->dwStyle & WS_CHILD)
148         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
149 }
150
151
152 /***********************************************************************
153  *           GetWindowRect32   (USER.32)
154  */
155 void GetWindowRect32( HWND32 hwnd, LPRECT32 rect ) 
156 {
157     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
158     if (!wndPtr) return;
159     
160     CONV_RECT16TO32( &wndPtr->rectWindow, rect );
161     if (wndPtr->dwStyle & WS_CHILD)
162         MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
163 }
164
165
166 /***********************************************************************
167  *           GetClientRect16   (USER.33)
168  */
169 void GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
170 {
171     WND * wndPtr = WIN_FindWndPtr( hwnd );
172
173     rect->left = rect->top = rect->right = rect->bottom = 0;
174     if (wndPtr) 
175     {
176         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
177         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
178     }
179 }
180
181
182 /***********************************************************************
183  *           GetClientRect32   (USER32.219)
184  */
185 void GetClientRect32( HWND32 hwnd, LPRECT32 rect ) 
186 {
187     WND * wndPtr = WIN_FindWndPtr( hwnd );
188
189     rect->left = rect->top = rect->right = rect->bottom = 0;
190     if (wndPtr) 
191     {
192         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
193         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
194     }
195 }
196
197
198 /*******************************************************************
199  *         ClientToScreen16   (USER.28)
200  */
201 BOOL16 ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
202 {
203     MapWindowPoints16( hwnd, 0, lppnt, 1 );
204     return TRUE;
205 }
206
207
208 /*******************************************************************
209  *         ClientToScreen32   (USER32.51)
210  */
211 BOOL32 ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
212 {
213     MapWindowPoints32( hwnd, 0, lppnt, 1 );
214     return TRUE;
215 }
216
217
218 /*******************************************************************
219  *         ScreenToClient16   (USER.29)
220  */
221 void ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
222 {
223     MapWindowPoints16( 0, hwnd, lppnt, 1 );
224 }
225
226
227 /*******************************************************************
228  *         ScreenToClient32   (USER32.446)
229  */
230 void ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
231 {
232     MapWindowPoints32( 0, hwnd, lppnt, 1 );
233 }
234
235
236 /***********************************************************************
237  *           WINPOS_WindowFromPoint
238  *
239  * Find the window and hittest for a given point.
240  */
241 INT16 WINPOS_WindowFromPoint( POINT16 pt, WND **ppWnd )
242 {
243     WND *wndPtr;
244     INT16 hittest = HTERROR;
245     INT16 x, y;
246
247     *ppWnd = NULL;
248     x = pt.x;
249     y = pt.y;
250     wndPtr = WIN_GetDesktop()->child;
251     for (;;)
252     {
253         while (wndPtr)
254         {
255             /* If point is in window, and window is visible, and it  */
256             /* is enabled (or it's a top-level window), then explore */
257             /* its children. Otherwise, go to the next window.       */
258
259             if ((wndPtr->dwStyle & WS_VISIBLE) &&
260                 (!(wndPtr->dwStyle & WS_DISABLED) ||
261                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
262                 (x >= wndPtr->rectWindow.left) &&
263                 (x < wndPtr->rectWindow.right) &&
264                 (y >= wndPtr->rectWindow.top) &&
265                 (y < wndPtr->rectWindow.bottom))
266             {
267                 *ppWnd = wndPtr;  /* Got a suitable window */
268
269                 /* If window is minimized or disabled, return at once */
270                 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
271                 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
272
273                 /* If point is not in client area, ignore the children */
274                 if ((x < wndPtr->rectClient.left) ||
275                     (x >= wndPtr->rectClient.right) ||
276                     (y < wndPtr->rectClient.top) ||
277                     (y >= wndPtr->rectClient.bottom)) break;
278
279                 x -= wndPtr->rectClient.left;
280                 y -= wndPtr->rectClient.top;
281                 wndPtr = wndPtr->child;
282             }
283             else wndPtr = wndPtr->next;
284         }
285
286         /* If nothing found, return the desktop window */
287         if (!*ppWnd)
288         {
289             *ppWnd = WIN_GetDesktop();
290             return HTCLIENT;
291         }
292
293         /* Send the WM_NCHITTEST message (only if to the same task) */
294         if ((*ppWnd)->hmemTaskQ != GetTaskQueue(0)) return HTCLIENT;
295         hittest = (INT)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 0,
296                                     MAKELONG( pt.x, pt.y ) );
297         if (hittest != HTTRANSPARENT) return hittest;  /* Found the window */
298
299         /* If no children found in last search, make point relative to parent*/
300         if (!wndPtr)
301         {
302             x += (*ppWnd)->rectClient.left;
303             y += (*ppWnd)->rectClient.top;
304         }
305
306         /* Restart the search from the next sibling */
307         wndPtr = (*ppWnd)->next;
308         *ppWnd = (*ppWnd)->parent;
309     }
310 }
311
312
313 /*******************************************************************
314  *         WindowFromPoint16   (USER.30)
315  */
316 HWND16  WindowFromPoint16( POINT16 pt )
317 {
318     WND *pWnd;
319     WINPOS_WindowFromPoint( pt, &pWnd );
320     return pWnd->hwndSelf;
321 }
322
323
324 /*******************************************************************
325  *         WindowFromPoint32   (USER32.581)
326  */
327 HWND32 WindowFromPoint32( POINT32 pt )
328 {
329     WND *pWnd;
330     POINT16 pt16;
331     CONV_POINT32TO16( &pt, &pt16 );
332     WINPOS_WindowFromPoint( pt16, &pWnd );
333     return (HWND32)pWnd->hwndSelf;
334 }
335
336
337 /*******************************************************************
338  *         ChildWindowFromPoint16   (USER.191)
339  */
340 HWND16 ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
341 {
342     /* pt is in the client coordinates */
343
344     WND* wnd = WIN_FindWndPtr(hwndParent);
345     RECT16 rect;
346
347     if( !wnd ) return 0;
348
349     /* get client rect fast */
350     rect.top = rect.left = 0;
351     rect.right = wnd->rectClient.right - wnd->rectClient.left;
352     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
353
354     if (!PtInRect16( &rect, pt )) return 0;
355
356     wnd = wnd->child;
357     while ( wnd )
358     {
359         if (PtInRect16( &wnd->rectWindow, pt )) return wnd->hwndSelf;
360         wnd = wnd->next;
361     }
362     return hwndParent;
363 }
364
365
366 /*******************************************************************
367  *         ChildWindowFromPoint32   (USER32.)
368  */
369 HWND32 ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
370 {
371     POINT16 pt16;
372     CONV_POINT32TO16( &pt, &pt16 );
373     return (HWND32)ChildWindowFromPoint16( hwndParent, pt16 );
374 }
375
376
377 /*******************************************************************
378  *         WINPOS_GetWinOffset
379  *
380  * Calculate the offset between the origin of the two windows. Used
381  * to implement MapWindowPoints.
382  */
383 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
384                                  POINT32 *offset )
385 {
386     WND * wndPtr;
387
388     offset->x = offset->y = 0;
389     if (hwndFrom == hwndTo ) return;
390
391       /* Translate source window origin to screen coords */
392     if (hwndFrom)
393     {
394         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
395         {
396             fprintf(stderr,"MapWindowPoints: bad hwndFrom = %04x\n",hwndFrom);
397             return;
398         }
399         while (wndPtr->parent)
400         {
401             offset->x += wndPtr->rectClient.left;
402             offset->y += wndPtr->rectClient.top;
403             wndPtr = wndPtr->parent;
404         }
405     }
406
407       /* Translate origin to destination window coords */
408     if (hwndTo)
409     {
410         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
411         {
412             fprintf(stderr,"MapWindowPoints: bad hwndTo = %04x\n", hwndTo );
413             return;
414         }
415         while (wndPtr->parent)
416         {
417             offset->x -= wndPtr->rectClient.left;
418             offset->y -= wndPtr->rectClient.top;
419             wndPtr = wndPtr->parent;
420         }    
421     }
422 }
423
424
425 /*******************************************************************
426  *         MapWindowPoints16   (USER.258)
427  */
428 void MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
429                         LPPOINT16 lppt, UINT16 count )
430 {
431     POINT32 offset;
432
433     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
434     while (count--)
435     {
436         lppt->x += offset.x;
437         lppt->y += offset.y;
438         lppt++;
439     }
440 }
441
442
443 /*******************************************************************
444  *         MapWindowPoints32   (USER32.385)
445  */
446 void MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
447                         LPPOINT32 lppt, UINT32 count )
448 {
449     POINT32 offset;
450
451     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
452     while (count--)
453     {
454         lppt->x += offset.x;
455         lppt->y += offset.y;
456         lppt++;
457     }
458 }
459
460
461 /***********************************************************************
462  *           IsIconic   (USER.31)
463  */
464 BOOL IsIconic(HWND hWnd)
465 {
466     WND * wndPtr = WIN_FindWndPtr(hWnd);
467     if (wndPtr == NULL) return FALSE;
468     return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
469 }
470  
471  
472 /***********************************************************************
473  *           IsZoomed   (USER.272)
474  */
475 BOOL IsZoomed(HWND hWnd)
476 {
477     WND * wndPtr = WIN_FindWndPtr(hWnd);
478     if (wndPtr == NULL) return FALSE;
479     return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
480 }
481
482
483 /*******************************************************************
484  *         GetActiveWindow    (USER.60)
485  */
486 HWND GetActiveWindow()
487 {
488     return hwndActive;
489 }
490
491
492 /*******************************************************************
493  *         SetActiveWindow    (USER.59)
494  */
495 HWND SetActiveWindow( HWND hwnd )
496 {
497     HWND prev = hwndActive;
498     WND *wndPtr = WIN_FindWndPtr( hwnd );
499
500     if (!wndPtr || (wndPtr->dwStyle & WS_DISABLED) ||
501         !(wndPtr->dwStyle & WS_VISIBLE)) return 0;
502
503     WINPOS_SetActiveWindow( hwnd, 0, 0 );
504     return prev;
505 }
506
507
508 /***********************************************************************
509  *           BringWindowToTop   (USER.45)
510  */
511 BOOL BringWindowToTop( HWND hwnd )
512 {
513     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
514 }
515
516
517 /***********************************************************************
518  *           MoveWindow   (USER.56)
519  */
520 BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
521 {    
522     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
523     if (!repaint) flags |= SWP_NOREDRAW;
524     dprintf_win(stddeb, "MoveWindow: %04x %d,%d %dx%d %d\n", 
525             hwnd, x, y, cx, cy, repaint );
526     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
527 }
528
529
530 /***********************************************************************
531  *           ShowWindow   (USER.42)
532  */
533 BOOL ShowWindow( HWND hwnd, int cmd ) 
534 {    
535     WND * wndPtr = WIN_FindWndPtr( hwnd );
536     BOOL32 wasVisible, showFlag;
537     POINT16 maxSize;
538     int swpflags = 0;
539     short x = 0, y = 0, cx = 0, cy = 0;
540
541     if (!wndPtr) return FALSE;
542
543     dprintf_win(stddeb,"ShowWindow: hwnd=%04x, cmd=%d\n", hwnd, cmd);
544
545     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
546
547     switch(cmd)
548     {
549         case SW_HIDE:
550             if (!wasVisible) return FALSE;
551             swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
552                         SWP_NOACTIVATE | SWP_NOZORDER;
553             break;
554
555         case SW_SHOWMINNOACTIVE:
556             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
557             /* fall through */
558         case SW_SHOWMINIMIZED:
559             swpflags |= SWP_SHOWWINDOW;
560             /* fall through */
561         case SW_MINIMIZE:
562             swpflags |= SWP_FRAMECHANGED;
563             if (!(wndPtr->dwStyle & WS_MINIMIZE))
564             {
565                 if (wndPtr->dwStyle & WS_MAXIMIZE)
566                 {
567                     wndPtr->flags |= WIN_RESTORE_MAX;
568                     wndPtr->dwStyle &= ~WS_MAXIMIZE;
569                 }
570                 else
571                 {
572                     wndPtr->flags &= ~WIN_RESTORE_MAX;
573                     wndPtr->rectNormal = wndPtr->rectWindow;
574                 }
575                 wndPtr->dwStyle |= WS_MINIMIZE;
576                 WINPOS_FindIconPos( hwnd );
577                 x  = wndPtr->ptIconPos.x;
578                 y  = wndPtr->ptIconPos.y;
579                 cx = SYSMETRICS_CXICON;
580                 cy = SYSMETRICS_CYICON;
581                 swpflags |= SWP_NOCOPYBITS;
582             }
583             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
584             break;
585
586         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
587             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
588             if (!(wndPtr->dwStyle & WS_MAXIMIZE))
589             {
590                   /* Store the current position and find the maximized size */
591                 if (!(wndPtr->dwStyle & WS_MINIMIZE))
592                     wndPtr->rectNormal = wndPtr->rectWindow; 
593
594                 NC_GetMinMaxInfo( hwnd, &maxSize,
595                                   &wndPtr->ptMaxPos, NULL, NULL );
596                 x  = wndPtr->ptMaxPos.x;
597                 y  = wndPtr->ptMaxPos.y;
598
599                 if( wndPtr->dwStyle & WS_MINIMIZE )
600                     if( !SendMessage16( hwnd, WM_QUERYOPEN, 0, 0L ) )
601                         {
602                          swpflags |= SWP_NOSIZE | SWP_NOMOVE;
603                          break;
604                         }
605                     else swpflags |= SWP_NOCOPYBITS;
606
607                 cx = maxSize.x;
608                 cy = maxSize.y;
609                 wndPtr->dwStyle &= ~WS_MINIMIZE;
610                 wndPtr->dwStyle |= WS_MAXIMIZE;
611             }
612             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
613             break;
614
615         case SW_SHOWNA:
616             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
617             /* fall through */
618         case SW_SHOW:
619             swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
620             break;
621
622         case SW_SHOWNOACTIVATE:
623             swpflags |= SWP_NOZORDER;
624             if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
625             /* fall through */
626         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
627         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
628         case SW_RESTORE:
629             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
630
631             if (wndPtr->dwStyle & WS_MINIMIZE)
632             {
633                 if( !SendMessage16( hwnd, WM_QUERYOPEN, 0, 0L) )
634                   {
635                     swpflags |= SWP_NOSIZE | SWP_NOMOVE;
636                     break;
637                   }
638                 wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
639                 wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
640                 wndPtr->dwStyle &= ~WS_MINIMIZE;
641                 if (wndPtr->flags & WIN_RESTORE_MAX)
642                 {
643                     /* Restore to maximized position */
644                     NC_GetMinMaxInfo( hwnd, &maxSize, &wndPtr->ptMaxPos,
645                                       NULL, NULL );
646                     x  = wndPtr->ptMaxPos.x;
647                     y  = wndPtr->ptMaxPos.y;
648                     cx = maxSize.x;
649                     cy = maxSize.y;
650                    wndPtr->dwStyle |= WS_MAXIMIZE;
651                 }
652                 else  /* Restore to normal position */
653                 {
654                     x  = wndPtr->rectNormal.left;
655                     y  = wndPtr->rectNormal.top;
656                     cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
657                     cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
658                 }
659                 swpflags |= SWP_NOCOPYBITS;
660             }
661             else if (wndPtr->dwStyle & WS_MAXIMIZE)
662             {
663                 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
664                 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
665                 wndPtr->dwStyle &= ~WS_MAXIMIZE;
666                 x  = wndPtr->rectNormal.left;
667                 y  = wndPtr->rectNormal.top;
668                 cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
669                 cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
670             }
671             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
672             break;
673     }
674
675     showFlag = (cmd != SW_HIDE);
676     if (showFlag != wasVisible)
677     {
678         SendMessage16( hwnd, WM_SHOWWINDOW, showFlag, 0 );
679         if (!IsWindow( hwnd )) return wasVisible;
680     }
681
682     if ((wndPtr->dwStyle & WS_CHILD) &&
683         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
684         (swpflags & SWP_NOSIZE) && (swpflags & SWP_NOMOVE))
685     {
686         /* Don't call SetWindowPos() on invisible child windows */
687         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
688         else wndPtr->dwStyle |= WS_VISIBLE;
689     }
690     else
691     {
692         /* We can't activate a child window */
693         if (wndPtr->dwStyle & WS_CHILD)
694             swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
695         SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
696         if (!IsWindow( hwnd )) return wasVisible;
697     }
698
699     if (wndPtr->flags & WIN_NEED_SIZE)
700     {
701         /* should happen only in CreateWindowEx() */
702         int wParam = SIZE_RESTORED;
703
704         wndPtr->flags &= ~WIN_NEED_SIZE;
705         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
706         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
707         SendMessage16( hwnd, WM_SIZE, wParam,
708                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
709                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
710         SendMessage16( hwnd, WM_MOVE, 0,
711                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
712     }
713
714     if (hwnd == GetFocus())
715     { 
716         SetFocus( (wndPtr->dwStyle & WS_CHILD)? wndPtr->parent->hwndSelf: 0 );
717         if (hwnd == CARET_GetHwnd()) DestroyCaret();
718     }
719
720     return wasVisible;
721 }
722
723
724 /***********************************************************************
725  *           GetInternalWindowPos16   (USER.460)
726  */
727 UINT16 GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd, LPPOINT16 ptIcon)
728 {
729     WINDOWPLACEMENT16 wndpl;
730     if (!GetWindowPlacement16( hwnd, &wndpl )) return 0;
731     if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
732     if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
733     return wndpl.showCmd;
734 }
735
736
737 /***********************************************************************
738  *           GetInternalWindowPos32   (USER32.244)
739  */
740 UINT32 GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd, LPPOINT32 ptIcon)
741 {
742     WINDOWPLACEMENT32 wndpl;
743     if (!GetWindowPlacement32( hwnd, &wndpl )) return 0;
744     if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
745     if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
746     return wndpl.showCmd;
747 }
748
749
750 /***********************************************************************
751  *           SetInternalWindowPos16   (USER.461)
752  */
753 void SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
754                              LPRECT16 rect, LPPOINT16 pt )
755 {
756     WINDOWPLACEMENT16 wndpl;
757     WND *wndPtr = WIN_FindWndPtr( hwnd );
758
759     wndpl.length  = sizeof(wndpl);
760     wndpl.flags   = (pt != NULL) ? WPF_SETMINPOSITION : 0;
761     wndpl.showCmd = showCmd;
762     if (pt) wndpl.ptMinPosition = *pt;
763     wndpl.rcNormalPosition = (rect != NULL) ? *rect : wndPtr->rectNormal;
764     wndpl.ptMaxPosition = wndPtr->ptMaxPos;
765     SetWindowPlacement16( hwnd, &wndpl );
766 }
767
768
769 /***********************************************************************
770  *           SetInternalWindowPos32   (USER32.482)
771  */
772 void SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
773                              LPRECT32 rect, LPPOINT32 pt )
774 {
775     WINDOWPLACEMENT32 wndpl;
776     WND *wndPtr = WIN_FindWndPtr( hwnd );
777
778     wndpl.length  = sizeof(wndpl);
779     wndpl.flags   = (pt != NULL) ? WPF_SETMINPOSITION : 0;
780     wndpl.showCmd = showCmd;
781     if (pt) wndpl.ptMinPosition = *pt;
782     if (rect) wndpl.rcNormalPosition = *rect;
783     else CONV_RECT16TO32( &wndPtr->rectNormal, &wndpl.rcNormalPosition );
784     CONV_POINT16TO32( &wndPtr->ptMaxPos, &wndpl.ptMaxPosition );
785     SetWindowPlacement32( hwnd, &wndpl );
786 }
787
788
789 /***********************************************************************
790  *           GetWindowPlacement16   (USER.370)
791  */
792 BOOL16 GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
793 {
794     WND *wndPtr = WIN_FindWndPtr( hwnd );
795     if (!wndPtr) return FALSE;
796
797     wndpl->length  = sizeof(*wndpl);
798     wndpl->flags   = 0;
799     wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED : 
800                      (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
801     wndpl->ptMinPosition = wndPtr->ptIconPos;
802     wndpl->ptMaxPosition = wndPtr->ptMaxPos;
803     wndpl->rcNormalPosition = wndPtr->rectNormal;
804     return TRUE;
805 }
806
807
808 /***********************************************************************
809  *           GetWindowPlacement32   (USER32.306)
810  */
811 BOOL32 GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *wndpl )
812 {
813     WND *wndPtr = WIN_FindWndPtr( hwnd );
814     if (!wndPtr) return FALSE;
815
816     wndpl->length  = sizeof(*wndpl);
817     wndpl->flags   = 0;
818     wndpl->showCmd = IsZoomed(hwnd) ? SW_SHOWMAXIMIZED : 
819                      (IsIconic(hwnd) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL);
820     CONV_POINT16TO32( &wndPtr->ptIconPos, &wndpl->ptMinPosition );
821     CONV_POINT16TO32( &wndPtr->ptMaxPos, &wndpl->ptMaxPosition );
822     CONV_RECT16TO32( &wndPtr->rectNormal, &wndpl->rcNormalPosition );
823     return TRUE;
824 }
825
826
827 /***********************************************************************
828  *           SetWindowPlacement16   (USER.371)
829  */
830 BOOL16 SetWindowPlacement16( HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl )
831 {
832     WND *wndPtr = WIN_FindWndPtr( hwnd );
833     if (!wndPtr) return FALSE;
834
835     if (wndpl->flags & WPF_SETMINPOSITION)
836         wndPtr->ptIconPos = wndpl->ptMinPosition;
837     if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
838         (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
839     wndPtr->ptMaxPos   = wndpl->ptMaxPosition;
840     wndPtr->rectNormal = wndpl->rcNormalPosition;
841     ShowWindow( hwnd, wndpl->showCmd );
842     return TRUE;
843 }
844
845
846 /***********************************************************************
847  *           SetWindowPlacement32   (USER32.518)
848  */
849 BOOL32 SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *wndpl )
850 {
851     WND *wndPtr = WIN_FindWndPtr( hwnd );
852     if (!wndPtr) return FALSE;
853
854     if (wndpl->flags & WPF_SETMINPOSITION)
855         CONV_POINT32TO16( &wndpl->ptMinPosition, &wndPtr->ptIconPos );
856     if ((wndpl->flags & WPF_RESTORETOMAXIMIZED) &&
857         (wndpl->showCmd == SW_SHOWMINIMIZED)) wndPtr->flags |= WIN_RESTORE_MAX;
858     CONV_POINT32TO16( &wndpl->ptMaxPosition, &wndPtr->ptMaxPos );
859     CONV_RECT32TO16( &wndpl->rcNormalPosition, &wndPtr->rectNormal );
860     ShowWindow( hwnd, wndpl->showCmd );
861     return TRUE;
862 }
863
864
865 /*******************************************************************
866  *         WINPOS_SetActiveWindow
867  *
868  * back-end to SetActiveWindow
869  */
870 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus )
871 {
872     WND                   *wndPtr          = WIN_FindWndPtr(hWnd);
873     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
874     CBTACTIVATESTRUCT16   *cbtStruct;
875     WORD                   wIconized=0;
876     HANDLE hNewActiveQueue;
877
878     /* FIXME: When proper support for cooperative multitasking is in place 
879      *        hActiveQ will be global 
880      */
881
882     HANDLE                 hActiveQ = 0;   
883
884     /* paranoid checks */
885     if( hWnd == GetDesktopWindow() || hWnd == hwndActive )
886         return 0;
887
888     if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
889         return 0;
890
891     if( wndTemp )
892         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
893     else
894         dprintf_win(stddeb,"WINPOS_ActivateWindow: no current active window.\n");
895
896     /* call CBT hook chain */
897     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
898     {
899         LRESULT wRet;
900         cbtStruct->fMouse     = fMouse;
901         cbtStruct->hWndActive = hwndActive;
902         wRet = HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd,
903                                (LPARAM)SEGPTR_GET(cbtStruct) );
904         SEGPTR_FREE(cbtStruct);
905         if (wRet) return wRet;
906     }
907
908     /* set prev active wnd to current active wnd and send notification */
909     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
910     {
911         if (!SendMessage16( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
912         {
913             if (GetSysModalWindow16() != hWnd) return 0;
914             /* disregard refusal if hWnd is sysmodal */
915         }
916
917         SendMessage32A( hwndPrevActive, WM_ACTIVATE,
918                         MAKEWPARAM( WA_INACTIVE, wIconized ),
919                         (LPARAM)hWnd );
920
921         /* check if something happened during message processing */
922         if( hwndPrevActive != hwndActive ) return 0;
923     }
924
925     /* set active wnd */
926     hwndActive = hWnd;
927
928     /* send palette messages */
929     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
930         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0L );
931
932     /* if prev wnd is minimized redraw icon title 
933   if( hwndPrevActive )
934     {
935         wndTemp = WIN_FindWndPtr( WIN_GetTopParent( hwndPrevActive ) );
936         if(wndTemp)
937           if(wndTemp->dwStyle & WS_MINIMIZE)
938             RedrawIconTitle(hwndPrevActive); 
939       } 
940   */
941
942     /* managed windows will get ConfigureNotify event */  
943     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
944     {
945         /* check Z-order and bring hWnd to the top */
946         for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
947             if (wndTemp->dwStyle & WS_VISIBLE) break;
948
949         if( wndTemp != wndPtr )
950             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
951                          SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
952         if( !IsWindow(hWnd) ) return 0;
953     }
954
955     if (hwndPrevActive)
956     {
957         wndTemp = WIN_FindWndPtr( hwndPrevActive );
958         if (wndTemp) hActiveQ = wndTemp->hmemTaskQ;
959     }
960     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
961
962     /* send WM_ACTIVATEAPP if necessary */
963     if (hActiveQ != hNewActiveQueue)
964     {
965         WND **list, **ppWnd;
966
967         if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
968         {
969             for (ppWnd = list; *ppWnd; ppWnd++)
970             {
971                 /* Make sure that the window still exists */
972                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
973                 if ((*ppWnd)->hmemTaskQ != hActiveQ) continue;
974                 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
975                                0, QUEUE_GetQueueTask(hNewActiveQueue) );
976             }
977             HeapFree( SystemHeap, 0, list );
978         }
979
980         if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
981         {
982             for (ppWnd = list; *ppWnd; ppWnd++)
983             {
984                 /* Make sure that the window still exists */
985                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
986                 if ((*ppWnd)->hmemTaskQ != hNewActiveQueue) continue;
987                 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
988                                1, QUEUE_GetQueueTask( hActiveQ ) );
989             }
990             HeapFree( SystemHeap, 0, list );
991         }
992         if (!IsWindow(hWnd)) return 0;
993     }
994
995     if (hWnd)
996     {
997         /* walk up to the first unowned window */
998         wndTemp = wndPtr;
999         while (wndTemp->owner) wndTemp = wndTemp->owner;
1000         /* and set last active owned popup */
1001         wndTemp->hwndLastActive = hWnd;
1002
1003         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1004         SendMessage16( hWnd, WM_NCACTIVATE, TRUE, 0 );
1005         SendMessage32A( hWnd, WM_ACTIVATE,
1006                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1007                  (LPARAM)hwndPrevActive );
1008
1009         if( !IsWindow(hWnd) ) return 0;
1010     }
1011
1012     /* change focus if possible */
1013     if( fChangeFocus && GetFocus() )
1014         if( WIN_GetTopParent(GetFocus()) != hwndActive )
1015             FOCUS_SwitchFocus( GetFocus(),
1016                                (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
1017
1018     /* if active wnd is minimized redraw icon title 
1019   if( hwndActive )
1020       {
1021         wndPtr = WIN_FindWndPtr(hwndActive);
1022         if(wndPtr->dwStyle & WS_MINIMIZE)
1023            RedrawIconTitle(hwndActive);
1024     }
1025   */
1026     return (hWnd == hwndActive);
1027 }
1028
1029
1030 /*******************************************************************
1031  *         WINPOS_ChangeActiveWindow
1032  *
1033  */
1034 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1035 {
1036     WND *wndPtr = WIN_FindWndPtr(hWnd);
1037
1038     if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1039
1040     if( !wndPtr ) return FALSE;
1041
1042     /* child windows get WM_CHILDACTIVATE message */
1043     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1044         return SendMessage16(hWnd, WM_CHILDACTIVATE, 0, 0L);
1045
1046         /* owned popups imply owner activation - not sure */
1047     if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1048         !(wndPtr->owner->dwStyle & WS_DISABLED ))
1049     {
1050         if (!(wndPtr = wndPtr->owner)) return FALSE;
1051         hWnd = wndPtr->hwndSelf;
1052     }
1053
1054     if( hWnd == hwndActive ) return FALSE;
1055
1056     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1057         return FALSE;
1058
1059     /* switch desktop queue to current active */
1060     if( wndPtr->parent == WIN_GetDesktop())
1061         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1062
1063     return TRUE;
1064 }
1065
1066
1067 /***********************************************************************
1068  *           WINPOS_SendNCCalcSize
1069  *
1070  * Send a WM_NCCALCSIZE message to a window.
1071  * All parameters are read-only except newClientRect.
1072  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1073  * when calcValidRect is TRUE.
1074  */
1075 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1076                             RECT16 *newWindowRect, RECT16 *oldWindowRect,
1077                             RECT16 *oldClientRect, SEGPTR winpos,
1078                             RECT16 *newClientRect )
1079 {
1080     NCCALCSIZE_PARAMS16 *params;
1081     LONG result;
1082
1083     if (!(params = SEGPTR_NEW(NCCALCSIZE_PARAMS16))) return 0;
1084     params->rgrc[0] = *newWindowRect;
1085     if (calcValidRect)
1086     {
1087         params->rgrc[1] = *oldWindowRect;
1088         params->rgrc[2] = *oldClientRect;
1089         params->lppos = winpos;
1090     }
1091     result = SendMessage16( hwnd, WM_NCCALCSIZE, calcValidRect,
1092                           (LPARAM)SEGPTR_GET( params ) );
1093     dprintf_win(stddeb, "WINPOS_SendNCCalcSize: %d %d %d %d\n",
1094                 (int)params->rgrc[0].top,    (int)params->rgrc[0].left,
1095                 (int)params->rgrc[0].bottom, (int)params->rgrc[0].right);
1096     *newClientRect = params->rgrc[0];
1097     SEGPTR_FREE(params);
1098     return result;
1099 }
1100
1101
1102 /***********************************************************************
1103  *           WINPOS_HandleWindowPosChanging16
1104  *
1105  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1106  */
1107 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1108 {
1109     POINT16 maxSize;
1110     if (winpos->flags & SWP_NOSIZE) return 0;
1111     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1112         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1113     {
1114         NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
1115         winpos->cx = MIN( winpos->cx, maxSize.x );
1116         winpos->cy = MIN( winpos->cy, maxSize.y );
1117     }
1118     return 0;
1119 }
1120
1121
1122 /***********************************************************************
1123  *           WINPOS_HandleWindowPosChanging32
1124  *
1125  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1126  */
1127 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1128 {
1129     POINT16 maxSize;
1130     if (winpos->flags & SWP_NOSIZE) return 0;
1131     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1132         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1133     {
1134         NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
1135         winpos->cx = MIN( winpos->cx, maxSize.x );
1136         winpos->cy = MIN( winpos->cy, maxSize.y );
1137     }
1138     return 0;
1139 }
1140
1141
1142 /***********************************************************************
1143  *           WINPOS_MoveWindowZOrder
1144  *
1145  * Move a window in Z order, invalidating everything that needs it.
1146  * Only necessary for windows without associated X window.
1147  */
1148 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
1149 {
1150     BOOL movingUp;
1151     WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1152
1153     /* We have two possible cases:
1154      * - The window is moving up: we have to invalidate all areas
1155      *   of the window that were covered by other windows
1156      * - The window is moving down: we have to invalidate areas
1157      *   of other windows covered by this one.
1158      */
1159
1160     if (hwndAfter == HWND_TOP)
1161     {
1162         movingUp = TRUE;
1163     }
1164     else if (hwndAfter == HWND_BOTTOM)
1165     {
1166         if (!wndPtr->next) return;  /* Already at the bottom */
1167         movingUp = FALSE;
1168     }
1169     else
1170     {
1171         if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1172         if (wndPtr->next == pWndAfter) return;  /* Already placed right */
1173
1174           /* Determine which window we encounter first in Z-order */
1175         pWndCur = wndPtr->parent->child;
1176         while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1177             pWndCur = pWndCur->next;
1178         movingUp = (pWndCur == pWndAfter);
1179     }
1180
1181     if (movingUp)
1182     {
1183         WND *pWndPrevAfter = wndPtr->next;
1184         WIN_UnlinkWindow( hwnd );
1185         WIN_LinkWindow( hwnd, hwndAfter );
1186         pWndCur = wndPtr->next;
1187         while (pWndCur != pWndPrevAfter)
1188         {
1189             RECT32 rect = { pWndCur->rectWindow.left,
1190                             pWndCur->rectWindow.top,
1191                             pWndCur->rectWindow.right,
1192                             pWndCur->rectWindow.bottom };
1193             OffsetRect32( &rect, -wndPtr->rectClient.left,
1194                           -wndPtr->rectClient.top );
1195             PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1196                               RDW_FRAME | RDW_ERASE, 0 );
1197             pWndCur = pWndCur->next;
1198         }
1199     }
1200     else  /* Moving down */
1201     {
1202         pWndCur = wndPtr->next;
1203         WIN_UnlinkWindow( hwnd );
1204         WIN_LinkWindow( hwnd, hwndAfter );
1205         while (pWndCur != wndPtr)
1206         {
1207             RECT32 rect = { pWndCur->rectWindow.left,
1208                             pWndCur->rectWindow.top,
1209                             pWndCur->rectWindow.right,
1210                             pWndCur->rectWindow.bottom };
1211             OffsetRect32( &rect, -pWndCur->rectClient.left,
1212                           -pWndCur->rectClient.top );
1213             PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1214                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1215             pWndCur = pWndCur->next;
1216         }
1217     }
1218 }
1219
1220 /***********************************************************************
1221  *           WINPOS_ReorderOwnedPopups
1222  *
1223  * fix Z order taking into account owned popups -
1224  * basically we need to maintain them above owner window
1225  */
1226 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter, WND* wndPtr, WORD flags)
1227 {
1228  WND*   w = WIN_GetDesktop();
1229
1230  w = w->child;
1231
1232  /* if we are dealing with owned popup... 
1233   */
1234  if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner && hwndInsertAfter != HWND_TOP )
1235    {
1236      BOOL bFound = FALSE;
1237      HWND hwndLocalPrev = HWND_TOP;
1238      HWND hwndNewAfter = 0;
1239
1240      while( w )
1241        {
1242          if( !bFound && hwndInsertAfter == hwndLocalPrev )
1243              hwndInsertAfter = HWND_TOP;
1244
1245          if( w->dwStyle & WS_POPUP && w->owner == wndPtr->owner )
1246            {
1247              bFound = TRUE;
1248
1249              if( hwndInsertAfter == HWND_TOP )
1250                {
1251                  hwndInsertAfter = hwndLocalPrev;
1252                  break;
1253                }
1254              hwndNewAfter = hwndLocalPrev;
1255            }
1256
1257          if( w == wndPtr->owner )
1258            {
1259              /* basically HWND_BOTTOM */
1260              hwndInsertAfter = hwndLocalPrev;
1261
1262              if( bFound )
1263                  hwndInsertAfter = hwndNewAfter;
1264              break;
1265            }
1266
1267            if( w != wndPtr )
1268                hwndLocalPrev = w->hwndSelf;
1269
1270            w = w->next;
1271         }
1272    }
1273  else 
1274    /* or overlapped top-level window... 
1275     */
1276    if( !(wndPtr->dwStyle & WS_CHILD) )
1277       while( w )
1278         {
1279           if( w == wndPtr ) break;
1280
1281           if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1282             {
1283               SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1284                                         SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1285               hwndInsertAfter = w->hwndSelf;
1286             }
1287           w = w->next;
1288         }
1289
1290   return hwndInsertAfter;
1291 }
1292
1293 /***********************************************************************
1294  *           WINPOS_SizeMoveClean
1295  *
1296  * Make window look nice without excessive repainting
1297  *
1298  * the pain:
1299  *
1300  * visible regions are in window coordinates
1301  * update regions are in window client coordinates
1302  * client and window rectangles are in parent client coordinates
1303  */
1304 static UINT WINPOS_SizeMoveClean(WND* Wnd, HRGN oldVisRgn, LPRECT16 lpOldWndRect, LPRECT16 lpOldClientRect, UINT uFlags )
1305 {
1306  HRGN newVisRgn    = DCE_GetVisRgn(Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS );
1307  HRGN dirtyRgn     = CreateRectRgn(0,0,0,0);
1308  int  other, my;
1309
1310  dprintf_win(stddeb,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
1311 \t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1312                    Wnd->rectWindow.left, Wnd->rectWindow.top, Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1313                    lpOldWndRect->left, lpOldWndRect->top, lpOldWndRect->right, lpOldWndRect->bottom,
1314                    Wnd->rectClient.left,Wnd->rectClient.top,Wnd->rectClient.right,Wnd->rectClient.bottom,
1315                    lpOldClientRect->left,lpOldClientRect->top,lpOldClientRect->right,lpOldClientRect->bottom);
1316
1317  if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1318      (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1319      uFlags |= SMC_DRAWFRAME;
1320
1321  CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
1322
1323  if( !(uFlags & SMC_NOCOPY) )
1324    CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
1325
1326  /* map regions to the parent client area */
1327  
1328  OffsetRgn(dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top);
1329  OffsetRgn(oldVisRgn, lpOldWndRect->left, lpOldWndRect->top);
1330
1331  /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1332
1333  other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1334
1335  /* map visible region to the Wnd client area */
1336
1337  OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1338                        Wnd->rectWindow.top - Wnd->rectClient.top );
1339
1340  /* substract previously invalidated region from the Wnd visible region */
1341
1342  my =  (Wnd->hrgnUpdate > 1)? CombineRgn( newVisRgn, newVisRgn, Wnd->hrgnUpdate, RGN_DIFF)
1343                             : COMPLEXREGION;
1344
1345  if( uFlags & SMC_NOCOPY )      /* invalidate Wnd visible region */
1346    {
1347      if (my != NULLREGION)  PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1348                             RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1349    } 
1350  else                   /* bitblt old client area */
1351    { 
1352      HDC   hDC;
1353      int   update;
1354      HRGN  updateRgn;
1355      int   xfrom,yfrom,xto,yto,width,height;
1356
1357      if( uFlags & SMC_DRAWFRAME )
1358        {
1359          /* copy only client area, frame will be redrawn anyway */
1360
1361          xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1362          xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1363          width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1364          updateRgn = CreateRectRgn( 0, 0, width, height );
1365          CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1366          SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto, Wnd->rectClient.bottom - yto );
1367        }
1368      else
1369        {
1370          xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1371          xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1372          width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1373          updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
1374                                     yto - Wnd->rectClient.top,
1375                                     Wnd->rectWindow.right - Wnd->rectClient.left,
1376                                     Wnd->rectWindow.bottom - Wnd->rectClient.top );
1377        }
1378
1379      CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1380
1381      /* substract new visRgn from target rect to get a region that won't be copied */
1382
1383      update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
1384
1385      /* Blt valid bits using parent window DC */
1386
1387      if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
1388        {
1389          
1390          /* compute clipping region in parent client coordinates */
1391
1392          OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
1393          CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
1394
1395          hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
1396
1397          BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
1398     
1399          ReleaseDC( Wnd->parent->hwndSelf, hDC); 
1400        }
1401
1402      if( update != NULLREGION )
1403          PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
1404                          RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1405      else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
1406      DeleteObject( updateRgn );
1407    }
1408
1409  /* erase uncovered areas */
1410
1411  if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
1412       PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
1413                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1414  DeleteObject(dirtyRgn);
1415  DeleteObject(newVisRgn);
1416  return uFlags;
1417 }
1418
1419
1420 /***********************************************************************
1421  *           WINPOS_ForceXWindowRaise
1422  */
1423 void WINPOS_ForceXWindowRaise( WND* pWnd )
1424 {
1425     XWindowChanges winChanges;
1426     WND *wndStop, *wndLast;
1427
1428     if (!pWnd->window) return;
1429         
1430     wndLast = wndStop = pWnd;
1431     winChanges.stack_mode = Above;
1432     XReconfigureWMWindow( display, pWnd->window, 0, CWStackMode, &winChanges );
1433
1434     /* Recursively raise owned popups according to their z-order 
1435      * (it would be easier with sibling-related Below but it doesn't
1436      * work very well with SGI mwm for instance)
1437      */
1438     while (wndLast)
1439     {
1440         WND *wnd = WIN_GetDesktop()->child;
1441         wndLast = NULL;
1442         while (wnd != wndStop)
1443         {
1444             if (wnd->owner == pWnd &&
1445                 (wnd->dwStyle & WS_POPUP) &&
1446                 (wnd->dwStyle & WS_VISIBLE))
1447                 wndLast = wnd;
1448             wnd = wnd->next;
1449         }
1450         if (wndLast)
1451         {
1452             WINPOS_ForceXWindowRaise( wndLast );
1453             wndStop = wndLast;
1454         }
1455     }
1456 }
1457
1458
1459 /***********************************************************************
1460  *           WINPOS_SetXWindowPos
1461  *
1462  * SetWindowPos() for an X window. Used by the real SetWindowPos().
1463  */
1464 static void WINPOS_SetXWindowPos( WINDOWPOS16 *winpos )
1465 {
1466     XWindowChanges winChanges;
1467     int changeMask = 0;
1468     WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
1469
1470     if (!(winpos->flags & SWP_NOSIZE))
1471     {
1472         winChanges.width     = winpos->cx;
1473         winChanges.height    = winpos->cy;
1474         changeMask |= CWWidth | CWHeight;
1475
1476         /* Tweak dialog window size hints */
1477
1478         if ((wndPtr->flags & WIN_MANAGED) &&
1479             (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
1480         {
1481             XSizeHints *size_hints = XAllocSizeHints();
1482
1483             if (size_hints)
1484             {
1485                 long supplied_return;
1486
1487                 XGetWMSizeHints( display, wndPtr->window, size_hints,
1488                                  &supplied_return, XA_WM_NORMAL_HINTS);
1489                 size_hints->min_width = size_hints->max_width = winpos->cx;
1490                 size_hints->min_height = size_hints->max_height = winpos->cy;
1491                 XSetWMSizeHints( display, wndPtr->window, size_hints,
1492                                  XA_WM_NORMAL_HINTS );
1493                 XFree(size_hints);
1494             }
1495         }
1496     }
1497     if (!(winpos->flags & SWP_NOMOVE))
1498     {
1499         winChanges.x = winpos->x;
1500         winChanges.y = winpos->y;
1501         changeMask |= CWX | CWY;
1502     }
1503     if (!(winpos->flags & SWP_NOZORDER))
1504     {
1505         if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
1506         else winChanges.stack_mode = Below;
1507         if ((winpos->hwndInsertAfter != HWND_TOP) &&
1508             (winpos->hwndInsertAfter != HWND_BOTTOM))
1509         {
1510             WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
1511             winChanges.sibling = insertPtr->window;
1512             changeMask |= CWSibling;
1513         }
1514         changeMask |= CWStackMode;
1515     }
1516     if (!changeMask) return;
1517     if (wndPtr->flags & WIN_MANAGED)
1518         XReconfigureWMWindow( display, wndPtr->window, 0,
1519                               changeMask, &winChanges );
1520     else XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
1521 }
1522
1523
1524 /***********************************************************************
1525  *           SetWindowPos   (USER.232)
1526  */
1527 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
1528                    INT cx, INT cy, WORD flags )
1529 {
1530     WINDOWPOS16 *winpos;
1531     WND *       wndPtr;
1532     RECT16      newWindowRect, newClientRect, oldWindowRect;
1533     HRGN        visRgn = 0;
1534     HWND        tempInsertAfter= 0;
1535     int         result = 0;
1536     UINT        uFlags = 0;
1537
1538     dprintf_win(stddeb,"SetWindowPos: hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
1539                                                  hwnd, x, y, x+cx, y+cy, flags);  
1540       /* Check window handle */
1541
1542     if (hwnd == GetDesktopWindow()) return FALSE;
1543     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1544
1545     if (wndPtr->dwStyle & WS_VISIBLE) flags &= ~SWP_SHOWWINDOW;
1546     else
1547     {
1548         uFlags |= SMC_NOPARENTERASE; 
1549         flags &= ~SWP_HIDEWINDOW;
1550         if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
1551     }
1552
1553 /*     Check for windows that may not be resized 
1554        FIXME: this should be done only for Windows 3.0 programs 
1555        if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
1556            flags |= SWP_NOSIZE | SWP_NOMOVE;
1557 */
1558       /* Check dimensions */
1559
1560     if (cx <= 0) cx = 1;
1561     if (cy <= 0) cy = 1;
1562
1563       /* Check flags */
1564
1565     if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
1566     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
1567         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
1568         flags |= SWP_NOSIZE;    /* Already the right size */
1569     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
1570         flags |= SWP_NOMOVE;    /* Already the right position */
1571
1572       /* Check hwndInsertAfter */
1573
1574     if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
1575     {
1576           /* Ignore TOPMOST flags when activating a window */
1577           /* _and_ moving it in Z order. */
1578         if ((hwndInsertAfter == HWND_TOPMOST) ||
1579             (hwndInsertAfter == HWND_NOTOPMOST))
1580             hwndInsertAfter = HWND_TOP; 
1581     }
1582       /* TOPMOST not supported yet */
1583     if ((hwndInsertAfter == HWND_TOPMOST) ||
1584         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
1585
1586       /* hwndInsertAfter must be a sibling of the window */
1587     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
1588        {
1589          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
1590          if( wnd->parent != wndPtr->parent ) return FALSE;
1591          if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
1592        }
1593     else
1594        if (hwndInsertAfter == HWND_TOP)
1595            flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
1596        else /* HWND_BOTTOM */
1597            flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
1598
1599       /* Fill the WINDOWPOS structure */
1600
1601     if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return FALSE;
1602     winpos->hwnd = hwnd;
1603     winpos->hwndInsertAfter = hwndInsertAfter;
1604     winpos->x = x;
1605     winpos->y = y;
1606     winpos->cx = cx;
1607     winpos->cy = cy;
1608     winpos->flags = flags;
1609     
1610       /* Send WM_WINDOWPOSCHANGING message */
1611
1612     if (!(flags & SWP_NOSENDCHANGING))
1613         SendMessage16( hwnd, WM_WINDOWPOSCHANGING, 0,
1614                        (LPARAM)SEGPTR_GET(winpos) );
1615
1616       /* Calculate new position and size */
1617
1618     newWindowRect = wndPtr->rectWindow;
1619     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
1620                                                     : wndPtr->rectClient;
1621
1622     if (!(winpos->flags & SWP_NOSIZE))
1623     {
1624         newWindowRect.right  = newWindowRect.left + winpos->cx;
1625         newWindowRect.bottom = newWindowRect.top + winpos->cy;
1626     }
1627     if (!(winpos->flags & SWP_NOMOVE))
1628     {
1629         newWindowRect.left    = winpos->x;
1630         newWindowRect.top     = winpos->y;
1631         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
1632         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
1633
1634         OffsetRect16( &newClientRect, winpos->x - wndPtr->rectWindow.left, 
1635                                       winpos->y - wndPtr->rectWindow.top );
1636     }
1637
1638     winpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
1639
1640       /* Reposition window in Z order */
1641
1642     if (!(winpos->flags & SWP_NOZORDER))
1643     {
1644         /* reorder owned popups if hwnd is top-level window 
1645          */
1646         if( wndPtr->parent == WIN_GetDesktop() )
1647             hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
1648                                                          wndPtr, flags );
1649
1650         if (wndPtr->window)
1651         {
1652             WIN_UnlinkWindow( winpos->hwnd );
1653             WIN_LinkWindow( winpos->hwnd, hwndInsertAfter );
1654         }
1655         else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndInsertAfter );
1656     }
1657
1658     if ( !wndPtr->window && !(flags & SWP_NOREDRAW) && 
1659         (!(flags & SWP_NOMOVE) || !(flags & SWP_NOSIZE) || (flags & SWP_FRAMECHANGED)) )
1660           visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
1661
1662
1663       /* Send WM_NCCALCSIZE message to get new client area */
1664     if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
1665       {
1666          result = WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
1667                                     &wndPtr->rectWindow, &wndPtr->rectClient,
1668                                     SEGPTR_GET(winpos), &newClientRect );
1669
1670          /* FIXME: WVR_ALIGNxxx */
1671
1672          if( newClientRect.left != wndPtr->rectClient.left ||
1673              newClientRect.top != wndPtr->rectClient.top )
1674              winpos->flags &= ~SWP_NOCLIENTMOVE;
1675
1676          if( (newClientRect.right - newClientRect.left !=
1677              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
1678             (newClientRect.bottom - newClientRect.top !=
1679              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
1680              winpos->flags &= ~SWP_NOCLIENTSIZE;
1681       }
1682     else
1683       if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
1684                                     newClientRect.top != wndPtr->rectClient.top) )
1685             winpos->flags &= ~SWP_NOCLIENTMOVE;
1686
1687     /* Update active DCEs */
1688
1689     if( !(flags & SWP_NOZORDER) || (flags & SWP_HIDEWINDOW) || (flags & SWP_SHOWWINDOW)
1690                                 || (memcmp(&newWindowRect,&wndPtr->rectWindow,sizeof(RECT16))
1691                                     && wndPtr->dwStyle & WS_VISIBLE ) )
1692       {
1693         RECT16 rect;
1694
1695         UnionRect16(&rect,&newWindowRect,&wndPtr->rectWindow);
1696         DCE_InvalidateDCE(wndPtr->parent, &rect);
1697       }
1698
1699     /* change geometry */
1700
1701     oldWindowRect = wndPtr->rectWindow;
1702
1703     if (wndPtr->window)
1704     {
1705         RECT16 oldClientRect = wndPtr->rectClient;
1706
1707         tempInsertAfter = winpos->hwndInsertAfter;
1708
1709         winpos->hwndInsertAfter = hwndInsertAfter;
1710
1711         /* postpone geometry change */
1712
1713         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
1714           {
1715               WINPOS_SetXWindowPos( winpos );
1716               winpos->hwndInsertAfter = tempInsertAfter;
1717           }
1718         else  uFlags |= SMC_SETXPOS;
1719
1720         wndPtr->rectWindow = newWindowRect;
1721         wndPtr->rectClient = newClientRect;
1722
1723         if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
1724           if( (oldClientRect.left - oldWindowRect.left !=
1725                newClientRect.left - newWindowRect.left) ||
1726               (oldClientRect.top - oldWindowRect.top !=
1727                newClientRect.top - newWindowRect.top) || winpos->flags & SWP_NOCOPYBITS )
1728
1729               PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
1730                               RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1731           else
1732               if( winpos->flags & SWP_FRAMECHANGED )
1733               {
1734                 WORD wErase = 0;
1735                 RECT32 rect;
1736
1737                 if( oldClientRect.right > newClientRect.right ) 
1738                 {
1739                     rect.left = newClientRect.right; rect.top = newClientRect.top;
1740                     rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
1741                     wErase = 1;
1742                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
1743                                       RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
1744                 }
1745                 if( oldClientRect.bottom > newClientRect.bottom )
1746                 {
1747                     rect.left = newClientRect.left; rect.top = newClientRect.bottom;
1748                     rect.right = (wErase)?oldClientRect.right:newClientRect.right;
1749                     rect.bottom = oldClientRect.bottom;
1750                     wErase = 1;
1751                     PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
1752                                       RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
1753                 }
1754                 if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
1755               }
1756     }
1757     else
1758     {
1759         RECT16 oldClientRect = wndPtr->rectClient;
1760
1761         wndPtr->rectWindow = newWindowRect;
1762         wndPtr->rectClient = newClientRect;
1763
1764         if( oldClientRect.bottom - oldClientRect.top ==
1765             newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
1766
1767         if( oldClientRect.right - oldClientRect.left ==
1768             newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
1769
1770         if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
1771           {
1772             uFlags |=  ((winpos->flags & SWP_NOCOPYBITS) || 
1773                         (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
1774             uFlags |=  (winpos->flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
1775
1776             if( (winpos->flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
1777                 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
1778                                                               &oldClientRect, uFlags);
1779             else
1780               { 
1781                 /* adjust frame and do not erase parent */
1782
1783                 if( winpos->flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
1784                 if( winpos->flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
1785               }
1786           }
1787         DeleteObject(visRgn);
1788     }
1789
1790     if (flags & SWP_SHOWWINDOW)
1791     {
1792         wndPtr->dwStyle |= WS_VISIBLE;
1793         if (wndPtr->window)
1794         {
1795             if( uFlags & SMC_SETXPOS )
1796             {
1797               WINPOS_SetXWindowPos( winpos );
1798               winpos->hwndInsertAfter = tempInsertAfter;
1799             }
1800             XMapWindow( display, wndPtr->window );
1801         }
1802         else
1803         {
1804             if (!(flags & SWP_NOREDRAW))
1805                 PAINT_RedrawWindow( winpos->hwnd, NULL, 0,
1806                                 RDW_INVALIDATE | RDW_ALLCHILDREN |
1807                                 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
1808         }
1809     }
1810     else if (flags & SWP_HIDEWINDOW)
1811     {
1812         wndPtr->dwStyle &= ~WS_VISIBLE;
1813         if (wndPtr->window)
1814         {
1815             XUnmapWindow( display, wndPtr->window );
1816             if( uFlags & SMC_SETXPOS )
1817             {
1818               WINPOS_SetXWindowPos( winpos );
1819               winpos->hwndInsertAfter = tempInsertAfter;
1820             }
1821         }
1822         else
1823         {
1824             if (!(flags & SWP_NOREDRAW))
1825             {
1826                 RECT32 rect = { oldWindowRect.left, oldWindowRect.top,
1827                                 oldWindowRect.right, oldWindowRect.bottom };
1828                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &rect, 0, 
1829                         RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW, 0);
1830             }
1831             uFlags |= SMC_NOPARENTERASE;
1832         }
1833
1834         if ((winpos->hwnd == GetFocus()) || IsChild(winpos->hwnd, GetFocus()))
1835             SetFocus( GetParent32(winpos->hwnd) ); /* Revert focus to parent */
1836
1837         if (winpos->hwnd == hwndActive)
1838         {
1839               /* Activate previously active window if possible */
1840             HWND newActive = hwndPrevActive;
1841             if (!IsWindow(newActive) || (newActive == winpos->hwnd))
1842             {
1843                 newActive = GetTopWindow( GetDesktopWindow() );
1844                 if (newActive == winpos->hwnd)
1845                     newActive = wndPtr->next ? wndPtr->next->hwndSelf : 0;
1846             }       
1847             WINPOS_ChangeActiveWindow( newActive, FALSE );
1848         }
1849     }
1850
1851       /* Activate the window */
1852
1853     if (!(flags & SWP_NOACTIVATE))
1854             WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
1855     
1856       /* Repaint the window */
1857
1858     if (wndPtr->window) EVENT_Synchronize();  /* Wait for all expose events */
1859
1860     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
1861
1862     if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
1863         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
1864     else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
1865         PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
1866
1867       /* And last, send the WM_WINDOWPOSCHANGED message */
1868
1869     dprintf_win(stddeb,"\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
1870
1871     if ( ((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
1872         !(winpos->flags & SWP_NOSENDCHANGING))
1873         SendMessage16( winpos->hwnd, WM_WINDOWPOSCHANGED,
1874                        0, (LPARAM)SEGPTR_GET(winpos) );
1875
1876     SEGPTR_FREE(winpos);
1877     return TRUE;
1878 }
1879
1880                                         
1881 /***********************************************************************
1882  *           BeginDeferWindowPos   (USER.259)
1883  */
1884 HDWP16 BeginDeferWindowPos( INT count )
1885 {
1886     HDWP16 handle;
1887     DWP *pDWP;
1888
1889     if (count <= 0) return 0;
1890     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS16) );
1891     if (!handle) return 0;
1892     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1893     pDWP->actualCount    = 0;
1894     pDWP->suggestedCount = count;
1895     pDWP->valid          = TRUE;
1896     pDWP->wMagic         = DWP_MAGIC;
1897     pDWP->hwndParent     = 0;
1898     return handle;
1899 }
1900
1901
1902 /***********************************************************************
1903  *           DeferWindowPos   (USER.260)
1904  */
1905 HDWP16 DeferWindowPos( HDWP16 hdwp, HWND hwnd, HWND hwndAfter, INT x, INT y,
1906                        INT cx, INT cy, UINT flags )
1907 {
1908     DWP *pDWP;
1909     int i;
1910     HDWP16 newhdwp = hdwp;
1911     HWND parent;
1912
1913     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1914     if (!pDWP) return 0;
1915     if (hwnd == GetDesktopWindow()) return 0;
1916
1917       /* All the windows of a DeferWindowPos() must have the same parent */
1918
1919     parent = WIN_FindWndPtr( hwnd )->parent->hwndSelf;
1920     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
1921     else if (parent != pDWP->hwndParent)
1922     {
1923         USER_HEAP_FREE( hdwp );
1924         return 0;
1925     }
1926
1927     for (i = 0; i < pDWP->actualCount; i++)
1928     {
1929         if (pDWP->winPos[i].hwnd == hwnd)
1930         {
1931               /* Merge with the other changes */
1932             if (!(flags & SWP_NOZORDER))
1933             {
1934                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1935             }
1936             if (!(flags & SWP_NOMOVE))
1937             {
1938                 pDWP->winPos[i].x = x;
1939                 pDWP->winPos[i].y = y;
1940             }                
1941             if (!(flags & SWP_NOSIZE))
1942             {
1943                 pDWP->winPos[i].cx = cx;
1944                 pDWP->winPos[i].cy = cy;
1945             }
1946             pDWP->winPos[i].flags &= flags & (SWP_NOSIZE | SWP_NOMOVE |
1947                                               SWP_NOZORDER | SWP_NOREDRAW |
1948                                               SWP_NOACTIVATE | SWP_NOCOPYBITS |
1949                                               SWP_NOOWNERZORDER);
1950             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1951                                               SWP_FRAMECHANGED);
1952             return hdwp;
1953         }
1954     }
1955     if (pDWP->actualCount >= pDWP->suggestedCount)
1956     {
1957         newhdwp = USER_HEAP_REALLOC( hdwp,
1958                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS16) );
1959         if (!newhdwp) return 0;
1960         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1961         pDWP->suggestedCount++;
1962     }
1963     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1964     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1965     pDWP->winPos[pDWP->actualCount].x = x;
1966     pDWP->winPos[pDWP->actualCount].y = y;
1967     pDWP->winPos[pDWP->actualCount].cx = cx;
1968     pDWP->winPos[pDWP->actualCount].cy = cy;
1969     pDWP->winPos[pDWP->actualCount].flags = flags;
1970     pDWP->actualCount++;
1971     return newhdwp;
1972 }
1973
1974
1975 /***********************************************************************
1976  *           EndDeferWindowPos   (USER.261)
1977  */
1978 BOOL EndDeferWindowPos( HDWP16 hdwp )
1979 {
1980     DWP *pDWP;
1981     WINDOWPOS16 *winpos;
1982     BOOL res = TRUE;
1983     int i;
1984
1985     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1986     if (!pDWP) return FALSE;
1987     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1988     {
1989         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
1990                                   winpos->x, winpos->y, winpos->cx, winpos->cy,
1991                                   winpos->flags ))) break;
1992     }
1993     USER_HEAP_FREE( hdwp );
1994     return res;
1995 }
1996
1997
1998 /***********************************************************************
1999  *           TileChildWindows   (USER.199)
2000  */
2001 void TileChildWindows( HWND parent, WORD action )
2002 {
2003     printf("STUB TileChildWindows(%04x, %d)\n", parent, action);
2004 }
2005
2006 /***********************************************************************
2007  *           CascageChildWindows   (USER.198)
2008  */
2009 void CascadeChildWindows( HWND parent, WORD action )
2010 {
2011     printf("STUB CascadeChildWindows(%04x, %d)\n", parent, action);
2012 }