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