Release 950319
[wine.git] / windows / win.c
blob6ed50d87a4674ae4cffc1862e8e2243726718db2
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 "stddebug.h"
25 #include "callback.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;
219 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_NAME, 0, &classPtr )))
220 return FALSE;
222 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
223 if (!hwndDesktop) return FALSE;
224 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
226 wndPtr->hwndNext = 0;
227 wndPtr->hwndChild = 0;
228 wndPtr->dwMagic = WND_MAGIC;
229 wndPtr->hwndParent = 0;
230 wndPtr->hwndOwner = 0;
231 wndPtr->hClass = hclass;
232 wndPtr->hInstance = 0;
233 wndPtr->rectWindow.left = 0;
234 wndPtr->rectWindow.top = 0;
235 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
236 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
237 wndPtr->rectClient = wndPtr->rectWindow;
238 wndPtr->rectNormal = wndPtr->rectWindow;
239 wndPtr->ptIconPos.x = -1;
240 wndPtr->ptIconPos.y = -1;
241 wndPtr->ptMaxPos.x = -1;
242 wndPtr->ptMaxPos.y = -1;
243 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
244 wndPtr->hrgnUpdate = 0;
245 wndPtr->hwndLastActive = hwndDesktop;
246 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
247 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
248 wndPtr->dwExStyle = 0;
249 wndPtr->hdce = 0;
250 wndPtr->hVScroll = 0;
251 wndPtr->hHScroll = 0;
252 wndPtr->wIDmenu = 0;
253 wndPtr->hText = 0;
254 wndPtr->flags = 0;
255 wndPtr->window = rootWindow;
256 wndPtr->hSysMenu = 0;
257 wndPtr->hProp = 0;
258 wndPtr->hTask = 0;
260 /* Send dummy WM_NCCREATE message */
261 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
262 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
263 RedrawWindow( hwndDesktop, NULL, 0,
264 RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
265 return TRUE;
269 /***********************************************************************
270 * CreateWindow (USER.41)
272 HWND CreateWindow( LPSTR className, LPSTR windowName,
273 DWORD style, short x, short y, short width, short height,
274 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
276 return CreateWindowEx( 0, className, windowName, style,
277 x, y, width, height, parent, menu, instance, data );
281 /***********************************************************************
282 * CreateWindowEx (USER.452)
284 HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
285 DWORD style, short x, short y, short width, short height,
286 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
288 HANDLE class, hwnd;
289 CLASS *classPtr;
290 WND *wndPtr;
291 POINT maxSize, maxPos, minTrack, maxTrack;
292 CREATESTRUCT *createStruct;
293 HANDLE hcreateStruct, hwinName, hclassName;
294 int wmcreate;
295 XSetWindowAttributes win_attr;
297 dprintf_win(stddeb, "CreateWindowEx: %08lX '%s' '%s' %08lX %d,%d %dx%d %04X %04X %04X %08lx\n",
298 exStyle, className, windowName, style, x, y, width, height,
299 parent, menu, instance, data);
300 /* 'soundrec.exe' has negative position !
301 Why ? For now, here a patch : */
302 if (!strcmp(className, "SoundRec"))
304 if (x < 0) x = 0;
305 if (y < 0) y = 0;
307 if (x == CW_USEDEFAULT) x = y = 0;
308 if (width == CW_USEDEFAULT)
310 width = 600;
311 height = 400;
313 if (width == 0) width = 1;
314 if (height == 0) height = 1;
316 /* Find the parent and class */
318 if (parent)
320 /* Make sure parent is valid */
321 if (!IsWindow( parent )) return 0;
323 else if (style & WS_CHILD) return 0; /* WS_CHILD needs a parent */
325 if (!(class = CLASS_FindClassByName( className, instance, &classPtr ))) {
326 fprintf(stderr,"CreateWindow BAD CLASSNAME '%s' !\n", className);
327 return 0;
330 /* Correct the window style */
332 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
333 style |= WS_CAPTION | WS_CLIPSIBLINGS;
334 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
336 /* Create the window structure */
338 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
339 if (!hwnd) return 0;
341 /* Fill the structure */
343 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
344 wndPtr->hwndNext = 0;
345 wndPtr->hwndChild = 0;
346 wndPtr->window = 0;
347 wndPtr->dwMagic = WND_MAGIC;
348 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
349 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : parent;
350 wndPtr->hClass = class;
351 wndPtr->hInstance = instance;
352 wndPtr->rectWindow.left = x;
353 wndPtr->rectWindow.top = y;
354 wndPtr->rectWindow.right = x + width;
355 wndPtr->rectWindow.bottom = y + height;
356 wndPtr->rectClient = wndPtr->rectWindow;
357 wndPtr->rectNormal = wndPtr->rectWindow;
358 wndPtr->ptIconPos.x = -1;
359 wndPtr->ptIconPos.y = -1;
360 wndPtr->ptMaxPos.x = -1;
361 wndPtr->ptMaxPos.y = -1;
362 wndPtr->hmemTaskQ = GetTaskQueue(0);
363 wndPtr->hrgnUpdate = 0;
364 wndPtr->hwndPrevActive = 0;
365 wndPtr->hwndLastActive = hwnd;
366 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
367 wndPtr->dwStyle = style;
368 wndPtr->dwExStyle = exStyle;
369 wndPtr->wIDmenu = 0;
370 wndPtr->hText = 0;
371 wndPtr->flags = 0;
372 wndPtr->hVScroll = 0;
373 wndPtr->hHScroll = 0;
374 wndPtr->hSysMenu = 0;
375 wndPtr->hProp = 0;
376 wndPtr->hTask = 0;
378 if (classPtr->wc.cbWndExtra)
379 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
380 classPtr->cWindows++;
382 /* Make sure owner is a top-level window */
384 while (wndPtr->hwndOwner && GetParent(wndPtr->hwndOwner))
385 wndPtr->hwndOwner = GetParent(wndPtr->hwndOwner);
387 /* Get class or window DC if needed */
389 if (classPtr->wc.style & CS_OWNDC)
390 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
391 else if (classPtr->wc.style & CS_CLASSDC)
392 wndPtr->hdce = classPtr->hdce;
393 else
394 wndPtr->hdce = 0;
396 /* Insert the window in the linked list */
398 WIN_LinkWindow( hwnd, HWND_TOP );
400 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
402 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
404 if ( maxSize.x < width)
406 width = maxSize.x;
407 wndPtr->rectWindow.right = x + width;
409 if ( maxSize.y < height)
411 height = maxSize.y;
412 wndPtr->rectWindow.bottom = y + height;
415 /* Create the X window (only for top-level windows, and then only */
416 /* when there's no desktop window) */
418 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
420 CURSORALLOC *cursor;
421 HCURSOR hCursor = classPtr->wc.hCursor;
422 if (!hCursor) hCursor = LoadCursor( 0, IDC_ARROW );
423 cursor = (CURSORALLOC *) GlobalLock(hCursor);
425 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
426 PointerMotionMask | ButtonPressMask |
427 ButtonReleaseMask | FocusChangeMask;
428 win_attr.override_redirect = TRUE;
429 win_attr.colormap = COLOR_WinColormap;
430 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
431 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
432 win_attr.cursor = cursor ? cursor->xcursor : None;
433 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
434 width, height, 0, CopyFromParent,
435 InputOutput, CopyFromParent,
436 CWEventMask | CWOverrideRedirect |
437 CWColormap | CWCursor | CWSaveUnder |
438 CWBackingStore, &win_attr );
439 XStoreName( display, wndPtr->window, windowName );
440 EVENT_RegisterWindow( wndPtr->window, hwnd );
441 GlobalUnlock( hCursor );
444 if ((style & WS_CAPTION) && !(style & WS_CHILD))
446 if (menu) SetMenu(hwnd, menu);
447 else if (classPtr->wc.lpszMenuName)
448 SetMenu(hwnd,LoadMenu(instance,(SEGPTR)classPtr->wc.lpszMenuName));
450 else wndPtr->wIDmenu = menu;
452 /* Send the WM_CREATE message */
454 hcreateStruct = USER_HEAP_ALLOC( sizeof(CREATESTRUCT) );
455 hclassName = USER_HEAP_ALLOC( strlen(className)+1 );
456 strcpy( USER_HEAP_LIN_ADDR(hclassName), className );
457 createStruct = (CREATESTRUCT *) USER_HEAP_LIN_ADDR( hcreateStruct );
458 createStruct->lpCreateParams = (LPSTR)data;
459 createStruct->hInstance = instance;
460 createStruct->hMenu = menu;
461 createStruct->hwndParent = parent;
462 createStruct->cx = width;
463 createStruct->cy = height;
464 createStruct->x = x;
465 createStruct->y = y;
466 createStruct->style = style;
467 createStruct->lpszClass = (LPSTR)USER_HEAP_SEG_ADDR(hclassName);
468 createStruct->dwExStyle = 0;
469 if (windowName)
471 hwinName = USER_HEAP_ALLOC( strlen(windowName)+1 );
472 strcpy( USER_HEAP_LIN_ADDR(hwinName), windowName );
473 createStruct->lpszName = (LPSTR)USER_HEAP_SEG_ADDR(hwinName);
475 else
477 hwinName = 0;
478 createStruct->lpszName = NULL;
481 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0,
482 USER_HEAP_SEG_ADDR(hcreateStruct) );
483 if (!wmcreate) wmcreate = -1;
484 else
486 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
487 NULL, NULL, NULL, &wndPtr->rectClient );
488 wmcreate = SendMessage( hwnd, WM_CREATE, 0,
489 USER_HEAP_SEG_ADDR(hcreateStruct) );
492 USER_HEAP_FREE( hcreateStruct );
493 USER_HEAP_FREE( hclassName );
494 if (hwinName) USER_HEAP_FREE( hwinName );
496 if (wmcreate == -1)
498 /* Abort window creation */
499 WIN_DestroyWindow( hwnd );
500 return 0;
503 /* Create a copy of SysMenu */
504 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
506 /* Register window in current task windows list */
507 AddWindowToTask(GetCurrentTask(), hwnd);
509 WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
511 if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
512 /* if (style & WS_MINIMIZE) ShowWindow( hwnd, SW_MINIMIZE ); */
514 dprintf_win(stddeb, "CreateWindowEx: return %04X \n", hwnd);
515 return hwnd;
519 /***********************************************************************
520 * DestroyWindow (USER.53)
522 BOOL DestroyWindow( HWND hwnd )
524 WND * wndPtr;
525 CLASS * classPtr;
527 dprintf_win(stddeb, "DestroyWindow (%04x)\n", hwnd);
529 /* Initialisation */
531 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
532 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
533 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
535 /* Hide the window */
537 if (wndPtr->dwStyle & WS_VISIBLE)
538 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
539 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
540 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
541 ReleaseCapture();
542 WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
544 /* Recursively destroy owned windows */
546 for (;;)
548 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
549 while (hwndSibling)
551 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
552 if (siblingPtr->hwndOwner == hwnd) break;
553 hwndSibling = siblingPtr->hwndNext;
555 if (hwndSibling) DestroyWindow( hwndSibling );
556 else break;
559 /* Send destroy messages and destroy children */
561 SendMessage( hwnd, WM_DESTROY, 0, 0 );
562 while (wndPtr->hwndChild) /* The child removes itself from the list */
563 DestroyWindow( wndPtr->hwndChild );
564 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
566 /* Remove the window from current task windows list */
567 RemoveWindowFromTask(GetCurrentTask(), hwnd);
569 /* Destroy the window */
571 WIN_DestroyWindow( hwnd );
572 return TRUE;
576 /***********************************************************************
577 * CloseWindow (USER.43)
579 void CloseWindow(HWND hWnd)
581 WND * wndPtr = WIN_FindWndPtr(hWnd);
582 if (wndPtr->dwStyle & WS_CHILD) return;
583 ShowWindow(hWnd, SW_MINIMIZE);
587 /***********************************************************************
588 * OpenIcon (USER.44)
590 BOOL OpenIcon(HWND hWnd)
592 if (!IsIconic(hWnd)) return FALSE;
593 ShowWindow(hWnd, SW_SHOWNORMAL);
594 return(TRUE);
598 /***********************************************************************
599 * FindWindow (USER.50)
601 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
603 HCLASS hclass;
604 CLASS *classPtr;
605 HWND hwnd;
607 if (ClassMatch)
609 hclass = CLASS_FindClassByName( ClassMatch, 0xffff, &classPtr );
610 if (!hclass) return 0;
612 else hclass = 0;
614 hwnd = GetTopWindow( hwndDesktop );
615 while(hwnd)
617 WND *wndPtr = WIN_FindWndPtr( hwnd );
618 if (!hclass || (wndPtr->hClass == hclass))
620 /* Found matching class */
621 if (!TitleMatch) return hwnd;
622 if (wndPtr->hText)
624 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
625 if (!strcmp( textPtr, TitleMatch )) return hwnd;
628 hwnd = wndPtr->hwndNext;
630 return 0;
634 /**********************************************************************
635 * GetDesktopWindow (USER.286)
636 * GetDeskTopHwnd (USER.278)
638 HWND GetDesktopWindow(void)
640 return hwndDesktop;
644 /*******************************************************************
645 * EnableWindow (USER.34)
647 BOOL EnableWindow( HWND hwnd, BOOL enable )
649 WND *wndPtr;
651 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
652 if (enable && (wndPtr->dwStyle & WS_DISABLED))
654 /* Enable window */
655 wndPtr->dwStyle &= ~WS_DISABLED;
656 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
657 return TRUE;
659 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
661 /* Disable window */
662 wndPtr->dwStyle |= WS_DISABLED;
663 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
664 SetFocus( 0 ); /* A disabled window can't have the focus */
665 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
666 ReleaseCapture(); /* A disabled window can't capture the mouse */
667 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
668 return FALSE;
670 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
674 /***********************************************************************
675 * IsWindowEnabled (USER.35)
677 BOOL IsWindowEnabled(HWND hWnd)
679 WND * wndPtr;
681 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
682 return !(wndPtr->dwStyle & WS_DISABLED);
686 /**********************************************************************
687 * GetWindowWord (USER.133)
689 WORD GetWindowWord( HWND hwnd, short offset )
691 WND * wndPtr = WIN_FindWndPtr( hwnd );
692 if (!wndPtr) return 0;
693 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
694 switch(offset)
696 case GWW_ID: return wndPtr->wIDmenu;
697 case GWW_HWNDPARENT: return wndPtr->hwndParent;
698 case GWW_HINSTANCE: return wndPtr->hInstance;
700 return 0;
704 /**********************************************************************
705 * SetWindowWord (USER.134)
707 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
709 WORD *ptr, retval;
710 WND * wndPtr = WIN_FindWndPtr( hwnd );
711 if (!wndPtr) return 0;
712 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
713 else switch(offset)
715 case GWW_ID: ptr = &wndPtr->wIDmenu;
716 case GWW_HINSTANCE: ptr = &wndPtr->hInstance;
717 default: return 0;
719 retval = *ptr;
720 *ptr = newval;
721 return retval;
725 /**********************************************************************
726 * GetWindowLong (USER.135)
728 LONG GetWindowLong( HWND hwnd, short offset )
730 WND * wndPtr = WIN_FindWndPtr( hwnd );
731 if (!wndPtr) return 0;
732 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
733 switch(offset)
735 case GWL_STYLE: return wndPtr->dwStyle;
736 case GWL_EXSTYLE: return wndPtr->dwExStyle;
737 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
739 return 0;
743 /**********************************************************************
744 * SetWindowLong (USER.136)
746 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
748 LONG *ptr, retval;
749 WND * wndPtr = WIN_FindWndPtr( hwnd );
750 if (!wndPtr) return 0;
751 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
752 else switch(offset)
754 case GWL_STYLE: ptr = &wndPtr->dwStyle;
755 break;
756 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
757 break;
758 case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
759 break;
760 default: return 0;
762 retval = *ptr;
763 *ptr = newval;
764 return retval;
768 /*******************************************************************
769 * GetWindowText (USER.36)
771 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
773 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
774 (DWORD)lpString);
777 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
779 int len;
780 HANDLE handle;
782 /* We have to allocate a buffer on the USER heap */
783 /* to be able to pass its address to 16-bit code */
784 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
785 len = (int)SendMessage( hwnd, WM_GETTEXT, (WORD)nMaxCount,
786 USER_HEAP_SEG_ADDR(handle) );
787 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
788 USER_HEAP_FREE( handle );
789 return len;
793 /*******************************************************************
794 * SetWindowText (USER.37)
796 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
798 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
801 void SetWindowText( HWND hwnd, LPSTR lpString )
803 HANDLE handle;
805 /* We have to allocate a buffer on the USER heap */
806 /* to be able to pass its address to 16-bit code */
807 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
808 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
809 SendMessage( hwnd, WM_SETTEXT, 0, USER_HEAP_SEG_ADDR(handle) );
810 USER_HEAP_FREE( handle );
814 /*******************************************************************
815 * GetWindowTextLength (USER.38)
817 int GetWindowTextLength(HWND hwnd)
819 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
823 /*******************************************************************
824 * IsWindow (USER.47)
826 BOOL IsWindow( HWND hwnd )
828 WND * wndPtr = WIN_FindWndPtr( hwnd );
829 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
833 /*****************************************************************
834 * GetParent (USER.46)
836 HWND GetParent(HWND hwnd)
838 WND *wndPtr = WIN_FindWndPtr(hwnd);
839 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
840 return wndPtr->hwndParent;
843 /*****************************************************************
844 * SetParent (USER.233)
846 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
848 HWND temp;
850 WND *wndPtr = WIN_FindWndPtr(hwndChild);
851 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
853 temp = wndPtr->hwndParent;
855 if (hwndNewParent)
856 wndPtr->hwndParent = hwndNewParent;
857 else
858 wndPtr->hwndParent = GetDesktopWindow();
860 return temp;
865 /*******************************************************************
866 * IsChild (USER.48)
868 BOOL IsChild( HWND parent, HWND child )
870 WND * wndPtr = WIN_FindWndPtr( child );
871 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
873 if (wndPtr->hwndParent == parent) return TRUE;
874 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
876 return FALSE;
880 /***********************************************************************
881 * IsWindowVisible (USER.49)
883 BOOL IsWindowVisible(HWND hWnd)
885 WND * wndPtr = WIN_FindWndPtr(hWnd);
886 if (wndPtr == 0) return(FALSE);
887 else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
892 /*******************************************************************
893 * GetTopWindow (USER.229)
895 HWND GetTopWindow( HWND hwnd )
897 WND * wndPtr = WIN_FindWndPtr( hwnd );
898 if (wndPtr) return wndPtr->hwndChild;
899 else return 0;
903 /*******************************************************************
904 * GetWindow (USER.262)
906 HWND GetWindow( HWND hwnd, WORD rel )
908 WND * wndPtr = WIN_FindWndPtr( hwnd );
909 if (!wndPtr) return 0;
910 switch(rel)
912 case GW_HWNDFIRST:
913 if (wndPtr->hwndParent)
915 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
916 return parentPtr->hwndChild;
918 else return 0;
920 case GW_HWNDLAST:
921 if (!wndPtr->hwndParent) return 0; /* Desktop window */
922 while (wndPtr->hwndNext)
924 hwnd = wndPtr->hwndNext;
925 wndPtr = WIN_FindWndPtr( hwnd );
927 return hwnd;
929 case GW_HWNDNEXT:
930 return wndPtr->hwndNext;
932 case GW_HWNDPREV:
934 HWND hwndPrev;
936 if (wndPtr->hwndParent)
938 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
939 hwndPrev = parentPtr->hwndChild;
941 else return 0; /* Desktop window */
942 if (hwndPrev == hwnd) return 0;
943 while (hwndPrev)
945 wndPtr = WIN_FindWndPtr( hwndPrev );
946 if (wndPtr->hwndNext == hwnd) break;
947 hwndPrev = wndPtr->hwndNext;
949 return hwndPrev;
952 case GW_OWNER:
953 return wndPtr->hwndOwner;
955 case GW_CHILD:
956 return wndPtr->hwndChild;
958 return 0;
962 /*******************************************************************
963 * GetNextWindow (USER.230)
965 HWND GetNextWindow( HWND hwnd, WORD flag )
967 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
968 return GetWindow( hwnd, flag );
973 /*******************************************************************
974 * GetLastActivePopup (USER.287)
976 HWND GetLastActivePopup(HWND hwnd)
978 WND *wndPtr;
979 wndPtr = WIN_FindWndPtr(hwnd);
980 if (wndPtr == NULL) return hwnd;
981 return wndPtr->hwndLastActive;
985 /*******************************************************************
986 * EnumWindows (USER.54)
988 * o gets the desktop window and iterates over all the windows
989 * which are direct decendents of the desktop * by iterating over
990 * the desktop's child window and all the child windows next
991 * pointers
993 * o call wndenumprc for every child window the desktop has
994 * (parameters to Callback16 passed backwards so they are
995 * put in in pascal calling order)
997 * o if wndenumprc returns 0 exit
1000 BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
1002 HWND hwnd = GetTopWindow( GetDesktopWindow() );
1003 WND *wndPtr;
1004 int result;
1006 dprintf_enum(stddeb,"EnumWindows\n");
1008 while (hwnd) {
1009 if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
1010 return 0;
1012 #ifdef WINELIB
1013 (*wndenumprc)(hwnd, lParam);
1014 #else
1015 result = CallBack16(wndenumprc, 2,
1016 CALLBACK_SIZE_WORD, (int) hwnd,
1017 CALLBACK_SIZE_LONG, lParam);
1018 #endif
1019 if ( ! result ) {
1020 return 0;
1022 hwnd=wndPtr->hwndNext;
1024 return 1; /* for now */
1027 /*******************************************************************
1028 * WIN_EnumChildWin
1030 * o hwnd is the first child to use, loop until all next windows
1031 * are processed
1033 * o call wdnenumprc with parameters in inverse order (pascal)
1035 * o call ourselves with the next child window
1038 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1040 WND *wndPtr;
1042 while (hwnd) {
1043 if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
1044 return 0;
1046 #ifdef WINELIB
1047 if (!(*wndenumprc)( 2, lParam, (int) hwnd)) {
1048 #else
1049 if (!CallBack16(wndenumprc, 2,
1050 CALLBACK_SIZE_WORD, (int) hwnd,
1051 CALLBACK_SIZE_LONG, lParam)) {
1052 #endif
1053 return 0;
1055 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
1056 return 0;
1058 hwnd=wndPtr->hwndNext;
1060 return 1;
1063 /*******************************************************************
1064 * EnumChildWindows (USER.55)
1066 * o gets the first child of hwnd
1068 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1070 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1072 WND *wndPtr;
1074 dprintf_enum(stddeb,"EnumChildWindows\n");
1076 if (hwnd == 0) return 0;
1077 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1078 hwnd = wndPtr->hwndChild;
1079 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1082 /*******************************************************************
1083 * AnyPopup [USER.52]
1085 BOOL AnyPopup()
1087 dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
1088 return FALSE;
1091 /*******************************************************************
1092 * FlashWindow [USER.105]
1094 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1096 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1097 return FALSE;
1101 /*******************************************************************
1102 * SetSysModalWindow [USER.188]
1104 HWND SetSysModalWindow(HWND hWnd)
1106 HWND hWndOldModal = hWndSysModal;
1107 hWndSysModal = hWnd;
1108 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04X) !\n", hWnd);
1109 return hWndOldModal;
1113 /*******************************************************************
1114 * GetSysModalWindow [USER.189]
1116 HWND GetSysModalWindow(void)
1118 return hWndSysModal;