2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
15 #include "sysmetrics.h"
16 #include "cursoricon.h"
19 #include "nonclient.h"
22 #include "shm_main_blk.h"
26 /* #define DEBUG_WIN */
27 /* #define DEBUG_MENU */
30 static HWND hwndDesktop = 0;
31 static HWND hwndSysModal = 0;
33 static WORD wDragWidth = 4;
34 static WORD wDragHeight= 3;
36 extern HCURSOR CURSORICON_IconToCursor(HICON);
38 /***********************************************************************
41 * Return a pointer to the WND structure corresponding to a HWND.
43 WND * WIN_FindWndPtr( HWND hwnd )
47 if (!hwnd) return NULL;
48 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
49 if (ptr->dwMagic != WND_MAGIC) return NULL;
54 /***********************************************************************
57 * Return the X window associated to a window.
59 Window WIN_GetXWindow( HWND hwnd )
61 WND *wndPtr = WIN_FindWndPtr( hwnd );
62 while (wndPtr && !wndPtr->window)
64 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
66 return wndPtr ? wndPtr->window : 0;
70 /***********************************************************************
73 * Remove a window from the siblings linked list.
75 BOOL WIN_UnlinkWindow( HWND hwnd )
78 WND *parentPtr, *wndPtr;
80 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
81 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
83 curWndPtr = &parentPtr->hwndChild;
85 while (*curWndPtr != hwnd)
87 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
88 curWndPtr = &curPtr->hwndNext;
90 *curWndPtr = wndPtr->hwndNext;
95 /***********************************************************************
98 * Insert a window into the siblings linked list.
99 * The window is inserted after the specified window, which can also
100 * be specified as HWND_TOP or HWND_BOTTOM.
102 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
104 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
105 WND *wndPtr, *parentPtr;
107 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
108 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
110 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
112 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
113 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
116 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
117 hwndPtr = &nextPtr->hwndNext;
120 else /* Normal case */
122 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
123 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
125 if (!hwndPtr) return FALSE;
126 wndPtr->hwndNext = *hwndPtr;
132 /***********************************************************************
133 * WIN_FindWinToRepaint
135 * Find a window that needs repaint.
137 HWND WIN_FindWinToRepaint( HWND hwnd )
141 /* Note: the desktop window never gets WM_PAINT messages */
142 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
143 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
145 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
146 dprintf_win( stddeb, "WIN_FindWinToRepaint: "NPFMT", style %08lx\n",
147 hwnd, wndPtr->dwStyle );
148 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
150 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
152 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
154 if (wndPtr->hwndChild)
157 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
165 /***********************************************************************
166 * WIN_SendParentNotify
168 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
169 * the window has the WS_EX_NOPARENTNOTIFY style.
171 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
173 WND *wndPtr = WIN_FindWndPtr( hwnd );
175 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
177 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
179 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY,
180 MAKEWPARAM(event,idChild),
183 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event,
184 MAKELPARAM(LOWORD(lValue), idChild) );
186 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
191 /***********************************************************************
194 * Destroy storage associated to a window
196 static void WIN_DestroyWindow( HWND hwnd )
198 WND *wndPtr = WIN_FindWndPtr( hwnd );
199 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
203 DDE_DestroyWindow(hwnd);
204 #endif /* CONFIG_IPC */
206 if (!wndPtr || !classPtr) return;
207 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
208 wndPtr->dwMagic = 0; /* Mark it as invalid */
209 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
211 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
212 MSG_DecPaintCount( wndPtr->hmemTaskQ );
214 if (!(wndPtr->dwStyle & WS_CHILD))
216 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
218 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
219 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
220 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
221 classPtr->cWindows--;
222 USER_HEAP_FREE( hwnd );
226 /***********************************************************************
227 * WIN_CreateDesktopWindow
229 * Create the desktop window.
231 BOOL WIN_CreateDesktopWindow(void)
238 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
241 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
242 if (!hwndDesktop) return FALSE;
243 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
245 wndPtr->hwndNext = 0;
246 wndPtr->hwndChild = 0;
247 wndPtr->dwMagic = WND_MAGIC;
248 wndPtr->hwndParent = 0;
249 wndPtr->hwndOwner = 0;
250 wndPtr->hClass = hclass;
251 wndPtr->hInstance = 0;
252 wndPtr->rectWindow.left = 0;
253 wndPtr->rectWindow.top = 0;
254 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
255 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
256 wndPtr->rectClient = wndPtr->rectWindow;
257 wndPtr->rectNormal = wndPtr->rectWindow;
258 wndPtr->ptIconPos.x = -1;
259 wndPtr->ptIconPos.y = -1;
260 wndPtr->ptMaxPos.x = -1;
261 wndPtr->ptMaxPos.y = -1;
262 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
263 wndPtr->hrgnUpdate = 0;
264 wndPtr->hwndLastActive = hwndDesktop;
265 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
266 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
267 wndPtr->dwExStyle = 0;
269 wndPtr->hVScroll = 0;
270 wndPtr->hHScroll = 0;
274 wndPtr->window = rootWindow;
275 wndPtr->hSysMenu = 0;
277 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
278 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
279 if ((hdc = GetDC( hwndDesktop )) != 0)
281 SendMessage( hwndDesktop, WM_ERASEBKGND, (WPARAM)hdc, 0 );
282 ReleaseDC( hwndDesktop, hdc );
288 /***********************************************************************
289 * CreateWindow (USER.41)
291 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
292 DWORD style, INT x, INT y, INT width, INT height,
293 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
295 return CreateWindowEx( 0, className, windowName, style,
296 x, y, width, height, parent, menu, instance, data );
300 /***********************************************************************
301 * CreateWindowEx (USER.452)
303 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
304 DWORD style, INT x, INT y, INT width, INT height,
305 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
310 POINT maxSize, maxPos, minTrack, maxTrack;
311 CREATESTRUCT createStruct;
313 XSetWindowAttributes win_attr;
314 Atom XA_WM_DELETE_WINDOW;
316 /* FIXME: windowName and className should be SEGPTRs */
318 dprintf_win( stddeb, "CreateWindowEx: " );
319 if (HIWORD(windowName))
320 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
322 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
323 if (HIWORD(className))
324 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
326 dprintf_win( stddeb, "%04x ", LOWORD(className) );
328 dprintf_win(stddeb, "%08lx %08lx %d,%d %dx%d "NPFMT" "NPFMT" "NPFMT" %08lx\n",
329 exStyle, style, x, y, width, height,
330 parent, menu, instance, (DWORD)data);
332 if (x == CW_USEDEFAULT) x = y = 0;
333 if (width == CW_USEDEFAULT)
339 /* Find the parent and class */
343 /* Make sure parent is valid */
344 if (!IsWindow( parent )) {
345 dprintf_win(stddeb,"CreateWindowEx: Parent "NPFMT" is not a window\n", parent);
351 if (style & WS_CHILD) {
352 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
353 return 0; /* WS_CHILD needs a parent */
357 if (!(class = CLASS_FindClassByName( className, GetExePtr(instance),
360 fprintf(stderr,"CreateWindow BAD CLASSNAME " );
361 if (HIWORD(className)) fprintf( stderr, "'%s'\n",
362 (char *)PTR_SEG_TO_LIN(className) );
363 else fprintf( stderr, "%04x\n", LOWORD(className) );
367 /* Correct the window style */
369 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
370 style |= WS_CAPTION | WS_CLIPSIBLINGS;
371 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
373 /* Create the window structure */
375 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
377 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
381 /* Fill the structure */
383 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
384 wndPtr->hwndNext = 0;
385 wndPtr->hwndChild = 0;
387 wndPtr->dwMagic = WND_MAGIC;
388 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
389 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
390 wndPtr->hClass = class;
391 wndPtr->hInstance = instance;
392 wndPtr->ptIconPos.x = -1;
393 wndPtr->ptIconPos.y = -1;
394 wndPtr->ptMaxPos.x = -1;
395 wndPtr->ptMaxPos.y = -1;
396 wndPtr->hmemTaskQ = GetTaskQueue(0);
397 wndPtr->hrgnUpdate = 0;
398 wndPtr->hwndLastActive = hwnd;
399 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
400 wndPtr->dwStyle = style & ~WS_VISIBLE;
401 wndPtr->dwExStyle = exStyle;
405 wndPtr->hVScroll = 0;
406 wndPtr->hHScroll = 0;
407 wndPtr->hSysMenu = 0;
410 if (classPtr->wc.cbWndExtra)
411 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
412 classPtr->cWindows++;
414 /* Get class or window DC if needed */
416 if (classPtr->wc.style & CS_OWNDC)
417 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
418 else if (classPtr->wc.style & CS_CLASSDC)
419 wndPtr->hdce = classPtr->hdce;
423 /* Insert the window in the linked list */
425 WIN_LinkWindow( hwnd, HWND_TOP );
427 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
429 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
431 if (maxSize.x < width) width = maxSize.x;
432 if (maxSize.y < height) height = maxSize.y;
433 if (width <= 0) width = 1;
434 if (height <= 0) height = 1;
436 wndPtr->rectWindow.left = x;
437 wndPtr->rectWindow.top = y;
438 wndPtr->rectWindow.right = x + width;
439 wndPtr->rectWindow.bottom = y + height;
440 wndPtr->rectClient = wndPtr->rectWindow;
441 wndPtr->rectNormal = wndPtr->rectWindow;
443 /* Create the X window (only for top-level windows, and then only */
444 /* when there's no desktop window) */
446 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
448 if (Options.managed && ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
449 (exStyle & WS_EX_DLGMODALFRAME)))
451 win_attr.event_mask = ExposureMask | KeyPressMask |
452 KeyReleaseMask | PointerMotionMask |
453 ButtonPressMask | ButtonReleaseMask |
454 FocusChangeMask | StructureNotifyMask;
455 win_attr.override_redirect = FALSE;
456 wndPtr->flags |= WIN_MANAGED;
460 win_attr.event_mask = ExposureMask | KeyPressMask |
461 KeyReleaseMask | PointerMotionMask |
462 ButtonPressMask | ButtonReleaseMask |
464 win_attr.override_redirect = TRUE;
466 win_attr.colormap = COLOR_WinColormap;
467 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
468 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
469 win_attr.cursor = CURSORICON_XCursor;
470 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
471 width, height, 0, CopyFromParent,
472 InputOutput, CopyFromParent,
473 CWEventMask | CWOverrideRedirect |
474 CWColormap | CWCursor | CWSaveUnder |
475 CWBackingStore, &win_attr );
476 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
477 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
479 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
480 if (parent) /* Get window owner */
482 Window win = WIN_GetXWindow( parent );
483 if (win) XSetTransientForHint( display, wndPtr->window, win );
486 EVENT_RegisterWindow( wndPtr->window, hwnd );
489 if ((style & WS_CAPTION) && !(style & WS_CHILD))
491 if (menu) SetMenu(hwnd, menu);
492 else if (classPtr->wc.lpszMenuName)
493 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
495 else wndPtr->wIDmenu = (UINT)menu;
497 GetSystemMenu( hwnd, TRUE ); /* Create a copy of the system menu */
499 /* Send the WM_CREATE message */
501 createStruct.lpCreateParams = (LPSTR)data;
502 createStruct.hInstance = instance;
503 createStruct.hMenu = menu;
504 createStruct.hwndParent = parent;
505 createStruct.cx = width;
506 createStruct.cy = height;
509 createStruct.style = style;
510 createStruct.lpszName = windowName;
511 createStruct.lpszClass = className;
512 createStruct.dwExStyle = 0;
514 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct) );
517 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
522 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
523 NULL, NULL, NULL, &wndPtr->rectClient );
524 wmcreate = SendMessage(hwnd, WM_CREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct));
529 /* Abort window creation */
530 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
531 WIN_DestroyWindow( hwnd );
535 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
537 /* Show the window, maximizing or minimizing if needed */
539 if (wndPtr->dwStyle & WS_MINIMIZE)
541 wndPtr->dwStyle &= ~WS_MAXIMIZE;
542 WINPOS_FindIconPos( hwnd );
543 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
544 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
546 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
548 else if (wndPtr->dwStyle & WS_MAXIMIZE)
550 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
552 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
554 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
556 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
561 /***********************************************************************
562 * DestroyWindow (USER.53)
564 BOOL DestroyWindow( HWND hwnd )
569 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
573 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
574 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
575 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
577 /* Hide the window */
579 if (wndPtr->dwStyle & WS_VISIBLE)
580 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
581 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
582 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
584 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
586 /* Recursively destroy owned windows */
590 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
593 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
594 if (siblingPtr->hwndOwner == hwnd) break;
595 hwndSibling = siblingPtr->hwndNext;
597 if (hwndSibling) DestroyWindow( hwndSibling );
601 /* Send destroy messages and destroy children */
603 SendMessage( hwnd, WM_DESTROY, 0, 0 );
604 while (wndPtr->hwndChild) /* The child removes itself from the list */
605 DestroyWindow( wndPtr->hwndChild );
606 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
608 /* Destroy the window */
610 WIN_DestroyWindow( hwnd );
615 /***********************************************************************
616 * CloseWindow (USER.43)
618 BOOL CloseWindow(HWND hWnd)
620 WND * wndPtr = WIN_FindWndPtr(hWnd);
621 if (wndPtr->dwStyle & WS_CHILD) return TRUE;
622 ShowWindow(hWnd, SW_MINIMIZE);
627 /***********************************************************************
630 BOOL OpenIcon(HWND hWnd)
632 if (!IsIconic(hWnd)) return FALSE;
633 ShowWindow(hWnd, SW_SHOWNORMAL);
638 /***********************************************************************
639 * FindWindow (USER.50)
641 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
649 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
651 if (!hclass) return 0;
655 hwnd = GetTopWindow( hwndDesktop );
658 WND *wndPtr = WIN_FindWndPtr( hwnd );
659 if (!hclass || (wndPtr->hClass == hclass))
661 /* Found matching class */
662 if (!TitleMatch) return hwnd;
665 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
666 if (!strcmp( textPtr, TitleMatch )) return hwnd;
669 hwnd = wndPtr->hwndNext;
675 /**********************************************************************
676 * GetDesktopWindow (USER.286)
678 HWND GetDesktopWindow(void)
684 /**********************************************************************
685 * GetDesktopHwnd (USER.278)
687 * Exactly the same thing as GetDesktopWindow(), but not documented.
688 * Don't ask me why...
690 HWND GetDesktopHwnd(void)
696 /*******************************************************************
697 * EnableWindow (USER.34)
699 BOOL EnableWindow( HWND hwnd, BOOL enable )
703 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
704 if (enable && (wndPtr->dwStyle & WS_DISABLED))
707 wndPtr->dwStyle &= ~WS_DISABLED;
708 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
711 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
714 wndPtr->dwStyle |= WS_DISABLED;
715 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
716 SetFocus( 0 ); /* A disabled window can't have the focus */
717 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
718 ReleaseCapture(); /* A disabled window can't capture the mouse */
719 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
722 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
726 /***********************************************************************
727 * IsWindowEnabled (USER.35)
729 BOOL IsWindowEnabled(HWND hWnd)
733 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
734 return !(wndPtr->dwStyle & WS_DISABLED);
738 /**********************************************************************
739 * GetWindowWord (USER.133)
741 WORD GetWindowWord( HWND hwnd, short offset )
743 WND * wndPtr = WIN_FindWndPtr( hwnd );
744 if (!wndPtr) return 0;
745 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
748 case GWW_ID: return wndPtr->wIDmenu;
752 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
755 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
756 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
763 /**********************************************************************
764 * WIN_GetWindowInstance
766 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
768 WND * wndPtr = WIN_FindWndPtr( hwnd );
769 if (!wndPtr) return (HINSTANCE)0;
770 return wndPtr->hInstance;
774 /**********************************************************************
775 * SetWindowWord (USER.134)
777 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
780 WND * wndPtr = WIN_FindWndPtr( hwnd );
781 if (!wndPtr) return 0;
782 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
788 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
791 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
792 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
802 /**********************************************************************
803 * GetWindowLong (USER.135)
805 LONG GetWindowLong( HWND hwnd, short offset )
807 WND * wndPtr = WIN_FindWndPtr( hwnd );
808 if (!wndPtr) return 0;
809 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
812 case GWL_STYLE: return wndPtr->dwStyle;
813 case GWL_EXSTYLE: return wndPtr->dwExStyle;
814 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
816 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
817 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
824 /**********************************************************************
825 * SetWindowLong (USER.136)
827 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
830 WND * wndPtr = WIN_FindWndPtr( hwnd );
831 if (!wndPtr) return 0;
832 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
835 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
836 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
837 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
846 /*******************************************************************
847 * GetWindowText (USER.36)
849 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
851 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
855 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
860 /* We have to allocate a buffer on the USER heap */
861 /* to be able to pass its address to 16-bit code */
862 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
863 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
864 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
865 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
866 USER_HEAP_FREE( handle );
871 /*******************************************************************
872 * SetWindowText (USER.37)
874 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
876 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
879 void SetWindowText( HWND hwnd, LPCSTR lpString )
883 /* We have to allocate a buffer on the USER heap */
884 /* to be able to pass its address to 16-bit code */
885 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
886 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
887 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
888 USER_HEAP_FREE( handle );
892 /*******************************************************************
893 * GetWindowTextLength (USER.38)
895 int GetWindowTextLength(HWND hwnd)
897 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
901 /*******************************************************************
904 BOOL IsWindow( HWND hwnd )
906 WND * wndPtr = WIN_FindWndPtr( hwnd );
907 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
911 /*****************************************************************
912 * GetParent (USER.46)
914 HWND GetParent(HWND hwnd)
916 WND *wndPtr = WIN_FindWndPtr(hwnd);
917 if (!wndPtr) return 0;
918 return (wndPtr->dwStyle & WS_CHILD) ?
919 wndPtr->hwndParent : wndPtr->hwndOwner;
923 /*****************************************************************
926 * Get the top-level parent for a child window.
928 HWND WIN_GetTopParent( HWND hwnd )
932 WND *wndPtr = WIN_FindWndPtr( hwnd );
933 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
940 /*****************************************************************
941 * SetParent (USER.233)
943 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
947 WND *wndPtr = WIN_FindWndPtr(hwndChild);
948 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
950 temp = wndPtr->hwndParent;
952 WIN_UnlinkWindow(hwndChild);
954 wndPtr->hwndParent = hwndNewParent;
956 wndPtr->hwndParent = GetDesktopWindow();
957 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
959 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
966 /*******************************************************************
969 BOOL IsChild( HWND parent, HWND child )
971 WND * wndPtr = WIN_FindWndPtr( child );
972 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
974 if (wndPtr->hwndParent == parent) return TRUE;
975 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
981 /***********************************************************************
982 * IsWindowVisible (USER.49)
984 BOOL IsWindowVisible( HWND hwnd )
986 WND *wndPtr = WIN_FindWndPtr( hwnd );
987 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
989 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
990 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
992 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
997 /*******************************************************************
998 * GetTopWindow (USER.229)
1000 HWND GetTopWindow( HWND hwnd )
1002 WND * wndPtr = WIN_FindWndPtr( hwnd );
1003 if (wndPtr) return wndPtr->hwndChild;
1008 /*******************************************************************
1009 * GetWindow (USER.262)
1011 HWND GetWindow( HWND hwnd, WORD rel )
1013 WND * wndPtr = WIN_FindWndPtr( hwnd );
1014 if (!wndPtr) return 0;
1018 if (wndPtr->hwndParent)
1020 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1021 return parentPtr->hwndChild;
1026 if (!wndPtr->hwndParent) return 0; /* Desktop window */
1027 while (wndPtr->hwndNext)
1029 hwnd = wndPtr->hwndNext;
1030 wndPtr = WIN_FindWndPtr( hwnd );
1035 return wndPtr->hwndNext;
1041 if (wndPtr->hwndParent)
1043 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1044 hwndPrev = parentPtr->hwndChild;
1046 else return 0; /* Desktop window */
1047 if (hwndPrev == hwnd) return 0;
1050 wndPtr = WIN_FindWndPtr( hwndPrev );
1051 if (wndPtr->hwndNext == hwnd) break;
1052 hwndPrev = wndPtr->hwndNext;
1058 return wndPtr->hwndOwner;
1061 return wndPtr->hwndChild;
1067 /*******************************************************************
1068 * GetNextWindow (USER.230)
1070 HWND GetNextWindow( HWND hwnd, WORD flag )
1072 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1073 return GetWindow( hwnd, flag );
1076 /*******************************************************************
1077 * ShowOwnedPopups (USER.265)
1079 void ShowOwnedPopups( HWND owner, BOOL fShow )
1081 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1084 WND *wnd = WIN_FindWndPtr(hwnd);
1085 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1086 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1087 hwnd = wnd->hwndNext;
1092 /*******************************************************************
1093 * GetLastActivePopup (USER.287)
1095 HWND GetLastActivePopup(HWND hwnd)
1098 wndPtr = WIN_FindWndPtr(hwnd);
1099 if (wndPtr == NULL) return hwnd;
1100 return wndPtr->hwndLastActive;
1104 /*******************************************************************
1105 * EnumWindows (USER.54)
1107 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
1114 /* We have to build a list of all windows first, to avoid */
1115 /* unpleasant side-effects, for instance if the callback */
1116 /* function changes the Z-order of the windows. */
1118 /* First count the windows */
1121 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1123 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1126 if (!count) return TRUE;
1128 /* Now build the list of all windows */
1130 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1131 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1133 wndPtr = WIN_FindWndPtr( hwnd );
1137 /* Now call the callback function for every window */
1139 for (pWnd = list; count > 0; count--, pWnd++)
1141 /* Make sure that window still exists */
1142 if (!IsWindow(*pWnd)) continue;
1143 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1150 /**********************************************************************
1151 * EnumTaskWindows (USER.225)
1153 BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
1158 HANDLE hQueue = GetTaskQueue( hTask );
1161 /* This function is the same as EnumWindows(), */
1162 /* except for an added check on the window queue. */
1164 /* First count the windows */
1167 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1169 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1170 if (wndPtr->hmemTaskQ == hQueue) count++;
1172 if (!count) return TRUE;
1174 /* Now build the list of all windows */
1176 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1177 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1179 wndPtr = WIN_FindWndPtr( hwnd );
1180 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1183 /* Now call the callback function for every window */
1185 for (pWnd = list; count > 0; count--, pWnd++)
1187 /* Make sure that window still exists */
1188 if (!IsWindow(*pWnd)) continue;
1189 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1196 /*******************************************************************
1199 * o hwnd is the first child to use, loop until all next windows
1204 * o call ourselves with the next child window
1207 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1214 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1215 hwndN=wndPtr->hwndNext; /* storing hwnd is a way to avoid.. */
1216 hwndCh=wndPtr->hwndChild; /* ..side effects after wndenumprc */
1217 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1218 if (IsWindow(hwndCh)) /* to prevent too early termination */
1219 if (!WIN_EnumChildWin(hwndCh, wndenumprc, lParam)) return 0;
1225 /*******************************************************************
1226 * EnumChildWindows (USER.55)
1228 * o gets the first child of hwnd
1230 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1232 BOOL EnumChildWindows(HWND hwnd, WNDENUMPROC wndenumprc, LPARAM lParam)
1236 dprintf_enum(stddeb,"EnumChildWindows\n");
1238 if (hwnd == 0) return 0;
1239 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1240 hwnd = wndPtr->hwndChild;
1241 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1245 /*******************************************************************
1246 * AnyPopup [USER.52]
1250 WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
1251 HWND hwnd = wndPtr->hwndChild;
1253 for( ; hwnd ; hwnd = wndPtr->hwndNext )
1255 wndPtr = WIN_FindWndPtr(hwnd);
1256 if(wndPtr->hwndOwner)
1257 if(wndPtr->dwStyle & WS_VISIBLE)
1263 /*******************************************************************
1264 * FlashWindow [USER.105]
1266 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1268 WND *wndPtr = WIN_FindWndPtr(hWnd);
1270 dprintf_win(stddeb,"FlashWindow: "NPFMT"\n", hWnd);
1272 if (!wndPtr) return FALSE;
1274 if (wndPtr->dwStyle & WS_MINIMIZE)
1276 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1278 HDC hDC = GetDC(hWnd);
1280 if (!SendMessage( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1281 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1283 ReleaseDC( hWnd, hDC );
1284 wndPtr->flags |= WIN_NCACTIVATED;
1288 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1289 RDW_UPDATENOW | RDW_FRAME );
1290 wndPtr->flags &= ~WIN_NCACTIVATED;
1297 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1298 else wparam = (hWnd == GetActiveWindow());
1300 SendMessage( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1306 /*******************************************************************
1307 * SetSysModalWindow [USER.188]
1309 HWND SetSysModalWindow(HWND hWnd)
1311 HWND hWndOldModal = hwndSysModal;
1312 hwndSysModal = hWnd;
1313 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1314 return hWndOldModal;
1318 /*******************************************************************
1319 * GetSysModalWindow [USER.189]
1321 HWND GetSysModalWindow(void)
1323 return hwndSysModal;
1326 /*******************************************************************
1329 * recursively find a child that contains spDragInfo->pt point
1330 * and send WM_QUERYDROPOBJECT
1332 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1335 BOOL wParam,bResult = 0;
1337 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1338 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1339 RECT tempRect; /* this sucks */
1341 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1343 pt = ptrDragInfo->pt;
1345 GetWindowRect(hQueryWnd,&tempRect);
1347 if( !PtInRect(&tempRect,pt) ||
1348 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1351 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1353 tempRect = ptrQueryWnd->rectClient;
1354 if(ptrQueryWnd->dwStyle & WS_CHILD)
1355 MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
1357 if( PtInRect(&tempRect,pt) )
1360 ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
1362 for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
1363 if( ptrWnd->dwStyle & WS_VISIBLE )
1365 GetWindowRect(hWnd,&tempRect);
1367 if( PtInRect(&tempRect,pt) )
1372 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
1373 (int)ptrWnd->rectWindow.left,(int)ptrWnd->rectWindow.top,
1374 (int)ptrWnd->rectWindow.right,(int)ptrWnd->rectWindow.bottom);
1376 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
1379 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1380 bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
1382 if(bResult) return bResult;
1388 ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
1390 ptrDragInfo->hScope = hQueryWnd;
1392 bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
1393 (WPARAM)wParam ,(LPARAM) spDragInfo );
1395 ptrDragInfo->pt = pt;
1400 /*******************************************************************
1401 * DragDetect ( USER.465 )
1404 BOOL DragDetect(HWND hWnd, POINT pt)
1409 rect.left = pt.x - wDragWidth;
1410 rect.right = pt.x + wDragWidth;
1412 rect.top = pt.y - wDragHeight;
1413 rect.bottom = pt.y + wDragHeight;
1419 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1421 if( msg.message == WM_LBUTTONUP )
1426 if( msg.message == WM_MOUSEMOVE )
1428 POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
1429 if( !PtInRect( &rect, pt ) )
1442 /******************************************************************************
1443 * DragObject ( USER.464 )
1446 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1447 WORD szList , HCURSOR hCursor)
1450 LPDRAGINFO lpDragInfo;
1452 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1453 HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1454 WND *wndPtr = WIN_FindWndPtr(hWnd);
1457 HCURSOR hCurrentCursor = 0;
1458 HWND hCurrentWnd = 0;
1461 lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
1462 spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
1464 if( !lpDragInfo || !spDragInfo ) return 0L;
1466 hBummer = LoadCursor(0,IDC_BUMMER);
1468 if( !hBummer || !wndPtr )
1470 GlobalFree(hDragInfo);
1476 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1478 GlobalFree(hDragInfo);
1482 if( hDragCursor == hCursor ) hDragCursor = 0;
1483 else hCursor = hDragCursor;
1485 hOldCursor = SetCursor(hDragCursor);
1488 lpDragInfo->hWnd = hWnd;
1489 lpDragInfo->hScope = 0;
1490 lpDragInfo->wFlags = wObj;
1491 lpDragInfo->hList = szList; /* near pointer! */
1492 lpDragInfo->hOfStruct = hOfStruct;
1502 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1505 *(lpDragInfo+1) = *lpDragInfo;
1507 lpDragInfo->pt = msg.pt;
1509 /* update DRAGINFO struct */
1510 dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
1512 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1513 hCurrentCursor = hCursor;
1516 hCurrentCursor = hBummer;
1517 lpDragInfo->hScope = 0;
1519 if( hCurrentCursor )
1520 SetCursor(hCurrentCursor);
1522 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1524 /* send WM_DRAGLOOP */
1525 SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1526 (LPARAM) spDragInfo );
1527 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1528 if( hCurrentWnd != lpDragInfo->hScope )
1531 SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
1532 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1533 HIWORD(spDragInfo)) );
1534 hCurrentWnd = lpDragInfo->hScope;
1536 SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1540 SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1543 /* check if we're done */
1544 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1553 SetCursor(hOldCursor);
1555 DestroyCursor(hDragCursor);
1558 if( hCurrentCursor != hBummer )
1559 dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
1560 (WPARAM)hWnd, (LPARAM)spDragInfo );
1561 GlobalFree(hDragInfo);