Release 951105
[wine/multimedia.git] / windows / win.c
blob1e0d209ed46d75bca7afa4bee2268d22e415af14
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 "cursoricon.h"
18 #include "event.h"
19 #include "message.h"
20 #include "nonclient.h"
21 #include "winpos.h"
22 #include "color.h"
23 #include "shm_main_blk.h"
24 #include "dde_proc.h"
25 #include "callback.h"
26 #include "stddebug.h"
27 /* #define DEBUG_WIN */
28 /* #define DEBUG_MENU */
29 #include "debug.h"
31 static HWND hwndDesktop = 0;
32 static HWND hWndSysModal = 0;
34 /***********************************************************************
35 * WIN_FindWndPtr
37 * Return a pointer to the WND structure corresponding to a HWND.
39 WND * WIN_FindWndPtr( HWND hwnd )
41 WND * ptr;
43 if (!hwnd) return NULL;
44 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
45 if (ptr->dwMagic != WND_MAGIC) return NULL;
46 return ptr;
50 /***********************************************************************
51 * WIN_GetXWindow
53 * Return the X window associated to a window.
55 Window WIN_GetXWindow( HWND hwnd )
57 WND *wndPtr = WIN_FindWndPtr( hwnd );
58 while (wndPtr && !wndPtr->window)
60 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
62 return wndPtr ? wndPtr->window : 0;
66 /***********************************************************************
67 * WIN_UnlinkWindow
69 * Remove a window from the siblings linked list.
71 BOOL WIN_UnlinkWindow( HWND hwnd )
73 HWND * curWndPtr;
74 WND *parentPtr, *wndPtr;
76 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
77 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
79 curWndPtr = &parentPtr->hwndChild;
81 while (*curWndPtr != hwnd)
83 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
84 curWndPtr = &curPtr->hwndNext;
86 *curWndPtr = wndPtr->hwndNext;
87 return TRUE;
91 /***********************************************************************
92 * WIN_LinkWindow
94 * Insert a window into the siblings linked list.
95 * The window is inserted after the specified window, which can also
96 * be specified as HWND_TOP or HWND_BOTTOM.
98 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
100 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
101 WND *wndPtr, *parentPtr;
103 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
104 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
106 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
108 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
109 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
110 while (*hwndPtr)
112 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
113 hwndPtr = &nextPtr->hwndNext;
116 else /* Normal case */
118 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
119 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
121 if (!hwndPtr) return FALSE;
122 wndPtr->hwndNext = *hwndPtr;
123 *hwndPtr = hwnd;
124 return TRUE;
128 /***********************************************************************
129 * WIN_FindWinToRepaint
131 * Find a window that needs repaint.
133 HWND WIN_FindWinToRepaint( HWND hwnd )
135 WND * wndPtr;
137 /* Note: the desktop window never gets WM_PAINT messages */
138 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
139 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
141 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
142 dprintf_win( stddeb, "WIN_FindWinToRepaint: "NPFMT", style %08lx\n",
143 hwnd, wndPtr->dwStyle );
144 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
145 continue;
146 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
147 continue;
148 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
149 return hwnd;
150 if (wndPtr->hwndChild)
152 HWND child;
153 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
154 return child;
157 return 0;
161 /***********************************************************************
162 * WIN_SendParentNotify
164 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
165 * the window has the WS_EX_NOPARENTNOTIFY style.
167 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
169 WND *wndPtr = WIN_FindWndPtr( hwnd );
171 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
173 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
174 #ifdef WINELIB32
175 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY,
176 MAKEWPARAM(event,idChild),
177 (LPARAM)lValue );
178 #else
179 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event,
180 MAKELPARAM(LOWORD(lValue), idChild) );
181 #endif
182 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
187 /***********************************************************************
188 * WIN_DestroyWindow
190 * Destroy storage associated to a window
192 static void WIN_DestroyWindow( HWND hwnd )
194 WND *wndPtr = WIN_FindWndPtr( hwnd );
195 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
197 #ifdef CONFIG_IPC
198 if (main_block)
199 DDE_DestroyWindow(hwnd);
200 #endif /* CONFIG_IPC */
202 if (!wndPtr || !classPtr) return;
203 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
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( (HMENU)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(void)
229 WND *wndPtr;
230 HCLASS hclass;
231 CLASS *classPtr;
232 HDC hdc;
234 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
235 return FALSE;
237 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
238 if (!hwndDesktop) return FALSE;
239 wndPtr = (WND *) USER_HEAP_LIN_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->hVScroll = 0;
266 wndPtr->hHScroll = 0;
267 wndPtr->wIDmenu = 0;
268 wndPtr->hText = 0;
269 wndPtr->flags = 0;
270 wndPtr->window = rootWindow;
271 wndPtr->hSysMenu = 0;
272 wndPtr->hProp = 0;
273 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
274 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
275 if ((hdc = GetDC( hwndDesktop )) != 0)
277 SendMessage( hwndDesktop, WM_ERASEBKGND, (WPARAM)hdc, 0 );
278 ReleaseDC( hwndDesktop, hdc );
280 return TRUE;
284 /***********************************************************************
285 * CreateWindow (USER.41)
287 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
288 DWORD style, INT x, INT y, INT width, INT height,
289 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
291 return CreateWindowEx( 0, className, windowName, style,
292 x, y, width, height, parent, menu, instance, data );
296 /***********************************************************************
297 * CreateWindowEx (USER.452)
299 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
300 DWORD style, INT x, INT y, INT width, INT height,
301 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
303 HANDLE class, hwnd;
304 CLASS *classPtr;
305 WND *wndPtr;
306 POINT maxSize, maxPos, minTrack, maxTrack;
307 CREATESTRUCT createStruct;
308 int wmcreate;
309 XSetWindowAttributes win_attr;
311 /* FIXME: windowName and className should be SEGPTRs */
313 dprintf_win( stddeb, "CreateWindowEx: " );
314 if (HIWORD(windowName))
315 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
316 else
317 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
318 if (HIWORD(className))
319 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
320 else
321 dprintf_win( stddeb, "%04x ", LOWORD(className) );
323 dprintf_win(stddeb, "%08lx %08lx %d,%d %dx%d "NPFMT" "NPFMT" "NPFMT" %08lx\n",
324 exStyle, style, x, y, width, height,
325 parent, menu, instance, (DWORD)data);
327 if (x == CW_USEDEFAULT) x = y = 0;
328 if (width == CW_USEDEFAULT)
330 width = 600;
331 height = 400;
334 /* Find the parent and class */
336 if (parent)
338 /* Make sure parent is valid */
339 if (!IsWindow( parent )) {
340 dprintf_win(stddeb,"CreateWindowEx: Parent "NPFMT" is not a window\n", parent);
341 return 0;
344 else
346 if (style & WS_CHILD) {
347 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
348 return 0; /* WS_CHILD needs a parent */
352 if (!(class = CLASS_FindClassByName( className, GetExePtr(instance),
353 &classPtr )))
355 fprintf(stderr,"CreateWindow BAD CLASSNAME " );
356 if (HIWORD(className)) fprintf( stderr, "'%s'\n",
357 (char *)PTR_SEG_TO_LIN(className) );
358 else fprintf( stderr, "%04x\n", LOWORD(className) );
359 return 0;
362 /* Correct the window style */
364 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
365 style |= WS_CAPTION | WS_CLIPSIBLINGS;
366 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
368 /* Create the window structure */
370 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
371 if (!hwnd) {
372 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
373 return 0;
376 /* Fill the structure */
378 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
379 wndPtr->hwndNext = 0;
380 wndPtr->hwndChild = 0;
381 wndPtr->window = 0;
382 wndPtr->dwMagic = WND_MAGIC;
383 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
384 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
385 wndPtr->hClass = class;
386 wndPtr->hInstance = instance;
387 wndPtr->ptIconPos.x = -1;
388 wndPtr->ptIconPos.y = -1;
389 wndPtr->ptMaxPos.x = -1;
390 wndPtr->ptMaxPos.y = -1;
391 wndPtr->hmemTaskQ = GetTaskQueue(0);
392 wndPtr->hrgnUpdate = 0;
393 wndPtr->hwndPrevActive = 0;
394 wndPtr->hwndLastActive = hwnd;
395 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
396 wndPtr->dwStyle = style & ~WS_VISIBLE;
397 wndPtr->dwExStyle = exStyle;
398 wndPtr->wIDmenu = 0;
399 wndPtr->hText = 0;
400 wndPtr->flags = 0;
401 wndPtr->hVScroll = 0;
402 wndPtr->hHScroll = 0;
403 wndPtr->hSysMenu = 0;
404 wndPtr->hProp = 0;
406 if (classPtr->wc.cbWndExtra)
407 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
408 classPtr->cWindows++;
410 /* Get class or window DC if needed */
412 if (classPtr->wc.style & CS_OWNDC)
413 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
414 else if (classPtr->wc.style & CS_CLASSDC)
415 wndPtr->hdce = classPtr->hdce;
416 else
417 wndPtr->hdce = 0;
419 /* Insert the window in the linked list */
421 WIN_LinkWindow( hwnd, HWND_TOP );
423 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
425 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
427 if (maxSize.x < width) width = maxSize.x;
428 if (maxSize.y < height) height = maxSize.y;
429 if (width <= 0) width = 1;
430 if (height <= 0) height = 1;
432 wndPtr->rectWindow.left = x;
433 wndPtr->rectWindow.top = y;
434 wndPtr->rectWindow.right = x + width;
435 wndPtr->rectWindow.bottom = y + height;
436 wndPtr->rectClient = wndPtr->rectWindow;
437 wndPtr->rectNormal = wndPtr->rectWindow;
439 /* Create the X window (only for top-level windows, and then only */
440 /* when there's no desktop window) */
442 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
444 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
445 PointerMotionMask | ButtonPressMask |
446 ButtonReleaseMask | FocusChangeMask;
447 win_attr.override_redirect = TRUE;
448 win_attr.colormap = COLOR_WinColormap;
449 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
450 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
451 win_attr.cursor = CURSORICON_XCursor;
452 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
453 width, height, 0, CopyFromParent,
454 InputOutput, CopyFromParent,
455 CWEventMask | CWOverrideRedirect |
456 CWColormap | CWCursor | CWSaveUnder |
457 CWBackingStore, &win_attr );
458 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
459 EVENT_RegisterWindow( wndPtr->window, hwnd );
462 if ((style & WS_CAPTION) && !(style & WS_CHILD))
464 if (menu) SetMenu(hwnd, menu);
465 else if (classPtr->wc.lpszMenuName)
466 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
468 else wndPtr->wIDmenu = (UINT)menu;
470 /* Send the WM_CREATE message */
472 createStruct.lpCreateParams = (LPSTR)data;
473 createStruct.hInstance = instance;
474 createStruct.hMenu = menu;
475 createStruct.hwndParent = parent;
476 createStruct.cx = width;
477 createStruct.cy = height;
478 createStruct.x = x;
479 createStruct.y = y;
480 createStruct.style = style;
481 createStruct.lpszName = windowName;
482 createStruct.lpszClass = className;
483 createStruct.dwExStyle = 0;
485 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, MAKE_SEGPTR(&createStruct) );
486 if (!wmcreate)
488 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
489 wmcreate = -1;
491 else
493 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
494 NULL, NULL, NULL, &wndPtr->rectClient );
495 wmcreate = SendMessage(hwnd, WM_CREATE, 0, MAKE_SEGPTR(&createStruct));
498 if (wmcreate == -1)
500 /* Abort window creation */
501 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
502 WIN_DestroyWindow( hwnd );
503 return 0;
506 /* Create a copy of SysMenu */
507 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
509 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
511 /* Show the window, maximizing or minimizing if needed */
513 if (wndPtr->dwStyle & WS_MINIMIZE)
515 wndPtr->dwStyle &= ~WS_MAXIMIZE;
516 WINPOS_FindIconPos( hwnd );
517 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
518 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
519 SWP_FRAMECHANGED |
520 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
522 else if (wndPtr->dwStyle & WS_MAXIMIZE)
524 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
525 SWP_FRAMECHANGED |
526 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
528 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
530 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
531 return hwnd;
535 /***********************************************************************
536 * DestroyWindow (USER.53)
538 BOOL DestroyWindow( HWND hwnd )
540 WND * wndPtr;
541 CLASS * classPtr;
543 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
545 /* Initialisation */
547 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
548 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
549 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
551 /* Hide the window */
553 if (wndPtr->dwStyle & WS_VISIBLE)
554 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
555 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
556 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
557 ReleaseCapture();
558 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
560 /* Recursively destroy owned windows */
562 for (;;)
564 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
565 while (hwndSibling)
567 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
568 if (siblingPtr->hwndOwner == hwnd) break;
569 hwndSibling = siblingPtr->hwndNext;
571 if (hwndSibling) DestroyWindow( hwndSibling );
572 else break;
575 /* Send destroy messages and destroy children */
577 SendMessage( hwnd, WM_DESTROY, 0, 0 );
578 while (wndPtr->hwndChild) /* The child removes itself from the list */
579 DestroyWindow( wndPtr->hwndChild );
580 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
582 /* Destroy the window */
584 WIN_DestroyWindow( hwnd );
585 return TRUE;
589 /***********************************************************************
590 * CloseWindow (USER.43)
592 void CloseWindow(HWND hWnd)
594 WND * wndPtr = WIN_FindWndPtr(hWnd);
595 if (wndPtr->dwStyle & WS_CHILD) return;
596 ShowWindow(hWnd, SW_MINIMIZE);
600 /***********************************************************************
601 * OpenIcon (USER.44)
603 BOOL OpenIcon(HWND hWnd)
605 if (!IsIconic(hWnd)) return FALSE;
606 ShowWindow(hWnd, SW_SHOWNORMAL);
607 return(TRUE);
611 /***********************************************************************
612 * FindWindow (USER.50)
614 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
616 HCLASS hclass;
617 CLASS *classPtr;
618 HWND hwnd;
620 if (ClassMatch)
622 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
623 &classPtr );
624 if (!hclass) return 0;
626 else hclass = 0;
628 hwnd = GetTopWindow( hwndDesktop );
629 while(hwnd)
631 WND *wndPtr = WIN_FindWndPtr( hwnd );
632 if (!hclass || (wndPtr->hClass == hclass))
634 /* Found matching class */
635 if (!TitleMatch) return hwnd;
636 if (wndPtr->hText)
638 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
639 if (!strcmp( textPtr, TitleMatch )) return hwnd;
642 hwnd = wndPtr->hwndNext;
644 return 0;
648 /**********************************************************************
649 * GetDesktopWindow (USER.286)
650 * GetDeskTopHwnd (USER.278)
652 HWND GetDesktopWindow(void)
654 return hwndDesktop;
658 /*******************************************************************
659 * EnableWindow (USER.34)
661 BOOL EnableWindow( HWND hwnd, BOOL enable )
663 WND *wndPtr;
665 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
666 if (enable && (wndPtr->dwStyle & WS_DISABLED))
668 /* Enable window */
669 wndPtr->dwStyle &= ~WS_DISABLED;
670 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
671 return TRUE;
673 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
675 /* Disable window */
676 wndPtr->dwStyle |= WS_DISABLED;
677 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
678 SetFocus( 0 ); /* A disabled window can't have the focus */
679 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
680 ReleaseCapture(); /* A disabled window can't capture the mouse */
681 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
682 return FALSE;
684 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
688 /***********************************************************************
689 * IsWindowEnabled (USER.35)
691 BOOL IsWindowEnabled(HWND hWnd)
693 WND * wndPtr;
695 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
696 return !(wndPtr->dwStyle & WS_DISABLED);
700 /**********************************************************************
701 * GetWindowWord (USER.133)
703 WORD GetWindowWord( HWND hwnd, short offset )
705 WND * wndPtr = WIN_FindWndPtr( hwnd );
706 if (!wndPtr) return 0;
707 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
708 switch(offset)
710 case GWW_ID: return wndPtr->wIDmenu;
711 #ifdef WINELIB32
712 case GWW_HWNDPARENT:
713 case GWW_HINSTANCE:
714 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
715 return 0;
716 #else
717 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
718 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
719 #endif
721 return 0;
725 /**********************************************************************
726 * WIN_GetWindowInstance
728 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
730 WND * wndPtr = WIN_FindWndPtr( hwnd );
731 if (!wndPtr) return (HINSTANCE)0;
732 return wndPtr->hInstance;
736 /**********************************************************************
737 * SetWindowWord (USER.134)
739 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
741 WORD *ptr, retval;
742 WND * wndPtr = WIN_FindWndPtr( hwnd );
743 if (!wndPtr) return 0;
744 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
745 else switch(offset)
747 #ifdef WINELIB32
748 case GWW_ID:
749 case GWW_HINSTANCE:
750 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
751 return 0;
752 #else
753 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
754 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
755 #endif
756 default: return 0;
758 retval = *ptr;
759 *ptr = newval;
760 return retval;
764 /**********************************************************************
765 * GetWindowLong (USER.135)
767 LONG GetWindowLong( HWND hwnd, short offset )
769 WND * wndPtr = WIN_FindWndPtr( hwnd );
770 if (!wndPtr) return 0;
771 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
772 switch(offset)
774 case GWL_STYLE: return wndPtr->dwStyle;
775 case GWL_EXSTYLE: return wndPtr->dwExStyle;
776 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
777 #ifdef WINELIB32
778 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
779 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
780 #endif
782 return 0;
786 /**********************************************************************
787 * SetWindowLong (USER.136)
789 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
791 LONG *ptr, retval;
792 WND * wndPtr = WIN_FindWndPtr( hwnd );
793 if (!wndPtr) return 0;
794 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
795 else switch(offset)
797 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
798 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
799 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
800 default: return 0;
802 retval = *ptr;
803 *ptr = newval;
804 return retval;
808 /*******************************************************************
809 * GetWindowText (USER.36)
811 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
813 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
814 (DWORD)lpString);
817 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
819 int len;
820 HANDLE handle;
822 /* We have to allocate a buffer on the USER heap */
823 /* to be able to pass its address to 16-bit code */
824 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
825 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
826 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
827 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
828 USER_HEAP_FREE( handle );
829 return len;
833 /*******************************************************************
834 * SetWindowText (USER.37)
836 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
838 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
841 void SetWindowText( HWND hwnd, LPSTR lpString )
843 HANDLE handle;
845 /* We have to allocate a buffer on the USER heap */
846 /* to be able to pass its address to 16-bit code */
847 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
848 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
849 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
850 USER_HEAP_FREE( handle );
854 /*******************************************************************
855 * GetWindowTextLength (USER.38)
857 int GetWindowTextLength(HWND hwnd)
859 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
863 /*******************************************************************
864 * IsWindow (USER.47)
866 BOOL IsWindow( HWND hwnd )
868 WND * wndPtr = WIN_FindWndPtr( hwnd );
869 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
873 /*****************************************************************
874 * GetParent (USER.46)
876 HWND GetParent(HWND hwnd)
878 WND *wndPtr = WIN_FindWndPtr(hwnd);
879 if (!wndPtr) return 0;
880 return (wndPtr->dwStyle & WS_CHILD) ?
881 wndPtr->hwndParent : wndPtr->hwndOwner;
885 /*****************************************************************
886 * WIN_GetTopParent
888 * Get the top-level parent for a child window.
890 HWND WIN_GetTopParent( HWND hwnd )
892 while (hwnd)
894 WND *wndPtr = WIN_FindWndPtr( hwnd );
895 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
896 else break;
898 return hwnd;
902 /*****************************************************************
903 * SetParent (USER.233)
905 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
907 HWND temp;
909 WND *wndPtr = WIN_FindWndPtr(hwndChild);
910 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
912 temp = wndPtr->hwndParent;
914 WIN_UnlinkWindow(hwndChild);
915 if (hwndNewParent)
916 wndPtr->hwndParent = hwndNewParent;
917 else
918 wndPtr->hwndParent = GetDesktopWindow();
919 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
921 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
923 return temp;
928 /*******************************************************************
929 * IsChild (USER.48)
931 BOOL IsChild( HWND parent, HWND child )
933 WND * wndPtr = WIN_FindWndPtr( child );
934 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
936 if (wndPtr->hwndParent == parent) return TRUE;
937 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
939 return FALSE;
943 /***********************************************************************
944 * IsWindowVisible (USER.49)
946 BOOL IsWindowVisible( HWND hwnd )
948 WND *wndPtr = WIN_FindWndPtr( hwnd );
949 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
951 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
952 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
954 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
959 /*******************************************************************
960 * GetTopWindow (USER.229)
962 HWND GetTopWindow( HWND hwnd )
964 WND * wndPtr = WIN_FindWndPtr( hwnd );
965 if (wndPtr) return wndPtr->hwndChild;
966 else return 0;
970 /*******************************************************************
971 * GetWindow (USER.262)
973 HWND GetWindow( HWND hwnd, WORD rel )
975 WND * wndPtr = WIN_FindWndPtr( hwnd );
976 if (!wndPtr) return 0;
977 switch(rel)
979 case GW_HWNDFIRST:
980 if (wndPtr->hwndParent)
982 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
983 return parentPtr->hwndChild;
985 else return 0;
987 case GW_HWNDLAST:
988 if (!wndPtr->hwndParent) return 0; /* Desktop window */
989 while (wndPtr->hwndNext)
991 hwnd = wndPtr->hwndNext;
992 wndPtr = WIN_FindWndPtr( hwnd );
994 return hwnd;
996 case GW_HWNDNEXT:
997 return wndPtr->hwndNext;
999 case GW_HWNDPREV:
1001 HWND hwndPrev;
1003 if (wndPtr->hwndParent)
1005 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1006 hwndPrev = parentPtr->hwndChild;
1008 else return 0; /* Desktop window */
1009 if (hwndPrev == hwnd) return 0;
1010 while (hwndPrev)
1012 wndPtr = WIN_FindWndPtr( hwndPrev );
1013 if (wndPtr->hwndNext == hwnd) break;
1014 hwndPrev = wndPtr->hwndNext;
1016 return hwndPrev;
1019 case GW_OWNER:
1020 return wndPtr->hwndOwner;
1022 case GW_CHILD:
1023 return wndPtr->hwndChild;
1025 return 0;
1029 /*******************************************************************
1030 * GetNextWindow (USER.230)
1032 HWND GetNextWindow( HWND hwnd, WORD flag )
1034 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1035 return GetWindow( hwnd, flag );
1038 /*******************************************************************
1039 * ShowOwnedPopups (USER.265)
1041 void ShowOwnedPopups( HWND owner, BOOL fShow )
1043 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1044 while (hwnd)
1046 WND *wnd = WIN_FindWndPtr(hwnd);
1047 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1048 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1049 hwnd = wnd->hwndNext;
1054 /*******************************************************************
1055 * GetLastActivePopup (USER.287)
1057 HWND GetLastActivePopup(HWND hwnd)
1059 WND *wndPtr;
1060 wndPtr = WIN_FindWndPtr(hwnd);
1061 if (wndPtr == NULL) return hwnd;
1062 return wndPtr->hwndLastActive;
1066 /*******************************************************************
1067 * EnumWindows (USER.54)
1069 BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
1071 HWND hwnd;
1072 WND *wndPtr;
1073 HWND *list, *pWnd;
1074 int count;
1076 /* We have to build a list of all windows first, to avoid */
1077 /* unpleasant side-effects, for instance if the callback */
1078 /* function changes the Z-order of the windows. */
1080 /* First count the windows */
1082 count = 0;
1083 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1085 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1086 count++;
1088 if (!count) return TRUE;
1090 /* Now build the list of all windows */
1092 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1093 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1095 wndPtr = WIN_FindWndPtr( hwnd );
1096 *pWnd++ = hwnd;
1099 /* Now call the callback function for every window */
1101 for (pWnd = list; count > 0; count--, pWnd++)
1103 /* Make sure that window still exists */
1104 if (!IsWindow(*pWnd)) continue;
1105 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1107 free( list );
1108 return TRUE;
1112 /**********************************************************************
1113 * EnumTaskWindows (USER.225)
1115 BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
1117 HWND hwnd;
1118 WND *wndPtr;
1119 HWND *list, *pWnd;
1120 HANDLE hQueue = GetTaskQueue( hTask );
1121 int count;
1123 /* This function is the same as EnumWindows(), */
1124 /* except for an added check on the window queue. */
1126 /* First count the windows */
1128 count = 0;
1129 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1131 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1132 if (wndPtr->hmemTaskQ == hQueue) count++;
1134 if (!count) return TRUE;
1136 /* Now build the list of all windows */
1138 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1139 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1141 wndPtr = WIN_FindWndPtr( hwnd );
1142 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1145 /* Now call the callback function for every window */
1147 for (pWnd = list; count > 0; count--, pWnd++)
1149 /* Make sure that window still exists */
1150 if (!IsWindow(*pWnd)) continue;
1151 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1153 free( list );
1154 return TRUE;
1158 /*******************************************************************
1159 * WIN_EnumChildWin
1161 * o hwnd is the first child to use, loop until all next windows
1162 * are processed
1164 * o call wdnenumprc
1166 * o call ourselves with the next child window
1169 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1171 WND *wndPtr;
1173 while (hwnd)
1175 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1176 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1177 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1178 hwnd=wndPtr->hwndNext;
1180 return 1;
1183 /*******************************************************************
1184 * EnumChildWindows (USER.55)
1186 * o gets the first child of hwnd
1188 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1190 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1192 WND *wndPtr;
1194 dprintf_enum(stddeb,"EnumChildWindows\n");
1196 if (hwnd == 0) return 0;
1197 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1198 hwnd = wndPtr->hwndChild;
1199 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1203 /*******************************************************************
1204 * AnyPopup [USER.52]
1206 BOOL AnyPopup()
1208 dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
1209 return FALSE;
1212 /*******************************************************************
1213 * FlashWindow [USER.105]
1215 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1217 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1218 return FALSE;
1222 /*******************************************************************
1223 * SetSysModalWindow [USER.188]
1225 HWND SetSysModalWindow(HWND hWnd)
1227 HWND hWndOldModal = hWndSysModal;
1228 hWndSysModal = hWnd;
1229 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1230 return hWndOldModal;
1234 /*******************************************************************
1235 * GetSysModalWindow [USER.189]
1237 HWND GetSysModalWindow(void)
1239 return hWndSysModal;