Remove capture tests from dsound.c and place them in a new file
[wine] / dlls / ttydrv / wnd.c
1 /*
2  * TTY window driver
3  *
4  * Copyright 1998,1999 Patrik Stridvall
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "gdi.h"
24 #include "ttydrv.h"
25 #include "win.h"
26 #include "winpos.h"
27 #include "wownt32.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
31
32 #define SWP_AGG_NOGEOMETRYCHANGE \
33     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
34 #define SWP_AGG_NOPOSCHANGE \
35     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
36 #define SWP_AGG_STATUSFLAGS \
37     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
38
39 /**********************************************************************
40  *              CreateWindow   (TTYDRV.@)
41  */
42 BOOL TTYDRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
43 {
44     BOOL ret;
45     HWND hwndLinkAfter;
46     CBT_CREATEWNDA cbtc;
47     WND *wndPtr = WIN_GetPtr( hwnd );
48
49     TRACE("(%p)\n", hwnd);
50
51     if (!wndPtr->parent)  /* desktop window */
52     {
53         wndPtr->pDriverData = root_window;
54         WIN_ReleasePtr( wndPtr );
55         return TRUE;
56     }
57
58 #ifdef WINE_CURSES
59     /* Only create top-level windows */
60     if (!(wndPtr->dwStyle & WS_CHILD))
61     {
62         WINDOW *window;
63         const INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
64
65         int x = wndPtr->rectWindow.left;
66         int y = wndPtr->rectWindow.top;
67         int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
68         int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
69
70         window = subwin( root_window, cy/cellHeight, cx/cellWidth,
71                          y/cellHeight, x/cellWidth);
72         werase(window);
73         wrefresh(window);
74         wndPtr->pDriverData = window;
75     }
76 #else /* defined(WINE_CURSES) */
77     FIXME("(%x): stub\n", hwnd);
78 #endif /* defined(WINE_CURSES) */
79     WIN_ReleasePtr( wndPtr );
80
81     /* Call the WH_CBT hook */
82
83     hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
84
85     cbtc.lpcs = cs;
86     cbtc.hwndInsertAfter = hwndLinkAfter;
87     if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
88     {
89         TRACE("CBT-hook returned !0\n");
90         return FALSE;
91     }
92
93     if (unicode)
94     {
95         ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
96         if (ret) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
97     }
98     else
99     {
100         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
101         if (ret) ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
102     }
103     return ret;
104 }
105
106 /***********************************************************************
107  *              DestroyWindow   (TTYDRV.@)
108  */
109 BOOL TTYDRV_DestroyWindow( HWND hwnd )
110 {
111 #ifdef WINE_CURSES
112     WND *wndPtr = WIN_GetPtr( hwnd );
113     WINDOW *window = wndPtr->pDriverData;
114
115     TRACE("(%p)\n", hwnd);
116
117     if (window && window != root_window) delwin(window);
118     wndPtr->pDriverData = NULL;
119     WIN_ReleasePtr( wndPtr );
120 #else /* defined(WINE_CURSES) */
121     FIXME("(%x): stub\n", hwnd);
122 #endif /* defined(WINE_CURSES) */
123     return TRUE;
124 }
125
126
127 /***********************************************************************
128  *           DCE_GetVisRect
129  *
130  * Calculate the visible rectangle of a window (i.e. the client or
131  * window area clipped by the client area of all ancestors) in the
132  * corresponding coordinates. Return FALSE if the visible region is empty.
133  */
134 static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
135 {
136     *lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
137
138     if (wndPtr->dwStyle & WS_VISIBLE)
139     {
140         INT xoffset = lprect->left;
141         INT yoffset = lprect->top;
142
143         while ((wndPtr = WIN_FindWndPtr( GetAncestor(wndPtr->hwndSelf,GA_PARENT) )))
144         {
145             if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
146             {
147                 WIN_ReleaseWndPtr(wndPtr);
148                 goto fail;
149             }
150
151             xoffset += wndPtr->rectClient.left;
152             yoffset += wndPtr->rectClient.top;
153             OffsetRect( lprect, wndPtr->rectClient.left,
154                         wndPtr->rectClient.top );
155
156             if( (wndPtr->rectClient.left >= wndPtr->rectClient.right) ||
157                 (wndPtr->rectClient.top >= wndPtr->rectClient.bottom) ||
158                 (lprect->left >= wndPtr->rectClient.right) ||
159                 (lprect->right <= wndPtr->rectClient.left) ||
160                 (lprect->top >= wndPtr->rectClient.bottom) ||
161                 (lprect->bottom <= wndPtr->rectClient.top) )
162             {
163                 WIN_ReleaseWndPtr(wndPtr);
164                 goto fail;
165             }
166
167             lprect->left = max( lprect->left, wndPtr->rectClient.left );
168             lprect->right = min( lprect->right, wndPtr->rectClient.right );
169             lprect->top = max( lprect->top, wndPtr->rectClient.top );
170             lprect->bottom = min( lprect->bottom, wndPtr->rectClient.bottom );
171
172             WIN_ReleaseWndPtr(wndPtr);
173         }
174         OffsetRect( lprect, -xoffset, -yoffset );
175         return TRUE;
176     }
177
178 fail:
179     SetRectEmpty( lprect );
180     return FALSE;
181 }
182
183
184 /***********************************************************************
185  *           DCE_AddClipRects
186  *
187  * Go through the linked list of windows from pWndStart to pWndEnd,
188  * adding to the clip region the intersection of the target rectangle
189  * with an offset window rectangle.
190  */
191 static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
192 {
193     RECT rect;
194     WND *pWnd;
195     int i;
196     HWND *list = WIN_ListChildren( parent );
197     HRGN hrgn = 0;
198
199     if (!list) return;
200     for (i = 0; list[i]; i++)
201     {
202         if (list[i] == end) break;
203         if (!(pWnd = WIN_FindWndPtr( list[i] ))) continue;
204         if (pWnd->dwStyle & WS_VISIBLE)
205         {
206             rect.left = pWnd->rectWindow.left + x;
207             rect.top = pWnd->rectWindow.top + y;
208             rect.right = pWnd->rectWindow.right + x;
209             rect.bottom = pWnd->rectWindow.bottom + y;
210             if( IntersectRect( &rect, &rect, lpRect ))
211             {
212                 if (!hrgn) hrgn = CreateRectRgnIndirect( &rect );
213                 else SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
214                 CombineRgn( hrgnClip, hrgnClip, hrgn, RGN_OR );
215             }
216         }
217         WIN_ReleaseWndPtr( pWnd );
218     }
219     if (hrgn) DeleteObject( hrgn );
220     HeapFree( GetProcessHeap(), 0, list );
221 }
222
223
224 /***********************************************************************
225  *           DCE_GetVisRgn
226  *
227  * Return the visible region of a window, i.e. the client or window area
228  * clipped by the client area of all ancestors, and then optionally
229  * by siblings and children.
230  */
231 static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
232 {
233     HRGN hrgnVis = 0;
234     RECT rect;
235     WND *wndPtr = WIN_FindWndPtr( hwnd );
236     WND *childWnd = WIN_FindWndPtr( hwndChild );
237
238     /* Get visible rectangle and create a region with it. */
239
240     if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
241     {
242         if((hrgnVis = CreateRectRgnIndirect( &rect )))
243         {
244             HRGN hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
245             INT xoffset, yoffset;
246
247             if( hrgnClip )
248             {
249                 /* Compute obscured region for the visible rectangle by
250                  * clipping children, siblings, and ancestors. Note that
251                  * DCE_GetVisRect() returns a rectangle either in client
252                  * or in window coordinates (for DCX_WINDOW request). */
253
254                 if (flags & DCX_CLIPCHILDREN)
255                 {
256                     if( flags & DCX_WINDOW )
257                     {
258                         /* adjust offsets since child window rectangles are
259                          * in client coordinates */
260
261                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
262                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
263                     }
264                     else
265                         xoffset = yoffset = 0;
266
267                     DCE_AddClipRects( wndPtr->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
268                 }
269
270                 /* We may need to clip children of child window, if a window with PARENTDC
271                  * class style and CLIPCHILDREN window style (like in Free Agent 16
272                  * preference dialogs) gets here, we take the region for the parent window
273                  * but apparently still need to clip the children of the child window... */
274
275                 if( (cflags & DCX_CLIPCHILDREN) && childWnd)
276                 {
277                     if( flags & DCX_WINDOW )
278                     {
279                         /* adjust offsets since child window rectangles are
280                          * in client coordinates */
281
282                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
283                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
284                     }
285                     else
286                         xoffset = yoffset = 0;
287
288                     /* client coordinates of child window */
289                     xoffset += childWnd->rectClient.left;
290                     yoffset += childWnd->rectClient.top;
291
292                     DCE_AddClipRects( childWnd->hwndSelf, 0, hrgnClip,
293                                       &rect, xoffset, yoffset );
294                 }
295
296                 /* sibling window rectangles are in client
297                  * coordinates of the parent window */
298
299                 if (flags & DCX_WINDOW)
300                 {
301                     xoffset = -wndPtr->rectWindow.left;
302                     yoffset = -wndPtr->rectWindow.top;
303                 }
304                 else
305                 {
306                     xoffset = -wndPtr->rectClient.left;
307                     yoffset = -wndPtr->rectClient.top;
308                 }
309
310                 if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
311                     DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
312                                       hrgnClip, &rect, xoffset, yoffset );
313
314                 /* Clip siblings of all ancestors that have the
315                  * WS_CLIPSIBLINGS style
316                  */
317
318                 while (wndPtr->parent)
319                 {
320                     WND *ptr = WIN_FindWndPtr( wndPtr->parent );
321                     WIN_ReleaseWndPtr( wndPtr );
322                     wndPtr = ptr;
323                     xoffset -= wndPtr->rectClient.left;
324                     yoffset -= wndPtr->rectClient.top;
325                     if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
326                     {
327                         DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
328                                           hrgnClip, &rect, xoffset, yoffset );
329                     }
330                 }
331
332                 /* Now once we've got a jumbo clip region we have
333                  * to substract it from the visible rectangle.
334                  */
335                 CombineRgn( hrgnVis, hrgnVis, hrgnClip, RGN_DIFF );
336                 DeleteObject( hrgnClip );
337             }
338             else
339             {
340                 DeleteObject( hrgnVis );
341                 hrgnVis = 0;
342             }
343         }
344     }
345     else
346         hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
347     WIN_ReleaseWndPtr(wndPtr);
348     WIN_ReleaseWndPtr(childWnd);
349     return hrgnVis;
350 }
351
352
353 /***********************************************************************
354  *              GetDC   (TTYDRV.@)
355  *
356  * Set the drawable, origin and dimensions for the DC associated to
357  * a given window.
358  */
359 BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
360 {
361     WND *wndPtr = WIN_FindWndPtr(hwnd);
362     HRGN hrgnVisible = 0;
363     POINT org;
364
365     if (!wndPtr) return FALSE;
366
367     if(flags & DCX_WINDOW)
368     {
369         org.x = wndPtr->rectWindow.left;
370         org.y = wndPtr->rectWindow.top;
371     }
372     else
373     {
374         org.x = wndPtr->rectClient.left;
375         org.y = wndPtr->rectClient.top;
376     }
377
378     SetDCOrg16( HDC_16(hdc), org.x, org.y );
379
380     if (SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN ))  /* DC was dirty */
381     {
382         if (flags & DCX_PARENTCLIP)
383         {
384             WND *parentPtr = WIN_FindWndPtr( wndPtr->parent );
385
386             if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
387             {
388                 DWORD dcxFlags;
389
390                 if( parentPtr->dwStyle & WS_CLIPSIBLINGS )
391                     dcxFlags = DCX_CLIPSIBLINGS | (flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
392                 else
393                     dcxFlags = flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
394
395                 hrgnVisible = DCE_GetVisRgn( parentPtr->hwndSelf, dcxFlags,
396                                              wndPtr->hwndSelf, flags );
397                 if( flags & DCX_WINDOW )
398                     OffsetRgn( hrgnVisible, -wndPtr->rectWindow.left,
399                                -wndPtr->rectWindow.top );
400                 else
401                     OffsetRgn( hrgnVisible, -wndPtr->rectClient.left,
402                                -wndPtr->rectClient.top );
403             }
404             else
405                 hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
406             WIN_ReleaseWndPtr(parentPtr);
407         }
408         else
409         {
410             hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
411             OffsetRgn( hrgnVisible, org.x, org.y );
412         }
413         SelectVisRgn16( HDC_16(hdc), HRGN_16(hrgnVisible) );
414     }
415
416     /* apply additional region operation (if any) */
417
418     if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
419     {
420         if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
421
422         TRACE("\tsaved VisRgn, clipRgn = %p\n", hrgn);
423
424         SaveVisRgn16( HDC_16(hdc) );
425         CombineRgn( hrgnVisible, hrgn, 0, RGN_COPY );
426         OffsetRgn( hrgnVisible, org.x, org.y );
427         CombineRgn( hrgnVisible, HRGN_32(InquireVisRgn16(HDC_16(hdc))), hrgnVisible,
428                       (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
429         SelectVisRgn16(HDC_16(hdc), HRGN_16(hrgnVisible));
430     }
431
432     if (hrgnVisible) DeleteObject( hrgnVisible );
433
434     WIN_ReleaseWndPtr( wndPtr );
435     return TRUE;
436 }
437
438
439 /***********************************************************************
440  *              SetWindowPos   (TTYDRV.@)
441  */
442 BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
443 {
444     WND *wndPtr;
445     RECT newWindowRect, newClientRect;
446     BOOL retvalue;
447     HWND hwndActive = GetForegroundWindow();
448
449     TRACE( "hwnd %p, swp (%i,%i)-(%i,%i) flags %08x\n",
450            winpos->hwnd, winpos->x, winpos->y,
451            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
452
453     /* ------------------------------------------------------------------------ CHECKS */
454
455       /* Check window handle */
456
457     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
458     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
459
460     TRACE("\tcurrent (%ld,%ld)-(%ld,%ld), style %08x\n",
461           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
462           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
463
464     /* Fix redundant flags */
465
466     if(wndPtr->dwStyle & WS_VISIBLE)
467         winpos->flags &= ~SWP_SHOWWINDOW;
468     else
469     {
470         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
471         winpos->flags &= ~SWP_HIDEWINDOW;
472     }
473
474     if ( winpos->cx < 0 ) winpos->cx = 0;
475     if ( winpos->cy < 0 ) winpos->cy = 0;
476
477     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
478         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
479         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
480
481     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
482         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
483
484     if (winpos->hwnd == hwndActive)
485         winpos->flags |= SWP_NOACTIVATE;   /* Already active */
486     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
487     {
488         if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
489         {
490             winpos->flags &= ~SWP_NOZORDER;
491             winpos->hwndInsertAfter = HWND_TOP;
492             goto Pos;
493         }
494     }
495
496     /* Check hwndInsertAfter */
497
498       /* FIXME: TOPMOST not supported yet */
499     if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
500         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
501
502     /* hwndInsertAfter must be a sibling of the window */
503     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
504     {
505         WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
506
507         if( wnd ) {
508             if( wnd->parent != wndPtr->parent )
509             {
510                 retvalue = FALSE;
511                 WIN_ReleaseWndPtr(wnd);
512                 goto END;
513             }
514             /* don't need to change the Zorder of hwnd if it's already inserted
515              * after hwndInsertAfter or when inserting hwnd after itself.
516              */
517             if ((winpos->hwnd == winpos->hwndInsertAfter) ||
518                 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
519                 winpos->flags |= SWP_NOZORDER;
520         }
521         WIN_ReleaseWndPtr(wnd);
522     }
523
524  Pos:  /* ------------------------------------------------------------------------ MAIN part */
525
526       /* Send WM_WINDOWPOSCHANGING message */
527
528     if (!(winpos->flags & SWP_NOSENDCHANGING))
529         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos );
530
531       /* Calculate new position and size */
532
533     newWindowRect = wndPtr->rectWindow;
534     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
535                                                     : wndPtr->rectClient;
536
537     if (!(winpos->flags & SWP_NOSIZE))
538     {
539         newWindowRect.right  = newWindowRect.left + winpos->cx;
540         newWindowRect.bottom = newWindowRect.top + winpos->cy;
541     }
542     if (!(winpos->flags & SWP_NOMOVE))
543     {
544         newWindowRect.left    = winpos->x;
545         newWindowRect.top     = winpos->y;
546         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
547         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
548
549         OffsetRect( &newClientRect, winpos->x - wndPtr->rectWindow.left,
550                     winpos->y - wndPtr->rectWindow.top );
551     }
552
553     if( winpos->hwndInsertAfter == HWND_TOP )
554     {
555         if (GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ) == wndPtr->hwndSelf)
556             winpos->flags |= SWP_NOZORDER;
557     }
558     else
559         if( winpos->hwndInsertAfter == HWND_BOTTOM )
560         {
561             if (!GetWindow( wndPtr->hwndSelf, GW_HWNDNEXT ))
562                 winpos->flags |= SWP_NOZORDER;
563         }
564         else
565             if( !(winpos->flags & SWP_NOZORDER) )
566                 if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
567                     winpos->flags |= SWP_NOZORDER;
568
569     /* Common operations */
570
571       /* Send WM_NCCALCSIZE message to get new client area */
572     if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
573     {
574         NCCALCSIZE_PARAMS params;
575         WINDOWPOS winposCopy;
576
577         params.rgrc[0] = newWindowRect;
578         params.rgrc[1] = wndPtr->rectWindow;
579         params.rgrc[2] = wndPtr->rectClient;
580         params.lppos = &winposCopy;
581         winposCopy = *winpos;
582
583         SendMessageW( winpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
584
585         TRACE( "%ld,%ld-%ld,%ld\n", params.rgrc[0].left, params.rgrc[0].top,
586                params.rgrc[0].right, params.rgrc[0].bottom );
587
588         /* If the application send back garbage, ignore it */
589         if (params.rgrc[0].left <= params.rgrc[0].right &&
590             params.rgrc[0].top <= params.rgrc[0].bottom)
591             newClientRect = params.rgrc[0];
592
593          /* FIXME: WVR_ALIGNxxx */
594
595         if( newClientRect.left != wndPtr->rectClient.left ||
596             newClientRect.top != wndPtr->rectClient.top )
597             winpos->flags &= ~SWP_NOCLIENTMOVE;
598
599         if( (newClientRect.right - newClientRect.left !=
600              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
601             (newClientRect.bottom - newClientRect.top !=
602              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
603             winpos->flags &= ~SWP_NOCLIENTSIZE;
604     }
605
606     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
607     {
608         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
609         if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
610     }
611
612     /* FIXME: actually do something with WVR_VALIDRECTS */
613
614     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
615
616     if( winpos->flags & SWP_SHOWWINDOW )
617         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
618     else if( winpos->flags & SWP_HIDEWINDOW )
619         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
620
621     /* ------------------------------------------------------------------------ FINAL */
622
623     /* repaint invalidated region (if any)
624      *
625      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
626      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
627      */
628
629     if( !(winpos->flags & SWP_NOREDRAW) )
630     {
631         RedrawWindow( wndPtr->parent, NULL, 0,
632                       RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
633         if (wndPtr->parent == GetDesktopWindow())
634             RedrawWindow( wndPtr->parent, NULL, 0,
635                           RDW_ERASENOW | RDW_NOCHILDREN );
636     }
637
638     if (!(winpos->flags & SWP_NOACTIVATE)) SetActiveWindow( winpos->hwnd );
639
640       /* And last, send the WM_WINDOWPOSCHANGED message */
641
642     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
643
644     if ((((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
645           !(winpos->flags & SWP_NOSENDCHANGING)) )
646         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
647
648     retvalue = TRUE;
649  END:
650     WIN_ReleaseWndPtr(wndPtr);
651     return retvalue;
652 }
653
654
655 /***********************************************************************
656  *              WINPOS_MinMaximize   (internal)
657  *
658  *Lifted from x11 driver
659  */
660 static UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
661 {
662     UINT swpFlags = 0;
663     WINDOWPLACEMENT wpl;
664
665     TRACE("%p %u\n", hwnd, cmd );
666     FIXME("(%p): stub\n", hwnd);
667
668     wpl.length = sizeof(wpl);
669     GetWindowPlacement( hwnd, &wpl );
670
671     /* If I glark this right, yields an immutable window*/
672     swpFlags = SWP_NOSIZE | SWP_NOMOVE;
673
674     /*cmd handling goes here.  see dlls/x1drv/winpos.c*/
675
676     return swpFlags;
677 }
678
679 /***********************************************************************
680  *              ShowWindow   (TTYDRV.@)
681  *
682  *Lifted from x11 driver
683  *Sets the specified windows' show state.
684  */
685 BOOL TTYDRV_ShowWindow( HWND hwnd, INT cmd )
686 {
687     WND*        wndPtr = WIN_FindWndPtr( hwnd );
688     BOOL        wasVisible, showFlag;
689     RECT        newPos = {0, 0, 0, 0};
690     UINT        swp = 0;
691
692     if (!wndPtr) return FALSE;
693     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
694
695     TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd);
696
697     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
698
699     switch(cmd)
700     {
701         case SW_HIDE:
702             if (!wasVisible) goto END;
703             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
704                         SWP_NOACTIVATE | SWP_NOZORDER;
705             break;
706
707         case SW_SHOWMINNOACTIVE:
708             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
709             /* fall through */
710         case SW_SHOWMINIMIZED:
711             swp |= SWP_SHOWWINDOW;
712             /* fall through */
713         case SW_MINIMIZE:
714             swp |= SWP_FRAMECHANGED;
715             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
716                  swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
717             else swp |= SWP_NOSIZE | SWP_NOMOVE;
718             break;
719
720         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
721             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
722             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
723                  swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
724             else swp |= SWP_NOSIZE | SWP_NOMOVE;
725             break;
726
727         case SW_SHOWNA:
728             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
729             /* fall through */
730         case SW_SHOW:
731             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
732
733             /*
734              * ShowWindow has a little peculiar behavior that if the
735              * window is already the topmost window, it will not
736              * activate it.
737              */
738             if (GetTopWindow(NULL)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
739               swp |= SWP_NOACTIVATE;
740
741             break;
742
743         case SW_SHOWNOACTIVATE:
744             swp |= SWP_NOZORDER;
745             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
746             /* fall through */
747         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
748         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
749         case SW_RESTORE:
750             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
751
752             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
753                  swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
754             else swp |= SWP_NOSIZE | SWP_NOMOVE;
755             break;
756     }
757
758     showFlag = (cmd != SW_HIDE);
759     if (showFlag != wasVisible)
760     {
761         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
762         if (!IsWindow( hwnd )) goto END;
763     }
764
765     /* We can't activate a child window */
766     if ((wndPtr->dwStyle & WS_CHILD) &&
767         !(wndPtr->dwExStyle & WS_EX_MDICHILD))
768         swp |= SWP_NOACTIVATE | SWP_NOZORDER;
769
770     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
771                   newPos.right, newPos.bottom, LOWORD(swp) );
772     if (cmd == SW_HIDE)
773     {
774         /* FIXME: This will cause the window to be activated irrespective
775          * of whether it is owned by the same thread. Has to be done
776          * asynchronously.
777          */
778
779         if (hwnd == GetActiveWindow())
780             WINPOS_ActivateOtherWindow(hwnd);
781
782         /* Revert focus to parent */
783         if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
784             SetFocus( GetParent(hwnd) );
785     }
786     if (!IsWindow( hwnd )) goto END;
787     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
788
789     if (wndPtr->flags & WIN_NEED_SIZE)
790     {
791         /* should happen only in CreateWindowEx() */
792         int wParam = SIZE_RESTORED;
793
794         wndPtr->flags &= ~WIN_NEED_SIZE;
795         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
796         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
797         SendMessageA( hwnd, WM_SIZE, wParam,
798                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
799                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
800         SendMessageA( hwnd, WM_MOVE, 0,
801                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
802     }
803
804 END:
805     WIN_ReleaseWndPtr(wndPtr);
806     return wasVisible;
807 }