Release 950522
[wine.git] / windows / win.c
blob29dc18a798b81d6632c26a9888be18780ff4946d
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "menu.h"
17 #include "icon.h"
18 #include "cursor.h"
19 #include "event.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "winpos.h"
23 #include "color.h"
24 #include "callback.h"
25 #include "stddebug.h"
26 /* #define DEBUG_WIN */
27 /* #define DEBUG_MENU */
28 #include "debug.h"
30 static HWND hwndDesktop = 0;
31 static HWND hWndSysModal = 0;
33 /***********************************************************************
34 * WIN_FindWndPtr
36 * Return a pointer to the WND structure corresponding to a HWND.
38 WND * WIN_FindWndPtr( HWND hwnd )
40 WND * ptr;
42 if (!hwnd) return NULL;
43 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
44 if (ptr->dwMagic != WND_MAGIC) return NULL;
45 return ptr;
49 /***********************************************************************
50 * WIN_GetXWindow
52 * Return the X window associated to a window.
54 Window WIN_GetXWindow( HWND hwnd )
56 WND *wndPtr = WIN_FindWndPtr( hwnd );
57 while (wndPtr && !wndPtr->window)
59 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
61 return wndPtr ? wndPtr->window : 0;
65 /***********************************************************************
66 * WIN_UnlinkWindow
68 * Remove a window from the siblings linked list.
70 BOOL WIN_UnlinkWindow( HWND hwnd )
72 HWND * curWndPtr;
73 WND *parentPtr, *wndPtr;
75 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
76 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
78 curWndPtr = &parentPtr->hwndChild;
80 while (*curWndPtr != hwnd)
82 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
83 curWndPtr = &curPtr->hwndNext;
85 *curWndPtr = wndPtr->hwndNext;
86 return TRUE;
90 /***********************************************************************
91 * WIN_LinkWindow
93 * Insert a window into the siblings linked list.
94 * The window is inserted after the specified window, which can also
95 * be specified as HWND_TOP or HWND_BOTTOM.
97 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
99 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
100 WND *wndPtr, *parentPtr;
102 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
103 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
105 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
107 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
108 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
109 while (*hwndPtr)
111 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
112 hwndPtr = &nextPtr->hwndNext;
115 else /* Normal case */
117 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
118 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
120 if (!hwndPtr) return FALSE;
121 wndPtr->hwndNext = *hwndPtr;
122 *hwndPtr = hwnd;
123 return TRUE;
127 /***********************************************************************
128 * WIN_FindWinToRepaint
130 * Find a window that needs repaint.
132 HWND WIN_FindWinToRepaint( HWND hwnd )
134 WND * wndPtr;
136 /* Note: the desktop window never gets WM_PAINT messages */
137 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
138 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
140 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
141 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
142 continue;
143 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
144 continue;
145 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
146 return hwnd;
147 if (wndPtr->hwndChild)
149 HWND child;
150 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
151 return child;
154 return 0;
158 /***********************************************************************
159 * WIN_SendParentNotify
161 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
162 * the window has the WS_EX_NOPARENTNOTIFY style.
164 void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam )
166 HWND current = GetParent( hwnd );
167 WND *wndPtr = WIN_FindWndPtr( hwnd );
169 if (!wndPtr || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) return;
170 while (current)
172 SendMessage( current, WM_PARENTNOTIFY, event, lParam );
173 current = GetParent( current );
178 /***********************************************************************
179 * WIN_DestroyWindow
181 * Destroy storage associated to a window
183 static void WIN_DestroyWindow( HWND hwnd )
185 WND *wndPtr = WIN_FindWndPtr( hwnd );
186 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
188 if (!wndPtr || !classPtr) return;
189 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
190 wndPtr->dwMagic = 0; /* Mark it as invalid */
191 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
193 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
194 MSG_DecPaintCount( wndPtr->hmemTaskQ );
196 if (!(wndPtr->dwStyle & WS_CHILD))
198 if (wndPtr->wIDmenu) DestroyMenu( wndPtr->wIDmenu );
200 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
201 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
202 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
203 classPtr->cWindows--;
204 USER_HEAP_FREE( hwnd );
208 /***********************************************************************
209 * WIN_CreateDesktopWindow
211 * Create the desktop window.
213 BOOL WIN_CreateDesktopWindow()
215 WND *wndPtr;
216 HCLASS hclass;
217 CLASS *classPtr;
218 HDC hdc;
220 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_NAME, 0, &classPtr )))
221 return FALSE;
223 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
224 if (!hwndDesktop) return FALSE;
225 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
227 wndPtr->hwndNext = 0;
228 wndPtr->hwndChild = 0;
229 wndPtr->dwMagic = WND_MAGIC;
230 wndPtr->hwndParent = 0;
231 wndPtr->hwndOwner = 0;
232 wndPtr->hClass = hclass;
233 wndPtr->hInstance = 0;
234 wndPtr->rectWindow.left = 0;
235 wndPtr->rectWindow.top = 0;
236 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
237 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
238 wndPtr->rectClient = wndPtr->rectWindow;
239 wndPtr->rectNormal = wndPtr->rectWindow;
240 wndPtr->ptIconPos.x = -1;
241 wndPtr->ptIconPos.y = -1;
242 wndPtr->ptMaxPos.x = -1;
243 wndPtr->ptMaxPos.y = -1;
244 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
245 wndPtr->hrgnUpdate = 0;
246 wndPtr->hwndLastActive = hwndDesktop;
247 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
248 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
249 wndPtr->dwExStyle = 0;
250 wndPtr->hdce = 0;
251 wndPtr->hVScroll = 0;
252 wndPtr->hHScroll = 0;
253 wndPtr->wIDmenu = 0;
254 wndPtr->hText = 0;
255 wndPtr->flags = 0;
256 wndPtr->window = rootWindow;
257 wndPtr->hSysMenu = 0;
258 wndPtr->hProp = 0;
259 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
260 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
261 if ((hdc = GetDC( hwndDesktop )) != 0)
263 SendMessage( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
264 ReleaseDC( hwndDesktop, hdc );
266 return TRUE;
270 /***********************************************************************
271 * CreateWindow (USER.41)
273 HWND CreateWindow( LPSTR className, LPSTR windowName,
274 DWORD style, short x, short y, short width, short height,
275 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
277 return CreateWindowEx( 0, className, windowName, style,
278 x, y, width, height, parent, menu, instance, data );
282 /***********************************************************************
283 * CreateWindowEx (USER.452)
285 HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
286 DWORD style, short x, short y, short width, short height,
287 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
289 HANDLE class, hwnd;
290 CLASS *classPtr;
291 WND *wndPtr;
292 POINT maxSize, maxPos, minTrack, maxTrack;
293 CREATESTRUCT createStruct;
294 HANDLE hwinName, hclassName;
295 int wmcreate;
296 XSetWindowAttributes win_attr;
298 dprintf_win(stddeb, "CreateWindowEx: %08lX '%s' '%s' %08lX %d,%d %dx%d %04X %04X %04X %08lx\n",
299 exStyle, className, windowName, style, x, y, width, height,
300 parent, menu, instance, data);
301 /* 'soundrec.exe' has negative position !
302 Why ? For now, here a patch : */
303 if (!strcmp(className, "SoundRec"))
305 if (x < 0) x = 0;
306 if (y < 0) y = 0;
308 if (x == CW_USEDEFAULT) x = y = 0;
309 if (width == CW_USEDEFAULT)
311 width = 600;
312 height = 400;
314 if (width == 0) width = 1;
315 if (height == 0) height = 1;
317 /* Find the parent and class */
319 if (parent)
321 /* Make sure parent is valid */
322 if (!IsWindow( parent )) {
323 dprintf_win(stddeb,"CreateWindowEx: Parent %x is not a windows\n", parent);
324 return 0;
327 else if (style & WS_CHILD) {
328 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
329 return 0; /* WS_CHILD needs a parent */
332 if (!(class = CLASS_FindClassByName( className, instance, &classPtr ))) {
333 fprintf(stderr,"CreateWindow BAD CLASSNAME '%s' !\n", className);
334 return 0;
337 /* Correct the window style */
339 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
340 style |= WS_CAPTION | WS_CLIPSIBLINGS;
341 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
343 /* Create the window structure */
345 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
346 if (!hwnd) {
347 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
348 return 0;
351 /* Fill the structure */
353 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
354 wndPtr->hwndNext = 0;
355 wndPtr->hwndChild = 0;
356 wndPtr->window = 0;
357 wndPtr->dwMagic = WND_MAGIC;
358 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
359 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : parent;
360 wndPtr->hClass = class;
361 wndPtr->hInstance = instance;
362 wndPtr->rectWindow.left = x;
363 wndPtr->rectWindow.top = y;
364 wndPtr->rectWindow.right = x + width;
365 wndPtr->rectWindow.bottom = y + height;
366 wndPtr->rectClient = wndPtr->rectWindow;
367 wndPtr->rectNormal = wndPtr->rectWindow;
368 wndPtr->ptIconPos.x = -1;
369 wndPtr->ptIconPos.y = -1;
370 wndPtr->ptMaxPos.x = -1;
371 wndPtr->ptMaxPos.y = -1;
372 wndPtr->hmemTaskQ = GetTaskQueue(0);
373 wndPtr->hrgnUpdate = 0;
374 wndPtr->hwndPrevActive = 0;
375 wndPtr->hwndLastActive = hwnd;
376 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
377 wndPtr->dwStyle = style;
378 wndPtr->dwExStyle = exStyle;
379 wndPtr->wIDmenu = 0;
380 wndPtr->hText = 0;
381 wndPtr->flags = 0;
382 wndPtr->hVScroll = 0;
383 wndPtr->hHScroll = 0;
384 wndPtr->hSysMenu = 0;
385 wndPtr->hProp = 0;
387 if (classPtr->wc.cbWndExtra)
388 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
389 classPtr->cWindows++;
391 /* Make sure owner is a top-level window */
393 while (wndPtr->hwndOwner && GetParent(wndPtr->hwndOwner))
394 wndPtr->hwndOwner = GetParent(wndPtr->hwndOwner);
396 /* Get class or window DC if needed */
398 if (classPtr->wc.style & CS_OWNDC)
399 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
400 else if (classPtr->wc.style & CS_CLASSDC)
401 wndPtr->hdce = classPtr->hdce;
402 else
403 wndPtr->hdce = 0;
405 /* Insert the window in the linked list */
407 WIN_LinkWindow( hwnd, HWND_TOP );
409 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
411 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
413 if ( maxSize.x < width)
415 width = maxSize.x;
416 wndPtr->rectWindow.right = x + width;
418 if ( maxSize.y < height)
420 height = maxSize.y;
421 wndPtr->rectWindow.bottom = y + height;
424 /* Create the X window (only for top-level windows, and then only */
425 /* when there's no desktop window) */
427 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
429 CURSORALLOC *cursor;
430 HCURSOR hCursor = classPtr->wc.hCursor;
431 if (!hCursor) hCursor = LoadCursor( 0, IDC_ARROW );
432 cursor = (CURSORALLOC *) GlobalLock(hCursor);
434 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
435 PointerMotionMask | ButtonPressMask |
436 ButtonReleaseMask | FocusChangeMask;
437 win_attr.override_redirect = TRUE;
438 win_attr.colormap = COLOR_WinColormap;
439 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
440 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
441 win_attr.cursor = cursor ? cursor->xcursor : None;
442 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
443 width, height, 0, CopyFromParent,
444 InputOutput, CopyFromParent,
445 CWEventMask | CWOverrideRedirect |
446 CWColormap | CWCursor | CWSaveUnder |
447 CWBackingStore, &win_attr );
448 XStoreName( display, wndPtr->window, windowName );
449 EVENT_RegisterWindow( wndPtr->window, hwnd );
450 GlobalUnlock( hCursor );
453 if ((style & WS_CAPTION) && !(style & WS_CHILD))
455 if (menu) SetMenu(hwnd, menu);
456 else if (classPtr->wc.lpszMenuName)
457 SetMenu(hwnd,LoadMenu(instance,(SEGPTR)classPtr->wc.lpszMenuName));
459 else wndPtr->wIDmenu = menu;
461 /* Send the WM_CREATE message */
463 hclassName = USER_HEAP_ALLOC( strlen(className)+1 );
464 strcpy( USER_HEAP_LIN_ADDR(hclassName), className );
465 createStruct.lpCreateParams = (LPSTR)data;
466 createStruct.hInstance = instance;
467 createStruct.hMenu = menu;
468 createStruct.hwndParent = parent;
469 createStruct.cx = width;
470 createStruct.cy = height;
471 createStruct.x = x;
472 createStruct.y = y;
473 createStruct.style = style;
474 createStruct.lpszClass = (LPSTR)USER_HEAP_SEG_ADDR(hclassName);
475 createStruct.dwExStyle = 0;
476 if (windowName)
478 hwinName = USER_HEAP_ALLOC( strlen(windowName)+1 );
479 strcpy( USER_HEAP_LIN_ADDR(hwinName), windowName );
480 createStruct.lpszName = (LPSTR)USER_HEAP_SEG_ADDR(hwinName);
482 else
484 hwinName = 0;
485 createStruct.lpszName = NULL;
488 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, MAKE_SEGPTR(&createStruct) );
489 if (!wmcreate) {
490 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
491 wmcreate = -1;
493 else
495 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
496 NULL, NULL, NULL, &wndPtr->rectClient );
497 wmcreate = SendMessage(hwnd, WM_CREATE, 0, MAKE_SEGPTR(&createStruct));
500 USER_HEAP_FREE( hclassName );
501 if (hwinName) USER_HEAP_FREE( hwinName );
503 if (wmcreate == -1)
505 /* Abort window creation */
506 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
507 WIN_DestroyWindow( hwnd );
508 return 0;
511 /* Create a copy of SysMenu */
512 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
514 WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
516 if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
517 /* if (style & WS_MINIMIZE) ShowWindow( hwnd, SW_MINIMIZE ); */
519 dprintf_win(stddeb, "CreateWindowEx: return %04X \n", hwnd);
520 return hwnd;
524 /***********************************************************************
525 * DestroyWindow (USER.53)
527 BOOL DestroyWindow( HWND hwnd )
529 WND * wndPtr;
530 CLASS * classPtr;
532 dprintf_win(stddeb, "DestroyWindow (%04x)\n", hwnd);
534 /* Initialisation */
536 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
537 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
538 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
540 /* Hide the window */
542 if (wndPtr->dwStyle & WS_VISIBLE)
543 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
544 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
545 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
546 ReleaseCapture();
547 WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
549 /* Recursively destroy owned windows */
551 for (;;)
553 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
554 while (hwndSibling)
556 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
557 if (siblingPtr->hwndOwner == hwnd) break;
558 hwndSibling = siblingPtr->hwndNext;
560 if (hwndSibling) DestroyWindow( hwndSibling );
561 else break;
564 /* Send destroy messages and destroy children */
566 SendMessage( hwnd, WM_DESTROY, 0, 0 );
567 while (wndPtr->hwndChild) /* The child removes itself from the list */
568 DestroyWindow( wndPtr->hwndChild );
569 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
571 /* Destroy the window */
573 WIN_DestroyWindow( hwnd );
574 return TRUE;
578 /***********************************************************************
579 * CloseWindow (USER.43)
581 void CloseWindow(HWND hWnd)
583 WND * wndPtr = WIN_FindWndPtr(hWnd);
584 if (wndPtr->dwStyle & WS_CHILD) return;
585 ShowWindow(hWnd, SW_MINIMIZE);
589 /***********************************************************************
590 * OpenIcon (USER.44)
592 BOOL OpenIcon(HWND hWnd)
594 if (!IsIconic(hWnd)) return FALSE;
595 ShowWindow(hWnd, SW_SHOWNORMAL);
596 return(TRUE);
600 /***********************************************************************
601 * FindWindow (USER.50)
603 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
605 HCLASS hclass;
606 CLASS *classPtr;
607 HWND hwnd;
609 if (ClassMatch)
611 hclass = CLASS_FindClassByName( ClassMatch, 0xffff, &classPtr );
612 if (!hclass) return 0;
614 else hclass = 0;
616 hwnd = GetTopWindow( hwndDesktop );
617 while(hwnd)
619 WND *wndPtr = WIN_FindWndPtr( hwnd );
620 if (!hclass || (wndPtr->hClass == hclass))
622 /* Found matching class */
623 if (!TitleMatch) return hwnd;
624 if (wndPtr->hText)
626 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
627 if (!strcmp( textPtr, TitleMatch )) return hwnd;
630 hwnd = wndPtr->hwndNext;
632 return 0;
636 /**********************************************************************
637 * GetDesktopWindow (USER.286)
638 * GetDeskTopHwnd (USER.278)
640 HWND GetDesktopWindow(void)
642 return hwndDesktop;
646 /*******************************************************************
647 * EnableWindow (USER.34)
649 BOOL EnableWindow( HWND hwnd, BOOL enable )
651 WND *wndPtr;
653 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
654 if (enable && (wndPtr->dwStyle & WS_DISABLED))
656 /* Enable window */
657 wndPtr->dwStyle &= ~WS_DISABLED;
658 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
659 return TRUE;
661 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
663 /* Disable window */
664 wndPtr->dwStyle |= WS_DISABLED;
665 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
666 SetFocus( 0 ); /* A disabled window can't have the focus */
667 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
668 ReleaseCapture(); /* A disabled window can't capture the mouse */
669 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
670 return FALSE;
672 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
676 /***********************************************************************
677 * IsWindowEnabled (USER.35)
679 BOOL IsWindowEnabled(HWND hWnd)
681 WND * wndPtr;
683 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
684 return !(wndPtr->dwStyle & WS_DISABLED);
688 /**********************************************************************
689 * GetWindowWord (USER.133)
691 WORD GetWindowWord( HWND hwnd, short offset )
693 WND * wndPtr = WIN_FindWndPtr( hwnd );
694 if (!wndPtr) return 0;
695 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
696 switch(offset)
698 case GWW_ID: return wndPtr->wIDmenu;
699 case GWW_HWNDPARENT: return wndPtr->hwndParent;
700 case GWW_HINSTANCE: return wndPtr->hInstance;
702 return 0;
706 /**********************************************************************
707 * SetWindowWord (USER.134)
709 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
711 WORD *ptr, retval;
712 WND * wndPtr = WIN_FindWndPtr( hwnd );
713 if (!wndPtr) return 0;
714 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
715 else switch(offset)
717 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
718 case GWW_HINSTANCE: ptr = &wndPtr->hInstance; break;
719 default: return 0;
721 retval = *ptr;
722 *ptr = newval;
723 return retval;
727 /**********************************************************************
728 * GetWindowLong (USER.135)
730 LONG GetWindowLong( HWND hwnd, short offset )
732 WND * wndPtr = WIN_FindWndPtr( hwnd );
733 if (!wndPtr) return 0;
734 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
735 switch(offset)
737 case GWL_STYLE: return wndPtr->dwStyle;
738 case GWL_EXSTYLE: return wndPtr->dwExStyle;
739 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
741 return 0;
745 /**********************************************************************
746 * SetWindowLong (USER.136)
748 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
750 LONG *ptr, retval;
751 WND * wndPtr = WIN_FindWndPtr( hwnd );
752 if (!wndPtr) return 0;
753 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
754 else switch(offset)
756 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
757 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
758 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
759 default: return 0;
761 retval = *ptr;
762 *ptr = newval;
763 return retval;
767 /*******************************************************************
768 * GetWindowText (USER.36)
770 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
772 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
773 (DWORD)lpString);
776 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
778 int len;
779 HANDLE handle;
781 /* We have to allocate a buffer on the USER heap */
782 /* to be able to pass its address to 16-bit code */
783 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
784 len = (int)SendMessage( hwnd, WM_GETTEXT, (WORD)nMaxCount,
785 USER_HEAP_SEG_ADDR(handle) );
786 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
787 USER_HEAP_FREE( handle );
788 return len;
792 /*******************************************************************
793 * SetWindowText (USER.37)
795 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
797 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
800 void SetWindowText( HWND hwnd, LPSTR lpString )
802 HANDLE handle;
804 /* We have to allocate a buffer on the USER heap */
805 /* to be able to pass its address to 16-bit code */
806 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
807 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
808 SendMessage( hwnd, WM_SETTEXT, 0, USER_HEAP_SEG_ADDR(handle) );
809 USER_HEAP_FREE( handle );
813 /*******************************************************************
814 * GetWindowTextLength (USER.38)
816 int GetWindowTextLength(HWND hwnd)
818 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
822 /*******************************************************************
823 * IsWindow (USER.47)
825 BOOL IsWindow( HWND hwnd )
827 WND * wndPtr = WIN_FindWndPtr( hwnd );
828 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
832 /*****************************************************************
833 * GetParent (USER.46)
835 HWND GetParent(HWND hwnd)
837 WND *wndPtr = WIN_FindWndPtr(hwnd);
838 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
839 return wndPtr->hwndParent;
842 /*****************************************************************
843 * SetParent (USER.233)
845 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
847 HWND temp;
849 WND *wndPtr = WIN_FindWndPtr(hwndChild);
850 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
852 temp = wndPtr->hwndParent;
854 if (hwndNewParent)
855 wndPtr->hwndParent = hwndNewParent;
856 else
857 wndPtr->hwndParent = GetDesktopWindow();
859 return temp;
864 /*******************************************************************
865 * IsChild (USER.48)
867 BOOL IsChild( HWND parent, HWND child )
869 WND * wndPtr = WIN_FindWndPtr( child );
870 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
872 if (wndPtr->hwndParent == parent) return TRUE;
873 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
875 return FALSE;
879 /***********************************************************************
880 * IsWindowVisible (USER.49)
882 BOOL IsWindowVisible(HWND hWnd)
884 WND * wndPtr = WIN_FindWndPtr(hWnd);
885 if (wndPtr == 0) return(FALSE);
886 else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
891 /*******************************************************************
892 * GetTopWindow (USER.229)
894 HWND GetTopWindow( HWND hwnd )
896 WND * wndPtr = WIN_FindWndPtr( hwnd );
897 if (wndPtr) return wndPtr->hwndChild;
898 else return 0;
902 /*******************************************************************
903 * GetWindow (USER.262)
905 HWND GetWindow( HWND hwnd, WORD rel )
907 WND * wndPtr = WIN_FindWndPtr( hwnd );
908 if (!wndPtr) return 0;
909 switch(rel)
911 case GW_HWNDFIRST:
912 if (wndPtr->hwndParent)
914 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
915 return parentPtr->hwndChild;
917 else return 0;
919 case GW_HWNDLAST:
920 if (!wndPtr->hwndParent) return 0; /* Desktop window */
921 while (wndPtr->hwndNext)
923 hwnd = wndPtr->hwndNext;
924 wndPtr = WIN_FindWndPtr( hwnd );
926 return hwnd;
928 case GW_HWNDNEXT:
929 return wndPtr->hwndNext;
931 case GW_HWNDPREV:
933 HWND hwndPrev;
935 if (wndPtr->hwndParent)
937 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
938 hwndPrev = parentPtr->hwndChild;
940 else return 0; /* Desktop window */
941 if (hwndPrev == hwnd) return 0;
942 while (hwndPrev)
944 wndPtr = WIN_FindWndPtr( hwndPrev );
945 if (wndPtr->hwndNext == hwnd) break;
946 hwndPrev = wndPtr->hwndNext;
948 return hwndPrev;
951 case GW_OWNER:
952 return wndPtr->hwndOwner;
954 case GW_CHILD:
955 return wndPtr->hwndChild;
957 return 0;
961 /*******************************************************************
962 * GetNextWindow (USER.230)
964 HWND GetNextWindow( HWND hwnd, WORD flag )
966 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
967 return GetWindow( hwnd, flag );
972 /*******************************************************************
973 * GetLastActivePopup (USER.287)
975 HWND GetLastActivePopup(HWND hwnd)
977 WND *wndPtr;
978 wndPtr = WIN_FindWndPtr(hwnd);
979 if (wndPtr == NULL) return hwnd;
980 return wndPtr->hwndLastActive;
984 /*******************************************************************
985 * EnumWindows (USER.54)
987 BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
989 HWND hwnd;
990 WND *wndPtr;
991 HWND *list, *pWnd;
992 int count;
994 /* We have to build a list of all windows first, to avoid */
995 /* unpleasant side-effects, for instance if the callback */
996 /* function changes the Z-order of the windows. */
998 /* First count the windows */
1000 count = 0;
1001 for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
1003 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1004 count++;
1006 if (!count) return TRUE;
1008 /* Now build the list of all windows */
1010 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1011 for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1013 wndPtr = WIN_FindWndPtr( hwnd );
1014 *pWnd++ = hwnd;
1017 /* Now call the callback function for every window */
1019 for (pWnd = list; count > 0; count--, pWnd++)
1021 /* Make sure that window still exists */
1022 if (!IsWindow(*pWnd)) continue;
1023 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1025 free( list );
1026 return TRUE;
1030 /**********************************************************************
1031 * EnumTaskWindows (USER.225)
1033 BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
1035 HWND hwnd;
1036 WND *wndPtr;
1037 HWND *list, *pWnd;
1038 HANDLE hQueue = GetTaskQueue( hTask );
1039 int count;
1041 /* This function is the same as EnumWindows(), */
1042 /* except for an added check on the window queue. */
1044 /* First count the windows */
1046 count = 0;
1047 for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
1049 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1050 if (wndPtr->hmemTaskQ == hQueue) count++;
1052 if (!count) return TRUE;
1054 /* Now build the list of all windows */
1056 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1057 for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1059 wndPtr = WIN_FindWndPtr( hwnd );
1060 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1063 /* Now call the callback function for every window */
1065 for (pWnd = list; count > 0; count--, pWnd++)
1067 /* Make sure that window still exists */
1068 if (!IsWindow(*pWnd)) continue;
1069 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1071 free( list );
1072 return TRUE;
1076 /*******************************************************************
1077 * WIN_EnumChildWin
1079 * o hwnd is the first child to use, loop until all next windows
1080 * are processed
1082 * o call wdnenumprc
1084 * o call ourselves with the next child window
1087 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1089 WND *wndPtr;
1091 while (hwnd)
1093 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1094 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1095 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1096 hwnd=wndPtr->hwndNext;
1098 return 1;
1101 /*******************************************************************
1102 * EnumChildWindows (USER.55)
1104 * o gets the first child of hwnd
1106 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1108 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1110 WND *wndPtr;
1112 dprintf_enum(stddeb,"EnumChildWindows\n");
1114 if (hwnd == 0) return 0;
1115 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1116 hwnd = wndPtr->hwndChild;
1117 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1121 /*******************************************************************
1122 * AnyPopup [USER.52]
1124 BOOL AnyPopup()
1126 dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
1127 return FALSE;
1130 /*******************************************************************
1131 * FlashWindow [USER.105]
1133 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1135 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1136 return FALSE;
1140 /*******************************************************************
1141 * SetSysModalWindow [USER.188]
1143 HWND SetSysModalWindow(HWND hWnd)
1145 HWND hWndOldModal = hWndSysModal;
1146 hWndSysModal = hWnd;
1147 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04X) !\n", hWnd);
1148 return hWndOldModal;
1152 /*******************************************************************
1153 * GetSysModalWindow [USER.189]
1155 HWND GetSysModalWindow(void)
1157 return hWndSysModal;