Release 941030
[wine/multimedia.git] / windows / win.c
blob10236e061e873a70ef0e030793f24511bb1f38d7
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993, 1994";
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "scroll.h"
20 #include "icon.h"
21 #include "cursor.h"
22 #include "stddebug.h"
23 #include "callback.h"
24 /* #define DEBUG_WIN /* */
25 /* #undef DEBUG_WIN /* */
26 /* #define DEBUG_MENU /* */
27 /* #undef DEBUG_MENU /* */
28 #include "debug.h"
30 extern Colormap COLOR_WinColormap;
32 extern void EVENT_RegisterWindow( Window w, HWND hwnd ); /* event.c */
33 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
34 extern LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
35 RECT *newWindowRect, RECT *oldWindowRect,
36 RECT *oldClientRect, WINDOWPOS *winpos,
37 RECT *newClientRect ); /* winpos.c */
39 extern HMENU CopySysMenu(); /* menu.c */
40 extern LONG MDIClientWndProc(HWND hwnd, WORD message,
41 WORD wParam, LONG lParam); /* mdi.c */
44 static HWND hwndDesktop = 0;
45 static HWND hWndSysModal = 0;
47 /***********************************************************************
48 * WIN_FindWndPtr
50 * Return a pointer to the WND structure corresponding to a HWND.
52 WND * WIN_FindWndPtr( HWND hwnd )
54 WND * ptr;
56 if (!hwnd) return NULL;
57 ptr = (WND *) USER_HEAP_ADDR( hwnd );
58 if (IsBadReadPtr(ptr, sizeof *ptr)) return NULL;
59 if (ptr->dwMagic != WND_MAGIC) return NULL;
60 return ptr;
64 /***********************************************************************
65 * WIN_GetXWindow
67 * Return the X window associated to a window.
69 Window WIN_GetXWindow( HWND hwnd )
71 WND *wndPtr = WIN_FindWndPtr( hwnd );
72 while (wndPtr && !wndPtr->window)
74 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
76 return wndPtr ? wndPtr->window : 0;
80 /***********************************************************************
81 * WIN_UnlinkWindow
83 * Remove a window from the siblings linked list.
85 BOOL WIN_UnlinkWindow( HWND hwnd )
87 HWND * curWndPtr;
88 WND *parentPtr, *wndPtr;
90 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
91 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
93 curWndPtr = &parentPtr->hwndChild;
95 while (*curWndPtr != hwnd)
97 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
98 curWndPtr = &curPtr->hwndNext;
100 *curWndPtr = wndPtr->hwndNext;
101 return TRUE;
105 /***********************************************************************
106 * WIN_LinkWindow
108 * Insert a window into the siblings linked list.
109 * The window is inserted after the specified window, which can also
110 * be specified as HWND_TOP or HWND_BOTTOM.
112 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
114 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
115 WND *wndPtr, *parentPtr;
117 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
118 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
120 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
122 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
123 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
124 while (*hwndPtr)
126 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
127 hwndPtr = &nextPtr->hwndNext;
130 else /* Normal case */
132 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
133 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
135 if (!hwndPtr) return FALSE;
136 wndPtr->hwndNext = *hwndPtr;
137 *hwndPtr = hwnd;
138 return TRUE;
142 /***********************************************************************
143 * WIN_FindWinToRepaint
145 * Find a window that needs repaint.
147 HWND WIN_FindWinToRepaint( HWND hwnd )
149 WND * wndPtr;
151 /* Note: the desktop window never gets WM_PAINT messages */
152 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
153 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
155 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
156 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
157 continue;
158 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
159 continue;
160 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
161 return hwnd;
162 if (wndPtr->hwndChild)
164 HWND child;
165 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
166 return child;
169 return 0;
173 /***********************************************************************
174 * WIN_SendParentNotify
176 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
177 * the window has the WS_EX_NOPARENTNOTIFY style.
179 void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam )
181 HWND current = GetParent( hwnd );
182 WND *wndPtr = WIN_FindWndPtr( hwnd );
184 if (!wndPtr || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) return;
185 while (current)
187 SendMessage( current, WM_PARENTNOTIFY, event, lParam );
188 current = GetParent( current );
193 /***********************************************************************
194 * WIN_DestroyWindow
196 * Destroy storage associated to a window
198 static void WIN_DestroyWindow( HWND hwnd )
200 WND *wndPtr = WIN_FindWndPtr( hwnd );
201 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
203 if (!wndPtr || !classPtr) return;
204 wndPtr->dwMagic = 0; /* Mark it as invalid */
205 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
207 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
208 MSG_DecPaintCount( wndPtr->hmemTaskQ );
210 if (!(wndPtr->dwStyle & WS_CHILD))
212 if (wndPtr->wIDmenu) DestroyMenu( wndPtr->wIDmenu );
214 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
215 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
216 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
217 classPtr->cWindows--;
218 USER_HEAP_FREE( hwnd );
222 /***********************************************************************
223 * WIN_CreateDesktopWindow
225 * Create the desktop window.
227 BOOL WIN_CreateDesktopWindow()
229 WND *wndPtr;
230 HCLASS hclass;
231 CLASS *classPtr;
233 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_NAME, &classPtr )))
234 return FALSE;
236 hwndDesktop = USER_HEAP_ALLOC( GMEM_MOVEABLE,
237 sizeof(WND)+classPtr->wc.cbWndExtra );
238 if (!hwndDesktop) return FALSE;
239 wndPtr = (WND *) USER_HEAP_ADDR( hwndDesktop );
241 wndPtr->hwndNext = 0;
242 wndPtr->hwndChild = 0;
243 wndPtr->dwMagic = WND_MAGIC;
244 wndPtr->hwndParent = 0;
245 wndPtr->hwndOwner = 0;
246 wndPtr->hClass = hclass;
247 wndPtr->hInstance = 0;
248 wndPtr->rectWindow.left = 0;
249 wndPtr->rectWindow.top = 0;
250 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
251 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
252 wndPtr->rectClient = wndPtr->rectWindow;
253 wndPtr->rectNormal = wndPtr->rectWindow;
254 wndPtr->ptIconPos.x = -1;
255 wndPtr->ptIconPos.y = -1;
256 wndPtr->ptMaxPos.x = -1;
257 wndPtr->ptMaxPos.y = -1;
258 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
259 wndPtr->hrgnUpdate = 0;
260 wndPtr->hwndLastActive = hwndDesktop;
261 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
262 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
263 wndPtr->dwExStyle = 0;
264 wndPtr->hdce = 0;
265 wndPtr->VScroll = NULL;
266 wndPtr->HScroll = NULL;
267 wndPtr->scroll_flags = 0;
268 wndPtr->wIDmenu = 0;
269 wndPtr->hText = 0;
270 wndPtr->flags = 0;
271 wndPtr->window = rootWindow;
272 wndPtr->hSysMenu = 0;
273 wndPtr->hProp = 0;
274 wndPtr->hTask = 0;
276 /* Send dummy WM_NCCREATE message */
277 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
278 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
279 RedrawWindow( hwndDesktop, NULL, 0,
280 RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
281 return TRUE;
285 /***********************************************************************
286 * CreateWindow (USER.41)
288 HWND CreateWindow( LPSTR className, LPSTR windowName,
289 DWORD style, short x, short y, short width, short height,
290 HWND parent, HMENU menu, HANDLE instance, LPSTR data )
292 return CreateWindowEx( 0, className, windowName, style,
293 x, y, width, height, parent, menu, instance, data );
297 /***********************************************************************
298 * CreateWindowEx (USER.452)
300 HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
301 DWORD style, short x, short y, short width, short height,
302 HWND parent, HMENU menu, HANDLE instance, LPSTR data )
304 HANDLE class, hwnd;
305 CLASS *classPtr;
306 WND *wndPtr;
307 POINT maxSize, maxPos, minTrack, maxTrack;
308 CREATESTRUCT *createStruct;
309 HANDLE hcreateStruct;
310 int wmcreate;
311 XSetWindowAttributes win_attr;
313 dprintf_win(stddeb, "CreateWindowEx: %04X '%s' '%s' %04X %d,%d %dx%d %04X %04X %04X %08X\n",
314 exStyle, className, windowName, style, x, y, width, height,
315 parent, menu, instance, data);
316 /* 'soundrec.exe' has negative position !
317 Why ? For now, here a patch : */
318 if (!strcmp(className, "SoundRec"))
320 if (x < 0) x = 0;
321 if (y < 0) y = 0;
323 if (x == CW_USEDEFAULT) x = y = 0;
324 if (width == CW_USEDEFAULT)
326 width = 600;
327 height = 400;
329 if (width == 0) width = 1;
330 if (height == 0) height = 1;
332 /* Find the parent and class */
334 if (parent)
336 /* Make sure parent is valid */
337 if (!IsWindow( parent )) return 0;
339 else if (style & WS_CHILD) return 0; /* WS_CHILD needs a parent */
341 if (!(class = CLASS_FindClassByName( className, &classPtr ))) {
342 fprintf(stderr,"CreateWindow BAD CLASSNAME '%s' !\n", className);
343 return 0;
346 /* Correct the window style */
348 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
349 style |= WS_CAPTION | WS_CLIPSIBLINGS;
350 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
352 /* Create the window structure */
354 hwnd = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra);
355 if (!hwnd) return 0;
357 /* Fill the structure */
359 wndPtr = (WND *) USER_HEAP_ADDR( hwnd );
360 wndPtr->hwndNext = 0;
361 wndPtr->hwndChild = 0;
362 wndPtr->window = 0;
363 wndPtr->dwMagic = WND_MAGIC;
364 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
365 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : parent;
366 wndPtr->hClass = class;
367 wndPtr->hInstance = instance;
368 wndPtr->rectWindow.left = x;
369 wndPtr->rectWindow.top = y;
370 wndPtr->rectWindow.right = x + width;
371 wndPtr->rectWindow.bottom = y + height;
372 wndPtr->rectClient = wndPtr->rectWindow;
373 wndPtr->rectNormal = wndPtr->rectWindow;
374 wndPtr->ptIconPos.x = -1;
375 wndPtr->ptIconPos.y = -1;
376 wndPtr->ptMaxPos.x = -1;
377 wndPtr->ptMaxPos.y = -1;
378 wndPtr->hmemTaskQ = GetTaskQueue(0);
379 wndPtr->hrgnUpdate = 0;
380 wndPtr->hwndPrevActive = 0;
381 wndPtr->hwndLastActive = hwnd;
382 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
383 wndPtr->dwStyle = style;
384 wndPtr->dwExStyle = exStyle;
385 wndPtr->wIDmenu = 0;
386 wndPtr->hText = 0;
387 wndPtr->flags = 0;
388 wndPtr->VScroll = NULL;
389 wndPtr->HScroll = NULL;
390 wndPtr->scroll_flags = 0;
391 wndPtr->hSysMenu = 0;
392 wndPtr->hProp = 0;
393 wndPtr->hTask = 0;
395 if (classPtr->wc.cbWndExtra)
396 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
397 classPtr->cWindows++;
399 /* Make sure owner is a top-level window */
401 while (wndPtr->hwndOwner && GetParent(wndPtr->hwndOwner))
402 wndPtr->hwndOwner = GetParent(wndPtr->hwndOwner);
404 /* Get class or window DC if needed */
406 if (classPtr->wc.style & CS_OWNDC)
407 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
408 else if (classPtr->wc.style & CS_CLASSDC)
409 wndPtr->hdce = classPtr->hdce;
410 else
411 wndPtr->hdce = 0;
413 /* Insert the window in the linked list */
415 WIN_LinkWindow( hwnd, HWND_TOP );
417 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
419 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
421 if ( maxSize.x < width)
423 width = maxSize.x;
424 wndPtr->rectWindow.right = x + width;
426 if ( maxSize.y < height)
428 height = maxSize.y;
429 wndPtr->rectWindow.bottom = y + height;
432 /* Create the X window (only for top-level windows, and then only */
433 /* when there's no desktop window) */
435 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
437 CURSORALLOC *cursor;
438 HCURSOR hCursor = classPtr->wc.hCursor;
439 if (!hCursor) hCursor = LoadCursor( 0, IDC_ARROW );
440 cursor = (CURSORALLOC *) GlobalLock(hCursor);
442 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
443 PointerMotionMask | ButtonPressMask |
444 ButtonReleaseMask | FocusChangeMask;
445 win_attr.override_redirect = TRUE;
446 win_attr.colormap = COLOR_WinColormap;
447 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
448 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
449 win_attr.cursor = cursor ? cursor->xcursor : None;
450 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
451 width, height, 0, CopyFromParent,
452 InputOutput, CopyFromParent,
453 CWEventMask | CWOverrideRedirect |
454 CWColormap | CWCursor | CWSaveUnder |
455 CWBackingStore, &win_attr );
456 XStoreName( display, wndPtr->window, windowName );
457 EVENT_RegisterWindow( wndPtr->window, hwnd );
458 GlobalUnlock( hCursor );
461 dprintf_menu(stddeb,"CreateWindowEx // menu=%04X instance=%04X classmenu=%08X !\n",
462 menu, instance, classPtr->wc.lpszMenuName);
464 if ((style & WS_CAPTION) && (style & WS_CHILD) == 0) {
465 if (menu != 0)
466 SetMenu(hwnd, menu);
467 else {
468 if (classPtr->wc.lpszMenuName != NULL)
469 SetMenu(hwnd, LoadMenu(instance, classPtr->wc.lpszMenuName));
472 else
473 wndPtr->wIDmenu = menu;
475 /* Send the WM_CREATE message */
477 hcreateStruct = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
478 createStruct = (CREATESTRUCT *) USER_HEAP_ADDR( hcreateStruct );
479 createStruct->lpCreateParams = data;
480 createStruct->hInstance = instance;
481 createStruct->hMenu = menu;
482 createStruct->hwndParent = parent;
483 createStruct->cx = width;
484 createStruct->cy = height;
485 createStruct->x = x;
486 createStruct->y = y;
487 createStruct->style = style;
488 createStruct->lpszName = windowName;
489 createStruct->lpszClass = className;
490 createStruct->dwExStyle = 0;
492 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
493 if (!wmcreate) wmcreate = -1;
494 else
496 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
497 NULL, NULL, NULL, &wndPtr->rectClient );
498 wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
501 USER_HEAP_FREE( hcreateStruct );
503 if (wmcreate == -1)
505 /* Abort window creation */
506 WIN_DestroyWindow( hwnd );
507 return 0;
510 /* Create a copy of SysMenu */
511 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
513 /* Register window in current task windows list */
514 AddWindowToTask(GetCurrentTask(), hwnd);
516 WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
518 if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
519 /* if (style & WS_MINIMIZE) ShowWindow( hwnd, SW_MINIMIZE ); */
521 dprintf_win(stddeb, "CreateWindowEx: return %04X \n", hwnd);
522 return hwnd;
526 /***********************************************************************
527 * DestroyWindow (USER.53)
529 BOOL DestroyWindow( HWND hwnd )
531 WND * wndPtr;
532 CLASS * classPtr;
534 dprintf_win(stddeb, "DestroyWindow (%04x)\n", hwnd);
536 /* Initialisation */
538 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
539 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
540 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
542 /* Hide the window */
544 if (wndPtr->dwStyle & WS_VISIBLE)
545 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
546 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
547 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
548 ReleaseCapture();
549 WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
551 /* Send destroy messages and destroy children */
553 SendMessage( hwnd, WM_DESTROY, 0, 0 );
554 while (wndPtr->hwndChild) /* The child removes itself from the list */
555 DestroyWindow( wndPtr->hwndChild );
556 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
558 /* Remove the window from current task windows list */
559 RemoveWindowFromTask(GetCurrentTask(), hwnd);
561 /* Remove the window from the linked list */
562 WIN_UnlinkWindow( hwnd );
564 /* Destroy the window */
566 WIN_DestroyWindow( hwnd );
567 return TRUE;
571 /***********************************************************************
572 * CloseWindow (USER.43)
574 void CloseWindow(HWND hWnd)
576 WND * wndPtr = WIN_FindWndPtr(hWnd);
577 if (wndPtr->dwStyle & WS_CHILD) return;
578 ShowWindow(hWnd, SW_MINIMIZE);
583 /***********************************************************************
584 * OpenIcon (USER.44)
586 BOOL OpenIcon(HWND hWnd)
588 if (!IsIconic(hWnd)) return FALSE;
589 ShowWindow(hWnd, SW_SHOWNORMAL);
590 return(TRUE);
595 /***********************************************************************
596 * FindWindow (USER.50)
598 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
600 HCLASS hclass;
601 CLASS *classPtr;
602 HWND hwnd;
604 if (ClassMatch)
606 hclass = CLASS_FindClassByName( ClassMatch, &classPtr );
607 if (!hclass) return 0;
609 else hclass = 0;
611 hwnd = GetTopWindow( hwndDesktop );
612 while(hwnd)
614 WND *wndPtr = WIN_FindWndPtr( hwnd );
615 if (!hclass || (wndPtr->hClass == hclass))
617 /* Found matching class */
618 if (!TitleMatch) return hwnd;
619 if (wndPtr->hText)
621 char *textPtr = (char *) USER_HEAP_ADDR( wndPtr->hText );
622 if (!strcmp( textPtr, TitleMatch )) return hwnd;
625 hwnd = wndPtr->hwndNext;
627 return 0;
631 /**********************************************************************
632 * GetDesktopWindow (USER.286)
633 * GetDeskTopHwnd (USER.278)
635 HWND GetDesktopWindow(void)
637 return hwndDesktop;
641 /*******************************************************************
642 * EnableWindow (USER.34)
644 BOOL EnableWindow( HWND hwnd, BOOL enable )
646 WND *wndPtr;
648 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
649 if (enable && (wndPtr->dwStyle & WS_DISABLED))
651 /* Enable window */
652 wndPtr->dwStyle &= ~WS_DISABLED;
653 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
654 return TRUE;
656 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
658 /* Disable window */
659 wndPtr->dwStyle |= WS_DISABLED;
660 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
661 SetFocus( 0 ); /* A disabled window can't have the focus */
662 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
663 ReleaseCapture(); /* A disabled window can't capture the mouse */
664 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
665 return FALSE;
667 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
671 /***********************************************************************
672 * IsWindowEnabled (USER.35)
674 BOOL IsWindowEnabled(HWND hWnd)
676 WND * wndPtr;
678 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
679 return !(wndPtr->dwStyle & WS_DISABLED);
683 /**********************************************************************
684 * GetWindowWord (USER.133)
686 WORD GetWindowWord( HWND hwnd, short offset )
688 WND * wndPtr = WIN_FindWndPtr( hwnd );
689 if (!wndPtr) return 0;
690 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
691 switch(offset)
693 case GWW_ID: return wndPtr->wIDmenu;
694 case GWW_HWNDPARENT: return wndPtr->hwndParent;
695 case GWW_HINSTANCE: return wndPtr->hInstance;
697 return 0;
701 /**********************************************************************
702 * SetWindowWord (USER.134)
704 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
706 WORD *ptr, retval;
707 WND * wndPtr = WIN_FindWndPtr( hwnd );
708 if (!wndPtr) return 0;
709 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
710 else switch(offset)
712 case GWW_ID: ptr = &wndPtr->wIDmenu;
713 case GWW_HINSTANCE: ptr = &wndPtr->hInstance;
714 default: return 0;
716 retval = *ptr;
717 *ptr = newval;
718 return retval;
722 /**********************************************************************
723 * GetWindowLong (USER.135)
725 LONG GetWindowLong( HWND hwnd, short offset )
727 WND * wndPtr = WIN_FindWndPtr( hwnd );
728 if (!wndPtr) return 0;
729 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
730 switch(offset)
732 case GWL_STYLE: return wndPtr->dwStyle;
733 case GWL_EXSTYLE: return wndPtr->dwExStyle;
734 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
736 return 0;
740 /**********************************************************************
741 * SetWindowLong (USER.136)
743 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
745 LONG *ptr, retval;
746 WND * wndPtr = WIN_FindWndPtr( hwnd );
747 if (!wndPtr) return 0;
748 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
749 else switch(offset)
751 case GWL_STYLE: ptr = &wndPtr->dwStyle;
752 break;
753 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
754 break;
755 case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
756 break;
757 default: return 0;
759 retval = *ptr;
760 *ptr = newval;
761 return retval;
765 /*******************************************************************
766 * GetWindowText (USER.36)
768 int GetWindowText(HWND hwnd, LPSTR lpString, int nMaxCount)
770 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
771 (DWORD)lpString);
774 /*******************************************************************
775 * SetWindowText (USER.37)
777 void SetWindowText(HWND hwnd, LPSTR lpString)
779 SendMessage(hwnd, WM_SETTEXT, (WORD)NULL, (DWORD)lpString);
782 /*******************************************************************
783 * GetWindowTextLength (USER.38)
785 int GetWindowTextLength(HWND hwnd)
787 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, (WORD)NULL,
788 (DWORD)NULL);
792 /*******************************************************************
793 * IsWindow (USER.47)
795 BOOL IsWindow( HWND hwnd )
797 WND * wndPtr = WIN_FindWndPtr( hwnd );
798 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
802 /*****************************************************************
803 * GetParent (USER.46)
805 HWND GetParent(HWND hwnd)
807 WND *wndPtr = WIN_FindWndPtr(hwnd);
808 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
809 return wndPtr->hwndParent;
812 /*****************************************************************
813 * SetParent (USER.233)
815 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
817 HWND temp;
819 WND *wndPtr = WIN_FindWndPtr(hwndChild);
820 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
822 temp = wndPtr->hwndParent;
824 if (hwndNewParent)
825 wndPtr->hwndParent = hwndNewParent;
826 else
827 wndPtr->hwndParent = GetDesktopWindow();
829 return temp;
834 /*******************************************************************
835 * IsChild (USER.48)
837 BOOL IsChild( HWND parent, HWND child )
839 WND * wndPtr = WIN_FindWndPtr( child );
840 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
842 if (wndPtr->hwndParent == parent) return TRUE;
843 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
845 return FALSE;
849 /***********************************************************************
850 * IsWindowVisible (USER.49)
852 BOOL IsWindowVisible(HWND hWnd)
854 WND * wndPtr = WIN_FindWndPtr(hWnd);
855 if (wndPtr == 0) return(FALSE);
856 else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
861 /*******************************************************************
862 * GetTopWindow (USER.229)
864 HWND GetTopWindow( HWND hwnd )
866 WND * wndPtr = WIN_FindWndPtr( hwnd );
867 if (wndPtr) return wndPtr->hwndChild;
868 else return 0;
872 /*******************************************************************
873 * GetWindow (USER.262)
875 HWND GetWindow( HWND hwnd, WORD rel )
877 WND * wndPtr = WIN_FindWndPtr( hwnd );
878 if (!wndPtr) return 0;
879 switch(rel)
881 case GW_HWNDFIRST:
882 if (wndPtr->hwndParent)
884 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
885 return parentPtr->hwndChild;
887 else return 0;
889 case GW_HWNDLAST:
890 if (!wndPtr->hwndParent) return 0; /* Desktop window */
891 while (wndPtr->hwndNext)
893 hwnd = wndPtr->hwndNext;
894 wndPtr = WIN_FindWndPtr( hwnd );
896 return hwnd;
898 case GW_HWNDNEXT:
899 return wndPtr->hwndNext;
901 case GW_HWNDPREV:
903 HWND hwndPrev;
905 if (wndPtr->hwndParent)
907 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
908 hwndPrev = parentPtr->hwndChild;
910 else return 0; /* Desktop window */
911 if (hwndPrev == hwnd) return 0;
912 while (hwndPrev)
914 wndPtr = WIN_FindWndPtr( hwndPrev );
915 if (wndPtr->hwndNext == hwnd) break;
916 hwndPrev = wndPtr->hwndNext;
918 return hwndPrev;
921 case GW_OWNER:
922 return wndPtr->hwndOwner;
924 case GW_CHILD:
925 return wndPtr->hwndChild;
927 return 0;
931 /*******************************************************************
932 * GetNextWindow (USER.230)
934 HWND GetNextWindow( HWND hwnd, WORD flag )
936 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
937 return GetWindow( hwnd, flag );
942 /*******************************************************************
943 * GetLastActivePopup (USER.287)
945 HWND GetLastActivePopup(HWND hwnd)
947 WND *wndPtr;
948 wndPtr = WIN_FindWndPtr(hwnd);
949 if (wndPtr == NULL) return hwnd;
950 return wndPtr->hwndLastActive;
954 /*******************************************************************
955 * EnumWindows (USER.54)
957 * o gets the desktop window and iterates over all the windows
958 * which are direct decendents of the desktop * by iterating over
959 * the desktop's child window and all the child windows next
960 * pointers
962 * o call wndenumprc for every child window the desktop has
963 * (parameters to Callback16 passed backwards so they are
964 * put in in pascal calling order)
966 * o if wndenumprc returns 0 exit
969 BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
971 HWND hwnd = GetTopWindow( GetDesktopWindow() );
972 WND *wndPtr;
973 int result;
975 dprintf_enum(stddeb,"EnumWindows\n");
977 while (hwnd) {
978 char *ptr;
980 if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
981 return 0;
983 #ifdef WINELIB
984 (*wndenumprc)(hwnd, lParam);
985 #else
986 result = CallBack16(wndenumprc, 2,
987 CALLBACK_SIZE_WORD, (int) hwnd,
988 CALLBACK_SIZE_LONG, lParam);
989 #endif
990 if ( ! result ) {
991 return 0;
993 hwnd=wndPtr->hwndNext;
995 return 1; /* for now */
998 /*******************************************************************
999 * WIN_EnumChildWin
1001 * o hwnd is the first child to use, loop until all next windows
1002 * are processed
1004 * o call wdnenumprc with parameters in inverse order (pascal)
1006 * o call ourselves with the next child window
1009 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1011 WND *wndPtr;
1012 int result;
1015 while (hwnd) {
1016 char *ptr;
1017 if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
1018 return 0;
1020 #ifdef WINELIB
1021 if (!(*wndenumprc)( 2, lParam, (int) hwnd)) {
1022 #else
1023 if (!CallBack16(wndenumprc, 2,
1024 CALLBACK_SIZE_WORD, (int) hwnd,
1025 CALLBACK_SIZE_LONG, lParam)) {
1026 #endif
1027 return 0;
1029 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
1030 return 0;
1032 hwnd=wndPtr->hwndNext;
1034 return 1;
1037 /*******************************************************************
1038 * EnumChildWindows (USER.55)
1040 * o gets the first child of hwnd
1042 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1044 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1046 WND *wndPtr;
1048 dprintf_enum(stddeb,"EnumChildWindows\n");
1050 if (hwnd == 0) return 0;
1051 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1052 hwnd = wndPtr->hwndChild;
1053 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1056 /*******************************************************************
1057 * AnyPopup [USER.52]
1059 BOOL AnyPopup()
1061 dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
1062 return FALSE;
1065 /*******************************************************************
1066 * FlashWindow [USER.105]
1068 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1070 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1071 return FALSE;
1075 /*******************************************************************
1076 * SetSysModalWindow [USER.188]
1078 HWND SetSysModalWindow(HWND hWnd)
1080 HWND hWndOldModal = hWndSysModal;
1081 hWndSysModal = hWnd;
1082 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04X) !\n", hWnd);
1083 return hWndOldModal;
1087 /*******************************************************************
1088 * GetSysModalWindow [USER.189]
1090 HWND GetSysModalWindow(void)
1092 return hWndSysModal;