2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xatom.h>
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
24 #include "nonclient.h"
29 #include "shm_main_blk.h"
31 #include "clipboard.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
39 static WND *pWndDesktop = NULL;
41 static HWND hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
47 extern HWND32 CARET_GetHwnd(void);
48 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
49 extern void WINPOS_CheckActive(HWND32);
51 /***********************************************************************
54 * Return a pointer to the WND structure corresponding to a HWND.
56 WND * WIN_FindWndPtr( HWND32 hwnd )
60 if (!hwnd || HIWORD(hwnd)) return NULL;
61 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
62 if (ptr->dwMagic != WND_MAGIC) return NULL;
63 if (ptr->hwndSelf != hwnd)
65 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
66 hwnd, ptr->hwndSelf );
73 /***********************************************************************
76 * Dump the content of a window structure to stderr.
78 void WIN_DumpWindow( HWND32 hwnd )
84 if (!(ptr = WIN_FindWndPtr( hwnd )))
86 fprintf( stderr, "%04x is not a window handle\n", hwnd );
90 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
91 strcpy( className, "#NULL#" );
93 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
95 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
96 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
97 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
98 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
99 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
100 ptr->next, ptr->child, ptr->parent, ptr->owner,
101 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
102 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
103 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
104 ptr->text ? ptr->text : "",
105 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
106 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
107 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
108 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
109 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
111 if (ptr->class->cbWndExtra)
113 fprintf( stderr, "extra bytes:" );
114 for (i = 0; i < ptr->class->cbWndExtra; i++)
115 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
116 fprintf( stderr, "\n" );
118 fprintf( stderr, "\n" );
122 /***********************************************************************
125 * Walk the windows tree and print each window on stderr.
127 void WIN_WalkWindows( HWND32 hwnd, int indent )
132 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
135 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
139 if (!indent) /* first time around */
140 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
141 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
145 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
147 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
149 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
150 (DWORD)ptr, ptr->hmemTaskQ, className,
151 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
153 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
159 /***********************************************************************
162 * Return the X window associated to a window.
164 Window WIN_GetXWindow( HWND32 hwnd )
166 WND *wndPtr = WIN_FindWndPtr( hwnd );
167 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
168 return wndPtr ? wndPtr->window : 0;
172 /***********************************************************************
175 * Remove a window from the siblings linked list.
177 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
179 WND *wndPtr, **ppWnd;
181 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182 ppWnd = &wndPtr->parent->child;
183 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
184 *ppWnd = wndPtr->next;
189 /***********************************************************************
192 * Insert a window into the siblings linked list.
193 * The window is inserted after the specified window, which can also
194 * be specified as HWND_TOP or HWND_BOTTOM.
196 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
198 WND *wndPtr, **ppWnd;
200 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
202 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
204 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
205 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
206 while (*ppWnd) ppWnd = &(*ppWnd)->next;
208 else /* Normal case */
210 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
211 if (!afterPtr) return FALSE;
212 ppWnd = &afterPtr->next;
214 wndPtr->next = *ppWnd;
220 /***********************************************************************
221 * WIN_FindWinToRepaint
223 * Find a window that needs repaint.
225 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
228 WND *pWnd = pWndDesktop;
230 /* Note: the desktop window never gets WM_PAINT messages
231 * The real reason why is because Windows DesktopWndProc
232 * does ValidateRgn inside WM_ERASEBKGND handler.
235 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
237 for ( ; pWnd ; pWnd = pWnd->next )
239 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
241 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
245 if ((pWnd->hmemTaskQ == hQueue) &&
246 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
249 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
255 hwndRet = pWnd->hwndSelf;
257 /* look among siblings if we got a transparent window */
258 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
259 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
263 if (pWnd) hwndRet = pWnd->hwndSelf;
264 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
269 /***********************************************************************
270 * WIN_SendParentNotify
272 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
273 * the window has the WS_EX_NOPARENTNOTIFY style.
275 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
277 LPPOINT16 lppt = (LPPOINT16)&lValue;
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
279 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
281 /* if lValue contains cursor coordinates they have to be
282 * mapped to the client area of parent window */
284 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
288 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
289 !(wndPtr->dwStyle & WS_CHILD)) break;
293 lppt->x += wndPtr->rectClient.left;
294 lppt->y += wndPtr->rectClient.top;
297 wndPtr = wndPtr->parent;
298 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
299 MAKEWPARAM( event, idChild ), lValue );
304 /***********************************************************************
307 * Destroy storage associated to a window. "Internals" p.358
309 static void WIN_DestroyWindow( WND* wndPtr )
311 HWND hwnd = wndPtr->hwndSelf;
314 dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
318 DDE_DestroyWindow(wndPtr->hwndSelf);
319 #endif /* CONFIG_IPC */
321 /* free child windows */
323 pNext = wndPtr->child;
324 while( (pWnd = pNext) )
327 WIN_DestroyWindow( pWnd );
330 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
332 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
334 WINPOS_CheckActive( hwnd );
335 if( hwnd == GetCapture32()) ReleaseCapture();
337 /* free resources associated with the window */
339 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
340 PROPERTY_RemoveWindowProps( wndPtr );
342 wndPtr->dwMagic = 0; /* Mark it as invalid */
343 wndPtr->hwndSelf = 0;
345 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
347 if (wndPtr->hrgnUpdate) DeleteObject32( wndPtr->hrgnUpdate );
348 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
351 /* toss stale messages from the queue */
353 if( wndPtr->hmemTaskQ )
356 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
358 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
359 QUEUE_RemoveMsg(msgQ, pos);
360 wndPtr->hmemTaskQ = 0;
363 if (!(wndPtr->dwStyle & WS_CHILD))
364 if (wndPtr->wIDmenu) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
365 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
366 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
367 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
369 WINPROC_FreeProc( wndPtr->winproc );
371 wndPtr->class->cWindows--;
372 wndPtr->class = NULL;
374 USER_HEAP_FREE( hwnd );
377 /***********************************************************************
378 * WIN_ResetQueueWindows
380 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
387 if (wnd->hmemTaskQ == hQueue)
388 if( hNew ) wnd->hmemTaskQ = hNew;
389 else DestroyWindow( wnd->hwndSelf );
390 else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
395 /***********************************************************************
396 * WIN_CreateDesktopWindow
398 * Create the desktop window.
400 BOOL32 WIN_CreateDesktopWindow(void)
405 dprintf_win(stddeb,"Creating desktop window\n");
407 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
410 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
411 if (!hwndDesktop) return FALSE;
412 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
414 pWndDesktop->next = NULL;
415 pWndDesktop->child = NULL;
416 pWndDesktop->parent = NULL;
417 pWndDesktop->owner = NULL;
418 pWndDesktop->class = class;
419 pWndDesktop->winproc = NULL;
420 pWndDesktop->dwMagic = WND_MAGIC;
421 pWndDesktop->hwndSelf = hwndDesktop;
422 pWndDesktop->hInstance = 0;
423 pWndDesktop->rectWindow.left = 0;
424 pWndDesktop->rectWindow.top = 0;
425 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
426 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
427 pWndDesktop->rectClient = pWndDesktop->rectWindow;
428 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
429 pWndDesktop->ptIconPos.x = -1;
430 pWndDesktop->ptIconPos.y = -1;
431 pWndDesktop->ptMaxPos.x = -1;
432 pWndDesktop->ptMaxPos.y = -1;
433 pWndDesktop->text = NULL;
434 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
435 pWndDesktop->hrgnUpdate = 0;
436 pWndDesktop->hwndLastActive = hwndDesktop;
437 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
439 pWndDesktop->dwExStyle = 0;
440 pWndDesktop->dce = NULL;
441 pWndDesktop->pVScroll = NULL;
442 pWndDesktop->pHScroll = NULL;
443 pWndDesktop->pProp = NULL;
444 pWndDesktop->wIDmenu = 0;
445 pWndDesktop->flags = 0;
446 pWndDesktop->window = rootWindow;
447 pWndDesktop->hSysMenu = 0;
448 pWndDesktop->userdata = 0;
450 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
451 EVENT_RegisterWindow( pWndDesktop );
452 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
453 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
458 /***********************************************************************
461 * Implementation of CreateWindowEx().
463 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
468 HWND16 hwnd, hwndLinkAfter;
469 POINT16 maxSize, maxPos, minTrack, maxTrack;
472 dprintf_win( stddeb, "CreateWindowEx: " );
473 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
474 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
475 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
476 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
478 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
479 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
480 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
482 /* Find the parent window */
486 /* Make sure parent is valid */
487 if (!IsWindow( cs->hwndParent ))
489 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
493 else if (cs->style & WS_CHILD)
495 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
496 return 0; /* WS_CHILD needs a parent */
499 /* Find the window class */
501 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
502 GetExePtr(cs->hInstance) )))
505 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
506 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
510 /* Fix the coordinates */
512 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
513 if (cs->cx == CW_USEDEFAULT32)
515 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
523 /* Create the window structure */
525 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
526 - sizeof(wndPtr->wExtra) )))
528 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
532 /* Fill the window structure */
534 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
536 wndPtr->child = NULL;
538 if (cs->style & WS_CHILD)
540 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
541 wndPtr->owner = NULL;
545 wndPtr->parent = pWndDesktop;
546 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
547 wndPtr->owner = NULL;
549 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
553 wndPtr->class = classPtr;
554 wndPtr->winproc = NULL;
555 wndPtr->dwMagic = WND_MAGIC;
556 wndPtr->hwndSelf = hwnd;
557 wndPtr->hInstance = cs->hInstance;
558 wndPtr->ptIconPos.x = -1;
559 wndPtr->ptIconPos.y = -1;
560 wndPtr->ptMaxPos.x = -1;
561 wndPtr->ptMaxPos.y = -1;
563 wndPtr->hmemTaskQ = GetTaskQueue(0);
564 wndPtr->hrgnUpdate = 0;
565 wndPtr->hwndLastActive = hwnd;
566 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
567 wndPtr->dwExStyle = cs->dwExStyle;
570 wndPtr->pVScroll = NULL;
571 wndPtr->pHScroll = NULL;
572 wndPtr->pProp = NULL;
573 wndPtr->hSysMenu = MENU_GetDefSysMenu();
574 wndPtr->userdata = 0;
576 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
578 /* Call the WH_CBT hook */
580 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
582 if (HOOK_IsHooked( WH_CBT ))
584 CBT_CREATEWND32A cbtc;
587 cbtc.hwndInsertAfter = hwndLinkAfter;
588 wmcreate = !HOOK_CallHooks32A( WH_CBT, HCBT_CREATEWND, hwnd,
592 dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
593 USER_HEAP_FREE( hwnd );
598 /* Set the window procedure */
600 classPtr->cWindows++;
601 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
603 /* Correct the window style */
605 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
607 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
608 wndPtr->flags |= WIN_NEED_SIZE;
610 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
612 /* Get class or window DC if needed */
614 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
615 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
616 else wndPtr->dce = NULL;
618 /* Insert the window in the linked list */
620 WIN_LinkWindow( hwnd, hwndLinkAfter );
622 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
624 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
626 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
627 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
628 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
629 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
630 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
632 if (cs->cx <= 0) cs->cx = 1;
633 if (cs->cy <= 0) cs->cy = 1;
635 wndPtr->rectWindow.left = cs->x;
636 wndPtr->rectWindow.top = cs->y;
637 wndPtr->rectWindow.right = cs->x + cs->cx;
638 wndPtr->rectWindow.bottom = cs->y + cs->cy;
639 wndPtr->rectClient = wndPtr->rectWindow;
640 wndPtr->rectNormal = wndPtr->rectWindow;
642 /* Create the X window (only for top-level windows, and then only */
643 /* when there's no desktop window) */
645 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
647 XSetWindowAttributes win_attr;
649 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
650 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
652 win_attr.event_mask = ExposureMask | KeyPressMask |
653 KeyReleaseMask | PointerMotionMask |
654 ButtonPressMask | ButtonReleaseMask |
655 FocusChangeMask | StructureNotifyMask;
656 win_attr.override_redirect = FALSE;
657 wndPtr->flags |= WIN_MANAGED;
661 win_attr.event_mask = ExposureMask | KeyPressMask |
662 KeyReleaseMask | PointerMotionMask |
663 ButtonPressMask | ButtonReleaseMask |
664 FocusChangeMask | StructureNotifyMask;
665 win_attr.override_redirect = TRUE;
667 win_attr.colormap = COLOR_GetColormap();
668 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
669 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
670 win_attr.cursor = CURSORICON_XCursor;
671 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
672 cs->cx, cs->cy, 0, CopyFromParent,
673 InputOutput, CopyFromParent,
674 CWEventMask | CWOverrideRedirect |
675 CWColormap | CWCursor | CWSaveUnder |
676 CWBackingStore, &win_attr );
678 if ((wndPtr->flags & WIN_MANAGED) &&
679 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
681 XSizeHints* size_hints = XAllocSizeHints();
685 size_hints->min_width = size_hints->max_width = cs->cx;
686 size_hints->min_height = size_hints->max_height = cs->cy;
687 size_hints->flags = (PSize | PMinSize | PMaxSize);
688 XSetWMSizeHints( display, wndPtr->window, size_hints,
689 XA_WM_NORMAL_HINTS );
694 if (cs->hwndParent) /* Get window owner */
696 Window win = WIN_GetXWindow( cs->hwndParent );
697 if (win) XSetTransientForHint( display, wndPtr->window, win );
699 EVENT_RegisterWindow( wndPtr );
702 /* Set the window menu */
704 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
706 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
709 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
710 if (classPtr->menuNameA)
711 cs->hMenu = HIWORD(classPtr->menuNameA) ?
712 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
713 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
715 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
716 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
719 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
721 else wndPtr->wIDmenu = (UINT)cs->hMenu;
723 /* Send the WM_CREATE message
724 * Perhaps we shouldn't allow width/height changes as well.
725 * See p327 in "Internals".
728 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
731 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
734 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
735 NULL, NULL, 0, &wndPtr->rectClient );
736 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
737 maxPos.y - wndPtr->rectWindow.top);
738 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
743 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
746 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
747 NULL, NULL, 0, &wndPtr->rectClient );
748 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
749 maxPos.y - wndPtr->rectWindow.top);
750 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
756 /* Abort window creation */
757 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
758 WIN_UnlinkWindow( hwnd );
759 WIN_DestroyWindow( wndPtr );
763 /* Send the size messages */
765 if (!(wndPtr->flags & WIN_NEED_SIZE))
768 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
769 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
770 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
771 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
772 wndPtr->rectClient.top ));
775 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
776 if (!IsWindow(hwnd)) return 0;
778 /* Show the window, maximizing or minimizing if needed */
780 if (wndPtr->dwStyle & WS_MINIMIZE)
782 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
784 wndPtr->dwStyle &= ~WS_MAXIMIZE;
785 WINPOS_FindIconPos( hwnd );
786 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
787 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
788 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
790 else if (wndPtr->dwStyle & WS_MAXIMIZE)
792 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
794 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
795 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
796 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
799 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
801 /* Call WH_SHELL hook */
803 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
804 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
806 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
811 /***********************************************************************
812 * CreateWindow16 (USER.41)
814 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
815 DWORD style, INT16 x, INT16 y, INT16 width,
816 INT16 height, HWND16 parent, HMENU16 menu,
817 HINSTANCE16 instance, LPVOID data )
819 return CreateWindowEx16( 0, className, windowName, style,
820 x, y, width, height, parent, menu, instance, data );
824 /***********************************************************************
825 * CreateWindowEx16 (USER.452)
827 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
828 DWORD style, INT16 x, INT16 y, INT16 width,
829 INT16 height, HWND16 parent, HMENU16 menu,
830 HINSTANCE16 instance, LPVOID data )
835 /* Find the class atom */
837 if (!(classAtom = GlobalFindAtom32A( className )))
839 fprintf( stderr, "CreateWindowEx16: bad class name " );
840 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
841 else fprintf( stderr, "'%s'\n", className );
845 /* Fix the coordinates */
847 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
848 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
849 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
850 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
852 /* Create the window */
854 cs.lpCreateParams = data;
855 cs.hInstance = (HINSTANCE32)instance;
856 cs.hMenu = (HMENU32)menu;
857 cs.hwndParent = (HWND32)parent;
859 cs.lpszName = windowName;
860 cs.lpszClass = className;
861 cs.dwExStyle = exStyle;
862 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
866 /***********************************************************************
867 * CreateWindowEx32A (USER32.82)
869 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
870 DWORD style, INT32 x, INT32 y, INT32 width,
871 INT32 height, HWND32 parent, HMENU32 menu,
872 HINSTANCE32 instance, LPVOID data )
877 /* Find the class atom */
879 if (!(classAtom = GlobalFindAtom32A( className )))
881 fprintf( stderr, "CreateWindowEx32A: bad class name " );
882 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
883 else fprintf( stderr, "'%s'\n", className );
887 /* Create the window */
889 cs.lpCreateParams = data;
890 cs.hInstance = instance;
892 cs.hwndParent = parent;
898 cs.lpszName = windowName;
899 cs.lpszClass = className;
900 cs.dwExStyle = exStyle;
901 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
905 /***********************************************************************
906 * CreateWindowEx32W (USER32.83)
908 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
909 DWORD style, INT32 x, INT32 y, INT32 width,
910 INT32 height, HWND32 parent, HMENU32 menu,
911 HINSTANCE32 instance, LPVOID data )
916 /* Find the class atom */
918 if (!(classAtom = GlobalFindAtom32W( className )))
920 if (HIWORD(className))
922 LPSTR cn = STRING32_DupUniToAnsi(className);
923 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
927 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
931 /* Create the window */
933 cs.lpCreateParams = data;
934 cs.hInstance = instance;
936 cs.hwndParent = parent;
942 cs.lpszName = windowName;
943 cs.lpszClass = className;
944 cs.dwExStyle = exStyle;
945 /* Note: we rely on the fact that CREATESTRUCT32A and */
946 /* CREATESTRUCT32W have the same layout. */
947 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
951 /***********************************************************************
954 static void WIN_CheckFocus( WND* pWnd )
956 if( GetFocus16() == pWnd->hwndSelf )
957 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
960 /***********************************************************************
963 static void WIN_SendDestroyMsg( WND* pWnd )
967 WIN_CheckFocus(pWnd);
969 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
970 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
972 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
974 if( !IsWindow(pWnd->hwndSelf) )
976 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
980 pChild = pWnd->child;
983 WIN_SendDestroyMsg( pChild );
984 pChild = pChild->next;
986 WIN_CheckFocus(pWnd);
990 /***********************************************************************
991 * DestroyWindow (USER.53)
993 BOOL DestroyWindow( HWND hwnd )
997 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
1001 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1002 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1006 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1009 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1011 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1012 /* FIXME: clean up palette - see "Internals" p.352 */
1015 if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1016 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1017 if( !IsWindow(hwnd) ) return TRUE;
1019 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1021 /* Hide the window */
1023 if (wndPtr->dwStyle & WS_VISIBLE)
1025 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1026 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
1027 ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1028 if( !IsWindow(hwnd) ) return TRUE;
1031 /* Recursively destroy owned windows */
1033 if( !(wndPtr->dwStyle & WS_CHILD) )
1037 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1040 if (siblingPtr->owner == wndPtr)
1041 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1044 siblingPtr->owner = NULL;
1045 siblingPtr = siblingPtr->next;
1047 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1051 WINPOS_ActivateOtherWindow(wndPtr);
1053 if( wndPtr->owner &&
1054 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1055 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1058 /* Send destroy messages */
1060 WIN_SendDestroyMsg( wndPtr );
1061 if( !IsWindow(hwnd) ) return TRUE;
1063 /* Unlink now so we won't bother with the children later on */
1065 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1067 /* Destroy the window storage */
1069 WIN_DestroyWindow( wndPtr );
1074 /***********************************************************************
1075 * CloseWindow (USER.43)
1077 BOOL CloseWindow(HWND hWnd)
1079 WND * wndPtr = WIN_FindWndPtr(hWnd);
1080 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
1081 ShowWindow(hWnd, SW_MINIMIZE);
1086 /***********************************************************************
1087 * OpenIcon (USER.44)
1089 BOOL OpenIcon(HWND hWnd)
1091 if (!IsIconic(hWnd)) return FALSE;
1092 ShowWindow(hWnd, SW_SHOWNORMAL);
1097 /***********************************************************************
1100 * Implementation of FindWindow() and FindWindowEx().
1102 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1106 CLASS *pClass = NULL;
1110 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1113 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1115 else if (pWnd->parent != pWndDesktop) return 0;
1120 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1123 if (!pWnd) return 0;
1125 /* For a child window, all siblings will have the same hInstance, */
1126 /* so we can look for the class once and for all. */
1128 if (className && (pWnd->dwStyle & WS_CHILD))
1130 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1134 for ( ; pWnd; pWnd = pWnd->next)
1136 if (className && !(pWnd->dwStyle & WS_CHILD))
1138 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1139 continue; /* Skip this window */
1141 if (pClass && (pWnd->class != pClass))
1142 continue; /* Not the right class */
1144 /* Now check the title */
1146 if (!title) return pWnd->hwndSelf;
1147 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1154 /***********************************************************************
1155 * FindWindow16 (USER.50)
1157 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1159 return FindWindowEx16( 0, 0, className, title );
1163 /***********************************************************************
1164 * FindWindowEx16 (USER.427)
1166 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1167 SEGPTR className, LPCSTR title )
1173 /* If the atom doesn't exist, then no class */
1174 /* with this name exists either. */
1175 if (!(atom = GlobalFindAtom16( className ))) return 0;
1177 return WIN_FindWindow( parent, child, atom, title );
1181 /***********************************************************************
1182 * FindWindow32A (USER32.197)
1184 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1186 return FindWindowEx32A( 0, 0, className, title );
1190 /***********************************************************************
1191 * FindWindowEx32A (USER32.198)
1193 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1194 LPCSTR className, LPCSTR title )
1200 /* If the atom doesn't exist, then no class */
1201 /* with this name exists either. */
1202 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1204 return WIN_FindWindow( 0, 0, atom, title );
1208 /***********************************************************************
1209 * FindWindowEx32W (USER32.199)
1211 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1212 LPCWSTR className, LPCWSTR title )
1220 /* If the atom doesn't exist, then no class */
1221 /* with this name exists either. */
1222 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1224 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1225 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1226 if (buffer) free( buffer );
1231 /***********************************************************************
1232 * FindWindow32W (USER32.200)
1234 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1236 return FindWindowEx32W( 0, 0, className, title );
1240 /**********************************************************************
1243 WND *WIN_GetDesktop(void)
1249 /**********************************************************************
1250 * GetDesktopWindow16 (USER.286)
1252 HWND16 GetDesktopWindow16(void)
1254 return (HWND16)pWndDesktop->hwndSelf;
1258 /**********************************************************************
1259 * GetDesktopWindow32 (USER32.231)
1261 HWND32 GetDesktopWindow32(void)
1263 return pWndDesktop->hwndSelf;
1267 /**********************************************************************
1268 * GetDesktopHwnd (USER.278)
1270 * Exactly the same thing as GetDesktopWindow(), but not documented.
1271 * Don't ask me why...
1273 HWND16 GetDesktopHwnd(void)
1275 return (HWND16)pWndDesktop->hwndSelf;
1279 /*******************************************************************
1280 * EnableWindow (USER.34)
1282 BOOL EnableWindow( HWND hwnd, BOOL enable )
1286 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1287 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1290 wndPtr->dwStyle &= ~WS_DISABLED;
1291 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1294 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1296 /* Disable window */
1297 wndPtr->dwStyle |= WS_DISABLED;
1298 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1299 SetFocus32( 0 ); /* A disabled window can't have the focus */
1300 if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
1301 ReleaseCapture(); /* A disabled window can't capture the mouse */
1302 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1305 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1309 /***********************************************************************
1310 * IsWindowEnabled (USER.35) (USER32.348)
1312 BOOL IsWindowEnabled(HWND hWnd)
1316 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1317 return !(wndPtr->dwStyle & WS_DISABLED);
1321 /***********************************************************************
1322 * IsWindowUnicode (USER32.349)
1324 BOOL32 IsWindowUnicode( HWND32 hwnd )
1328 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1329 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1333 /**********************************************************************
1334 * GetWindowWord (USER.133) (USER32.313)
1336 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1338 WND * wndPtr = WIN_FindWndPtr( hwnd );
1339 if (!wndPtr) return 0;
1342 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1344 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1347 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1351 case GWW_ID: return wndPtr->wIDmenu;
1352 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1353 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1355 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1361 /**********************************************************************
1362 * WIN_GetWindowInstance
1364 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1366 WND * wndPtr = WIN_FindWndPtr( hwnd );
1367 if (!wndPtr) return (HINSTANCE16)0;
1368 return wndPtr->hInstance;
1372 /**********************************************************************
1373 * SetWindowWord (USER.134) (USER32.523)
1375 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1378 WND * wndPtr = WIN_FindWndPtr( hwnd );
1379 if (!wndPtr) return 0;
1382 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1384 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1387 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1391 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1392 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1393 case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1395 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1404 /**********************************************************************
1407 * Helper function for GetWindowLong().
1409 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1412 WND * wndPtr = WIN_FindWndPtr( hwnd );
1413 if (!wndPtr) return 0;
1416 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1418 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1421 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1422 /* Special case for dialog window procedure */
1423 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1424 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1429 case GWL_USERDATA: return wndPtr->userdata;
1430 case GWL_STYLE: return wndPtr->dwStyle;
1431 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1432 case GWL_ID: return wndPtr->wIDmenu;
1433 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1435 case GWL_HWNDPARENT: return wndPtr->parent ?
1436 (HWND32)wndPtr->parent->hwndSelf : 0;
1437 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1439 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1445 /**********************************************************************
1448 * Helper function for SetWindowLong().
1450 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1451 WINDOWPROCTYPE type )
1454 WND * wndPtr = WIN_FindWndPtr( hwnd );
1455 if (!wndPtr) return 0;
1458 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1460 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1463 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1464 /* Special case for dialog window procedure */
1465 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1467 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1468 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1476 return SetWindowWord( hwnd, offset, (WORD)newval );
1478 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1479 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1482 ptr = &wndPtr->dwStyle;
1483 /* Some bits can't be changed this way */
1484 newval &= ~(WS_VISIBLE | WS_CHILD);
1485 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1487 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1488 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1490 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1499 /**********************************************************************
1500 * GetWindowLong16 (USER.135)
1502 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1504 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1508 /**********************************************************************
1509 * GetWindowLong32A (USER32.304)
1511 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1513 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1517 /**********************************************************************
1518 * GetWindowLong32W (USER32.305)
1520 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1522 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1526 /**********************************************************************
1527 * SetWindowLong16 (USER.136)
1529 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1531 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1535 /**********************************************************************
1536 * SetWindowLong32A (USER32.516)
1538 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1540 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1544 /**********************************************************************
1545 * SetWindowLong32W (USER32.517)
1547 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1549 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1553 /*******************************************************************
1554 * GetWindowText16 (USER.36)
1556 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1558 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1562 /*******************************************************************
1563 * GetWindowText32A (USER32.308)
1565 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1567 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1572 /*******************************************************************
1573 * GetWindowText32W (USER32.311)
1575 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1577 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1582 /*******************************************************************
1583 * SetWindowText16 (USER.37)
1585 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1587 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1591 /*******************************************************************
1592 * SetWindowText32A (USER32.)
1594 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1596 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1600 /*******************************************************************
1601 * SetWindowText32W (USER32.)
1603 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1605 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1609 /*******************************************************************
1610 * GetWindowTextLength16 (USER.38)
1612 INT16 GetWindowTextLength16( HWND16 hwnd )
1614 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1618 /*******************************************************************
1619 * GetWindowTextLength32A (USER32.309)
1621 INT32 GetWindowTextLength32A( HWND32 hwnd )
1623 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1626 /*******************************************************************
1627 * GetWindowTextLength32W (USER32.309)
1629 INT32 GetWindowTextLength32W( HWND32 hwnd )
1631 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1634 /*******************************************************************
1635 * IsWindow (USER.47) (USER32.347)
1637 BOOL16 IsWindow( HWND32 hwnd )
1639 WND * wndPtr = WIN_FindWndPtr( hwnd );
1640 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1644 /*****************************************************************
1645 * GetParent16 (USER.46)
1647 HWND16 GetParent16( HWND16 hwnd )
1649 return (HWND16)GetParent32( hwnd );
1653 /*****************************************************************
1654 * GetParent32 (USER32.277)
1656 HWND32 GetParent32( HWND32 hwnd )
1658 WND *wndPtr = WIN_FindWndPtr(hwnd);
1659 if (!wndPtr) return 0;
1660 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1661 return wndPtr ? wndPtr->hwndSelf : 0;
1665 /*****************************************************************
1668 * Get the top-level parent for a child window.
1670 HWND32 WIN_GetTopParent( HWND32 hwnd )
1672 WND *wndPtr = WIN_FindWndPtr( hwnd );
1673 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1674 return wndPtr ? wndPtr->hwndSelf : 0;
1678 /*****************************************************************
1679 * SetParent (USER.233)
1681 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1685 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1686 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1687 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1689 oldParent = wndPtr->parent->hwndSelf;
1691 WIN_UnlinkWindow(hwndChild);
1692 if (hwndNewParent) wndPtr->parent = pWndParent;
1693 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1695 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1702 /*******************************************************************
1705 BOOL IsChild( HWND parent, HWND child )
1707 WND * wndPtr = WIN_FindWndPtr( child );
1708 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1710 wndPtr = wndPtr->parent;
1711 if (wndPtr->hwndSelf == parent) return TRUE;
1717 /***********************************************************************
1718 * IsWindowVisible (USER.49) (USER32.350)
1720 BOOL IsWindowVisible( HWND hwnd )
1722 WND *wndPtr = WIN_FindWndPtr( hwnd );
1723 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1725 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1726 wndPtr = wndPtr->parent;
1728 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1731 /***********************************************************************
1732 * WIN_IsWindowDrawable
1734 * hwnd is drawable when it is visible, all parents are not
1735 * minimized, and it is itself not minimized unless we are
1736 * trying to draw icon and the default class icon is set.
1738 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1740 HWND hwnd= wnd->hwndSelf;
1745 if( wnd->dwStyle & WS_MINIMIZE )
1746 if( wnd->hwndSelf != hwnd ) break;
1747 else if( icon && wnd->class->hIcon ) break;
1749 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1750 wnd = wnd->parent; }
1751 return (!wnd && yes);
1754 /*******************************************************************
1755 * GetTopWindow (USER.229)
1757 HWND GetTopWindow( HWND hwnd )
1759 WND * wndPtr = WIN_FindWndPtr( hwnd );
1760 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1765 /*******************************************************************
1766 * GetWindow (USER.262)
1768 HWND GetWindow( HWND hwnd, WORD rel )
1770 WND * wndPtr = WIN_FindWndPtr( hwnd );
1771 if (!wndPtr) return 0;
1775 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1779 if (!wndPtr->parent) return 0; /* Desktop window */
1780 while (wndPtr->next) wndPtr = wndPtr->next;
1781 return wndPtr->hwndSelf;
1784 if (!wndPtr->next) return 0;
1785 return wndPtr->next->hwndSelf;
1788 if (!wndPtr->parent) return 0; /* Desktop window */
1789 wndPtr = wndPtr->parent->child; /* First sibling */
1790 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1791 while (wndPtr->next)
1793 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1794 wndPtr = wndPtr->next;
1799 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1802 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1808 /*******************************************************************
1809 * GetNextWindow (USER.230)
1811 HWND GetNextWindow( HWND hwnd, WORD flag )
1813 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1814 return GetWindow( hwnd, flag );
1817 /*******************************************************************
1818 * ShowOwnedPopups (USER.265)
1820 void ShowOwnedPopups( HWND owner, BOOL fShow )
1822 WND *pWnd = pWndDesktop->child;
1825 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1826 (pWnd->dwStyle & WS_POPUP))
1827 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1833 /*******************************************************************
1834 * GetLastActivePopup (USER.287)
1836 HWND GetLastActivePopup(HWND hwnd)
1839 wndPtr = WIN_FindWndPtr(hwnd);
1840 if (wndPtr == NULL) return hwnd;
1841 return wndPtr->hwndLastActive;
1845 /*******************************************************************
1848 * Build an array of pointers to all children of a given window.
1849 * The array must be freed with HeapFree(SystemHeap).
1851 WND **WIN_BuildWinArray( WND *wndPtr )
1853 WND **list, **ppWnd;
1857 /* First count the windows */
1859 if (!wndPtr) wndPtr = pWndDesktop;
1860 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1861 count++; /* For the terminating NULL */
1863 /* Now build the list of all windows */
1865 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1867 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1874 /*******************************************************************
1875 * EnumWindows16 (USER.54)
1877 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1879 WND **list, **ppWnd;
1881 /* We have to build a list of all windows first, to avoid */
1882 /* unpleasant side-effects, for instance if the callback */
1883 /* function changes the Z-order of the windows. */
1885 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1887 /* Now call the callback function for every window */
1889 for (ppWnd = list; *ppWnd; ppWnd++)
1891 /* Make sure that the window still exists */
1892 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1893 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1895 HeapFree( SystemHeap, 0, list );
1900 /*******************************************************************
1901 * EnumWindows32 (USER32.192)
1903 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1905 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1909 /**********************************************************************
1910 * EnumTaskWindows16 (USER.225)
1912 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1914 WND **list, **ppWnd;
1915 HQUEUE16 hQueue = GetTaskQueue( hTask );
1917 /* This function is the same as EnumWindows(), */
1918 /* except for an added check on the window queue. */
1920 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1922 /* Now call the callback function for every window */
1924 for (ppWnd = list; *ppWnd; ppWnd++)
1926 /* Make sure that the window still exists */
1927 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1928 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1929 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1931 HeapFree( SystemHeap, 0, list );
1936 /**********************************************************************
1937 * EnumThreadWindows (USER32.189)
1939 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1941 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1945 /**********************************************************************
1946 * WIN_EnumChildWindows
1948 * Helper function for EnumChildWindows().
1950 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1958 /* Make sure that the window still exists */
1959 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1960 /* Build children list first */
1961 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1962 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1963 ret = WIN_EnumChildWindows( childList, func, lParam );
1964 HeapFree( SystemHeap, 0, childList );
1965 if (!ret) return FALSE;
1972 /**********************************************************************
1973 * EnumChildWindows16 (USER.55)
1975 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1977 WND **list, *pParent;
1979 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1980 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1981 WIN_EnumChildWindows( list, func, lParam );
1982 HeapFree( SystemHeap, 0, list );
1987 /**********************************************************************
1988 * EnumChildWindows32 (USER32.177)
1990 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1992 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1997 /*******************************************************************
1998 * AnyPopup (USER.52)
2003 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2004 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2008 /*******************************************************************
2009 * FlashWindow [USER.105]
2011 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
2013 WND *wndPtr = WIN_FindWndPtr(hWnd);
2015 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2017 if (!wndPtr) return FALSE;
2019 if (wndPtr->dwStyle & WS_MINIMIZE)
2021 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2023 HDC32 hDC = GetDC32(hWnd);
2025 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2026 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2028 ReleaseDC32( hWnd, hDC );
2029 wndPtr->flags |= WIN_NCACTIVATED;
2033 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2034 RDW_UPDATENOW | RDW_FRAME, 0 );
2035 wndPtr->flags &= ~WIN_NCACTIVATED;
2042 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2043 else wparam = (hWnd == GetActiveWindow());
2045 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2051 /*******************************************************************
2052 * SetSysModalWindow16 (USER.188)
2054 HWND16 SetSysModalWindow16( HWND16 hWnd )
2056 HWND hWndOldModal = hwndSysModal;
2057 hwndSysModal = hWnd;
2058 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2059 return hWndOldModal;
2063 /*******************************************************************
2064 * GetSysModalWindow16 (USER.52)
2066 HWND16 GetSysModalWindow16(void)
2068 return hwndSysModal;
2072 /*******************************************************************
2075 * recursively find a child that contains spDragInfo->pt point
2076 * and send WM_QUERYDROPOBJECT
2078 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2080 BOOL16 wParam,bResult = 0;
2082 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2083 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2086 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2088 pt = ptrDragInfo->pt;
2090 GetWindowRect16(hQueryWnd,&tempRect);
2092 if( !PtInRect16(&tempRect,pt) ||
2093 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2096 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2098 tempRect = ptrQueryWnd->rectClient;
2099 if(ptrQueryWnd->dwStyle & WS_CHILD)
2100 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2102 if( PtInRect16(&tempRect,pt) )
2106 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2107 if( ptrWnd->dwStyle & WS_VISIBLE )
2109 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2111 if( PtInRect16(&tempRect,pt) )
2117 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2118 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2119 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2120 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2121 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2124 if(bResult) return bResult;
2130 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2132 ptrDragInfo->hScope = hQueryWnd;
2134 bResult = ( bNoSend )
2135 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2136 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2137 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2139 ptrDragInfo->pt = pt;
2144 /*******************************************************************
2145 * DragDetect ( USER.465 )
2148 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2153 rect.left = pt.x - wDragWidth;
2154 rect.right = pt.x + wDragWidth;
2156 rect.top = pt.y - wDragHeight;
2157 rect.bottom = pt.y + wDragHeight;
2163 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2165 if( msg.message == WM_LBUTTONUP )
2170 if( msg.message == WM_MOUSEMOVE )
2172 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2185 /******************************************************************************
2186 * DragObject ( USER.464 )
2189 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE16 hOfStruct,
2190 WORD szList , HCURSOR16 hCursor)
2193 LPDRAGINFO lpDragInfo;
2195 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2196 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2197 WND *wndPtr = WIN_FindWndPtr(hWnd);
2200 HCURSOR16 hCurrentCursor = 0;
2201 HWND hCurrentWnd = 0;
2204 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2205 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2207 if( !lpDragInfo || !spDragInfo ) return 0L;
2209 hBummer = LoadCursor16(0,IDC_BUMMER);
2211 if( !hBummer || !wndPtr )
2213 GlobalFree16(hDragInfo);
2219 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2221 GlobalFree16(hDragInfo);
2225 if( hDragCursor == hCursor ) hDragCursor = 0;
2226 else hCursor = hDragCursor;
2228 hOldCursor = SetCursor(hDragCursor);
2231 lpDragInfo->hWnd = hWnd;
2232 lpDragInfo->hScope = 0;
2233 lpDragInfo->wFlags = wObj;
2234 lpDragInfo->hList = szList; /* near pointer! */
2235 lpDragInfo->hOfStruct = hOfStruct;
2245 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2248 *(lpDragInfo+1) = *lpDragInfo;
2250 lpDragInfo->pt = msg.pt;
2252 /* update DRAGINFO struct */
2253 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2255 if( (b = DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE)) > 0 )
2256 hCurrentCursor = hCursor;
2259 hCurrentCursor = hBummer;
2260 lpDragInfo->hScope = 0;
2262 if( hCurrentCursor )
2263 SetCursor(hCurrentCursor);
2265 dprintf_msg(stddeb,"drag: got %04x\n", b);
2267 /* send WM_DRAGLOOP */
2268 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer) ,
2269 (LPARAM) spDragInfo );
2270 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2271 if( hCurrentWnd != lpDragInfo->hScope )
2274 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2275 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2276 HIWORD(spDragInfo)) );
2277 hCurrentWnd = lpDragInfo->hScope;
2279 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2283 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2286 /* check if we're done */
2287 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2296 SetCursor(hOldCursor);
2298 DestroyCursor(hDragCursor);
2301 if( hCurrentCursor != hBummer )
2302 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2303 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2304 GlobalFree16(hDragInfo);