Release 0.6
[wine] / windows / win.c
1 /*
2  * Window related functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
11 #include <X11/Core.h>
12 #include <X11/Shell.h>
13
14 #include "class.h"
15 #include "win.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19
20 extern Display * display;
21 extern Colormap COLOR_WinColormap;
22
23 extern void EVENT_RegisterWindow( Window w, HWND hwnd );  /* event.c */
24
25 static HWND firstWindow = 0;
26
27 /***********************************************************************
28  *           WIN_FindWndPtr
29  *
30  * Return a pointer to the WND structure corresponding to a HWND.
31  */
32 WND * WIN_FindWndPtr( HWND hwnd )
33 {
34     WND * ptr;
35     
36     if (!hwnd) return NULL;
37     ptr = (WND *) USER_HEAP_ADDR( hwnd );
38     if (ptr->dwMagic != WND_MAGIC) return NULL;
39     return ptr;
40 }
41
42
43 /***********************************************************************
44  *           WIN_UnlinkWindow
45  *
46  * Remove a window from the siblings linked list.
47  */
48 BOOL WIN_UnlinkWindow( HWND hwnd )
49 {    
50     HWND * curWndPtr;
51     WND * wndPtr = WIN_FindWndPtr( hwnd );
52
53     if (!wndPtr) return FALSE;
54     if (wndPtr->hwndParent)
55     {
56         WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
57         curWndPtr = &parentPtr->hwndChild;
58     }    
59     else curWndPtr = &firstWindow;
60
61     while (*curWndPtr != hwnd)
62     {
63         WND * curPtr = WIN_FindWndPtr( *curWndPtr );
64         curWndPtr = &curPtr->hwndNext;
65     }
66     *curWndPtr = wndPtr->hwndNext;
67     return TRUE;
68 }
69
70
71 /***********************************************************************
72  *           WIN_LinkWindow
73  *
74  * Insert a window into the siblings linked list.
75  * The window is inserted after the specified window, which can also
76  * be specified as HWND_TOP or HWND_BOTTOM.
77  */
78 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
79 {    
80     HWND * hwndPtr = NULL;  /* pointer to hwnd to change */
81
82     WND * wndPtr = WIN_FindWndPtr( hwnd );
83     if (!wndPtr) return FALSE;
84     
85     if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
86     {
87           /* Make hwndPtr point to the first sibling hwnd */
88         if (wndPtr->hwndParent)
89         {
90             WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
91             if (parentPtr) hwndPtr = &parentPtr->hwndChild;
92         }
93         else hwndPtr = &firstWindow;
94         if (hwndInsertAfter == HWND_BOTTOM)  /* Find last sibling hwnd */
95             while (*hwndPtr)
96             {
97                 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
98                 hwndPtr = &nextPtr->hwndNext;
99             }
100     }
101     else  /* Normal case */
102     {
103         WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
104         if (afterPtr) hwndPtr = &afterPtr->hwndNext;
105     }
106     if (!hwndPtr) return FALSE;
107     wndPtr->hwndNext = *hwndPtr;
108     *hwndPtr = hwnd;
109     return TRUE;
110 }
111
112
113 /***********************************************************************
114  *           WIN_FindWinToRepaint
115  *
116  * Find a window that needs repaint.
117  */
118 HWND WIN_FindWinToRepaint( HWND hwnd )
119 {
120     WND * wndPtr;
121     
122     if (!hwnd) hwnd = firstWindow;
123     for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
124     {
125         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
126         if (wndPtr->hrgnUpdate) return hwnd;
127         if (wndPtr->hwndChild)
128         {
129             HWND child;
130             if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
131                 return child;
132         }
133     }
134     return 0;
135 }
136
137
138 /***********************************************************************
139  *           WIN_SendParentNotify
140  *
141  * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
142  * the window has the WS_EX_NOPARENTNOTIFY style.
143  */
144 static void WIN_SendParentNotify( HWND hwnd, WND * wndPtr, WORD event )
145 {
146     HWND current = wndPtr->hwndParent;
147
148     if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) return;
149     while (current)
150     {
151         SendMessage( current, WM_PARENTNOTIFY, 
152                      event, MAKELONG( hwnd, wndPtr->wIDmenu ) );
153         current = GetParent( current );
154     }
155 }
156
157
158 /***********************************************************************
159  *           CreateWindow   (USER.41)
160  */
161 HWND CreateWindow( LPSTR className, LPSTR windowName,
162                    DWORD style, short x, short y, short width, short height,
163                    HWND parent, HMENU menu, HANDLE instance, LPSTR data ) 
164 {
165     return CreateWindowEx( 0, className, windowName, style,
166                            x, y, width, height, parent, menu, instance, data );
167 }
168
169
170 /***********************************************************************
171  *           CreateWindowEx   (USER.452)
172  */
173 HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
174                      DWORD style, short x, short y, short width, short height,
175                      HWND parent, HMENU menu, HANDLE instance, LPSTR data ) 
176 {
177     HANDLE class, hwnd;
178     CLASS *classPtr;
179     WND *wndPtr, *parentPtr = NULL;
180     CREATESTRUCT *createStruct;
181     HANDLE hcreateStruct;
182     int wmcreate;
183     XSetWindowAttributes win_attr;
184     Window parentWindow;
185     int x_rel, y_rel;
186     LPPOPUPMENU lpbar;
187
188 #ifdef DEBUG_WIN
189     printf( "CreateWindowEx: %d '%s' '%s' %d,%d %dx%d %08x %x\n",
190            exStyle, className, windowName, x, y, width, height, style, parent);
191 #endif
192
193     if (x == CW_USEDEFAULT) x = y = 0;
194     if (width == CW_USEDEFAULT)
195     {
196         width = 600;
197         height = 400;
198     }
199     if (width == 0) width = 1;
200     if (height == 0) height = 1;
201
202       /* Find the parent and class */
203
204     if (parent) 
205     {
206           /* Check if parent is valid */
207         parentPtr = WIN_FindWndPtr( parent );
208         if (!parent) return 0;
209     }
210     else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
211     
212     if (!(class = CLASS_FindClassByName( className, &classPtr ))) {
213         printf("CreateWindow BAD CLASSNAME '%s' !\n", className);
214         return 0;
215         }    
216
217       /* Correct the window style */
218
219     if (!(style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
220         style |= WS_CAPTION | WS_CLIPSIBLINGS;
221     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
222
223       /* Create the window structure */
224
225     hwnd = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra);
226     if (!hwnd) return 0;
227
228       /* Fill the structure */
229
230     wndPtr = (WND *) USER_HEAP_ADDR( hwnd );
231     wndPtr->hwndNext   = 0;
232     wndPtr->hwndChild  = 0;
233     wndPtr->dwMagic    = WND_MAGIC;
234     wndPtr->hwndParent = (style & WS_CHILD) ? parent : 0;
235     wndPtr->hwndOwner  = (style & WS_CHILD) ? 0 : parent;
236     wndPtr->hClass     = class;
237     wndPtr->hInstance  = instance;
238     wndPtr->rectWindow.left   = x;
239     wndPtr->rectWindow.top    = y;
240     wndPtr->rectWindow.right  = x + width;
241     wndPtr->rectWindow.bottom = y + height;
242     wndPtr->rectClient        = wndPtr->rectWindow;
243     wndPtr->hmemTaskQ         = GetTaskQueue(0);
244     wndPtr->hrgnUpdate        = 0;
245     wndPtr->hwndLastActive    = 0;
246     wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
247     wndPtr->dwStyle           = style;
248     wndPtr->dwExStyle         = exStyle;
249     wndPtr->hmenuSystem       = 0;
250     wndPtr->wIDmenu           = menu;
251     wndPtr->hText             = 0;
252     wndPtr->flags             = 0;
253     wndPtr->hCursor           = 0;
254     wndPtr->hWndVScroll       = 0;
255     wndPtr->hWndHScroll       = 0;
256     wndPtr->hWndMenuBar       = 0;
257     wndPtr->hWndCaption       = 0;
258
259     if (classPtr->wc.cbWndExtra)
260         memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
261     if (classPtr->wc.style & CS_DBLCLKS) wndPtr->flags |= WIN_DOUBLE_CLICKS;
262     classPtr->cWindows++;
263
264       /* Get class or window DC if needed */
265     if (classPtr->wc.style & CS_OWNDC)
266     {
267         wndPtr->flags |= WIN_OWN_DC;
268         wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
269     }
270     else if (classPtr->wc.style & CS_CLASSDC)
271     {
272         wndPtr->flags |= WIN_CLASS_DC;
273         wndPtr->hdce = classPtr->hdce;
274     }
275     else wndPtr->hdce = 0;
276
277       /* Insert the window in the linked list */
278
279     WIN_LinkWindow( hwnd, HWND_TOP );
280
281       /* Create the X window */
282
283     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
284                           PointerMotionMask | ButtonPressMask |
285                           ButtonReleaseMask | StructureNotifyMask |
286                           FocusChangeMask | EnterWindowMask;
287     win_attr.override_redirect = /*True*/ False;
288     win_attr.colormap = COLOR_WinColormap;
289     if (style & WS_CHILD)
290     {
291         parentWindow = parentPtr->window;
292         x_rel = x + parentPtr->rectClient.left - parentPtr->rectWindow.left;
293         y_rel = y + parentPtr->rectClient.top - parentPtr->rectWindow.top;
294     }
295     else
296     {
297         parentWindow = DefaultRootWindow( display );
298         x_rel = x;
299         y_rel = y;
300     }
301     wndPtr->window = XCreateWindow(display, parentWindow,
302                                    x_rel, y_rel, width, height, 0,
303                                    CopyFromParent, InputOutput, CopyFromParent,
304                                    CWEventMask | CWOverrideRedirect |
305                                    CWColormap, &win_attr );
306     XStoreName( display, wndPtr->window, windowName );
307
308       /* Send the WM_CREATE message */
309         
310     hcreateStruct = GlobalAlloc( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
311     createStruct = (CREATESTRUCT *) GlobalLock( hcreateStruct );
312     createStruct->lpCreateParams = data;
313     createStruct->hInstance      = instance;
314     createStruct->hMenu          = menu;
315     createStruct->hwndParent     = parent;
316     createStruct->cx             = width;
317     createStruct->cy             = height;
318     createStruct->x              = x;
319     createStruct->y              = y;
320     createStruct->style          = style;
321     createStruct->lpszName       = windowName;
322     createStruct->lpszClass      = className;
323     createStruct->dwExStyle      = 0;
324
325     wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
326     if (!wmcreate) wmcreate = -1;
327     else
328     {
329           /* Send WM_NCCALCSIZE message */
330         NCCALCSIZE_PARAMS *params;
331         HANDLE hparams;
332         hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
333         if (hparams)
334         {
335             params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
336             params->rgrc[0] = wndPtr->rectWindow;
337             params->lppos = NULL;
338             SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
339             wndPtr->rectClient = params->rgrc[0];
340             GlobalUnlock( hparams );
341             GlobalFree( hparams );
342         }       
343         wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
344     }
345
346     GlobalUnlock( hcreateStruct );
347     GlobalFree( hcreateStruct );
348
349     if (wmcreate == -1)
350     {
351           /* Abort window creation */
352
353         WIN_UnlinkWindow( hwnd );
354         XDestroyWindow( display, wndPtr->window );
355         if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
356         classPtr->cWindows--;
357         USER_HEAP_FREE( hwnd );
358         return 0;
359     }
360
361       /* Create scrollbars */
362
363     if (windowName != NULL) SetWindowText(hwnd, windowName);
364     if ((style & WS_CAPTION) == WS_CAPTION) {
365         wndPtr->hWndCaption = CreateWindow("CAPTION", "",
366                 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
367                 0, -20, width, 20, hwnd, 1, instance, 0L);
368         }
369     if (((style & WS_CHILD) != WS_CHILD) && (wndPtr->wIDmenu != 0)) {
370         lpbar = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
371         if (lpbar != NULL) {
372             lpbar->ownerWnd = hwnd;
373             wndPtr->hWndMenuBar = CreateWindow("POPUPMENU", "",
374                 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
375                 0, 0, width, 20, hwnd, 2, instance, (LPSTR)lpbar);
376             }
377         }
378     if ((style & WS_VSCROLL) == WS_VSCROLL)
379     {
380         wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
381                 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
382                 wndPtr->rectClient.right-wndPtr->rectClient.left, 0,
383                 SYSMETRICS_CXVSCROLL,
384                 wndPtr->rectClient.bottom-wndPtr->rectClient.top,
385                 hwnd, 3, instance, 0L);
386     }
387     if ((style & WS_HSCROLL) == WS_HSCROLL)
388     {
389         wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
390                 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
391                 0, wndPtr->rectClient.bottom-wndPtr->rectClient.top,
392                 wndPtr->rectClient.right-wndPtr->rectClient.left,
393                 SYSMETRICS_CYHSCROLL,
394                 hwnd, 4, instance, 0L);
395     }
396
397     EVENT_RegisterWindow( wndPtr->window, hwnd );
398
399     WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
400     
401     if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
402     return hwnd;
403 }
404
405 /***********************************************************************
406  *           DestroyWindow   (USER.53)
407  */
408 BOOL DestroyWindow( HWND hwnd )
409 {
410     WND * wndPtr;
411     CLASS * classPtr;
412     
413       /* Initialisation */
414
415     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
416     if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
417     WIN_SendParentNotify( hwnd, wndPtr, WM_DESTROY );
418
419       /* Send destroy messages */
420
421     SendMessage( hwnd, WM_DESTROY, 0, 0 );
422     SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
423     
424       /* Destroy all children */
425
426     if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
427     if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
428     while (wndPtr->hwndChild)  /* The child removes itself from the list */
429         DestroyWindow( wndPtr->hwndChild );
430
431       /* Remove the window from the linked list */
432
433     WIN_UnlinkWindow( hwnd );
434
435       /* Destroy the window */
436
437     XDestroyWindow( display, wndPtr->window );
438     if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
439     classPtr->cWindows--;
440     USER_HEAP_FREE( hwnd );
441     return TRUE;
442 }
443
444
445 /***********************************************************************
446  *           CloseWindow   (USER.43)
447  */
448 void CloseWindow(HWND hWnd)
449 {
450     WND * wndPtr = WIN_FindWndPtr(hWnd);
451     if (wndPtr->dwStyle & WS_CHILD) return;
452     ShowWindow(hWnd, SW_MINIMIZE);
453 }
454
455  
456  
457 /***********************************************************************
458  *           OpenIcon   (USER.44)
459  */
460 BOOL OpenIcon(HWND hWnd)
461 {
462     if (!IsIconic(hWnd)) return FALSE;
463     ShowWindow(hWnd, SW_SHOWNORMAL);
464     return(TRUE);
465 }
466
467  
468  
469 /***********************************************************************
470  *           FindWindow   (USER.50)
471  */
472 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
473 {
474     return((HWND)NULL);
475 }
476  
477  
478 /***********************************************************************
479  *           UpdateWindow   (USER.124)
480  */
481 void UpdateWindow( HWND hwnd )
482 {
483     if (GetUpdateRect( hwnd, NULL, FALSE )) 
484     {
485         if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
486     }
487 }
488
489 /**********************************************************************
490  *           GetMenu        (USER.157)
491  */
492 HMENU GetMenu( HWND hwnd ) 
493
494     WND * wndPtr = WIN_FindWndPtr(hwnd);
495     if (wndPtr == NULL)
496         return 0;
497     return wndPtr->wIDmenu;
498 }
499
500 /**********************************************************************
501  *           SetMenu        (USER.158)
502  */
503 BOOL SetMenu(HWND hwnd, HMENU hmenu)
504 {
505     return FALSE;
506 }
507
508
509 /**********************************************************************
510  *           GetDesktopWindow        (USER.286)
511  */
512 HWND GetDesktopWindow()
513 {
514     return 0;
515 }
516
517
518
519 /**********************************************************************
520  *           GetWindowWord    (USER.133)
521  */
522 WORD GetWindowWord( HWND hwnd, short offset )
523 {
524     WND * wndPtr = WIN_FindWndPtr( hwnd );
525     if (!wndPtr) return 0;
526     if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
527     switch(offset)
528     {
529         case GWW_ID:         return wndPtr->wIDmenu;
530         case GWW_HWNDPARENT: return wndPtr->hwndParent;
531         case GWW_HINSTANCE:  return wndPtr->hInstance;
532     }
533     return 0;
534 }
535
536
537 /**********************************************************************
538  *           SetWindowWord    (USER.134)
539  */
540 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
541 {
542     WORD *ptr, retval;
543     WND * wndPtr = WIN_FindWndPtr( hwnd );
544     if (!wndPtr) return 0;
545     if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
546     else switch(offset)
547     {
548         case GWW_ID: ptr = &wndPtr->wIDmenu;
549         case GWW_HINSTANCE: ptr = &wndPtr->hInstance;
550         default: return 0;
551     }
552     retval = *ptr;
553     *ptr = newval;
554     return retval;
555 }
556
557
558 /**********************************************************************
559  *           GetWindowLong    (USER.135)
560  */
561 LONG GetWindowLong( HWND hwnd, short offset )
562 {
563     WND * wndPtr = WIN_FindWndPtr( hwnd );
564     if (!wndPtr) return 0;
565     if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
566     switch(offset)
567     {
568         case GWL_STYLE:   return wndPtr->dwStyle;
569         case GWL_EXSTYLE: return wndPtr->dwExStyle;
570         case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
571     }
572     return 0;
573 }
574
575
576 /**********************************************************************
577  *           SetWindowLong    (USER.136)
578  */
579 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
580 {
581     LONG *ptr, retval;
582     WND * wndPtr = WIN_FindWndPtr( hwnd );
583     if (!wndPtr) return 0;
584     if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
585     else switch(offset)
586     {
587         case GWL_STYLE:   ptr = &wndPtr->dwStyle;
588         case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
589         case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
590         default: return 0;
591     }
592     retval = *ptr;
593     *ptr = newval;
594     return retval;
595 }
596
597
598 /*******************************************************************
599  *         GetWindowText          (USER.36)
600  */
601 int GetWindowText(HWND hwnd, LPSTR lpString, int nMaxCount)
602 {
603     return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount, 
604                                               (DWORD)lpString);
605 }
606
607 /*******************************************************************
608  *         SetWindowText          (USER.37)
609  */
610 void SetWindowText(HWND hwnd, LPSTR lpString)
611 {
612     SendMessage(hwnd, WM_SETTEXT, (WORD)NULL, (DWORD)lpString);
613 }
614
615 /*******************************************************************
616  *         GetWindowTextLength    (USER.38)
617  */
618 int GetWindowTextLength(HWND hwnd)
619 {
620     return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, (WORD)NULL, 
621                                                     (DWORD)NULL);
622 }
623
624
625 /*******************************************************************
626  *         IsWindow    (USER.47)
627  */
628 BOOL IsWindow( HWND hwnd )
629 {
630     WND * wndPtr = WIN_FindWndPtr( hwnd );
631     return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
632 }
633
634
635 /*****************************************************************
636  *         GetParent              (USER.46)
637  */
638 HWND GetParent(HWND hwnd)
639 {
640     WND *wndPtr = WIN_FindWndPtr(hwnd);
641     if (!wndPtr) return 0;
642     return wndPtr->hwndParent;
643 }
644
645
646 /*******************************************************************
647  *         IsChild    (USER.48)
648  */
649 BOOL IsChild( HWND parent, HWND child )
650 {
651     HWND curChild;
652     WND * parentPtr;
653     WND * childPtr;
654
655     if (!(parentPtr = WIN_FindWndPtr( parent ))) return FALSE;
656     curChild = parentPtr->hwndChild;
657
658     while (curChild)
659     {
660         if (curChild == child) return TRUE;
661         if (IsChild( curChild, child )) return TRUE;
662         if (!(childPtr = WIN_FindWndPtr( curChild ))) return FALSE;
663         curChild = childPtr->hwndNext;
664     }    
665     return FALSE;
666 }
667
668
669 /***********************************************************************
670  *           IsWindowVisible   (USER.49)
671  */
672 BOOL IsWindowVisible(HWND hWnd)
673 {
674     WND * wndPtr = WIN_FindWndPtr(hWnd);
675     if (wndPtr == 0) return(FALSE);
676     else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
677 }
678
679  
680  
681 /*******************************************************************
682  *         GetTopWindow    (USER.229)
683  */
684 HWND GetTopWindow( HWND hwnd )
685 {
686     WND * wndPtr = WIN_FindWndPtr( hwnd );
687     if (wndPtr) return wndPtr->hwndChild;
688     else return 0;
689 }
690
691
692 /*******************************************************************
693  *         GetWindow    (USER.262)
694  */
695 HWND GetWindow( HWND hwnd, WORD rel )
696 {
697     WND * wndPtr = WIN_FindWndPtr( hwnd );
698     if (!wndPtr) return 0;
699     switch(rel)
700     {
701     case GW_HWNDFIRST:
702         if (wndPtr->hwndParent)
703         {
704             WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
705             return parentPtr->hwndChild;
706         }
707         else return firstWindow;
708         
709     case GW_HWNDLAST:
710         while (wndPtr->hwndNext)
711         {
712             hwnd = wndPtr->hwndNext;
713             wndPtr = WIN_FindWndPtr( hwnd );
714         }
715         return hwnd;
716         
717     case GW_HWNDNEXT:
718         return wndPtr->hwndNext;
719         
720     case GW_HWNDPREV:   
721         {
722             HWND hwndPrev;
723             
724             if (wndPtr->hwndParent)
725             {
726                 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
727                 hwndPrev = parentPtr->hwndChild;
728             }
729             else hwndPrev = firstWindow;
730             if (hwndPrev == hwnd) return 0;
731             while (hwndPrev)
732             {
733                 wndPtr = WIN_FindWndPtr( hwndPrev );
734                 if (wndPtr->hwndNext == hwnd) break;
735                 hwndPrev = wndPtr->hwndNext;
736             }
737             return hwndPrev;
738         }
739         
740     case GW_OWNER:
741         return wndPtr->hwndOwner;
742
743     case GW_CHILD:
744         return wndPtr->hwndChild;
745     }
746     return 0;
747 }
748
749
750 /*******************************************************************
751  *         GetNextWindow    (USER.230)
752  */
753 HWND GetNextWindow( HWND hwnd, WORD flag )
754 {
755     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
756     return GetWindow( hwnd, flag );
757 }