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