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