Desktop window queue handling adapted.
[wine/hacks.git] / windows / win.c
blob1551a373dcf90cae7a822b2cd82c2c9508f8b127
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "options.h"
10 #include "class.h"
11 #include "win.h"
12 #include "heap.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "cursoricon.h"
17 #include "heap.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debug.h"
32 #include "winerror.h"
33 #include "mdi.h"
35 extern WND_DRIVER X11DRV_WND_Driver;
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND32 hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 /***********************************************************************
46 * WIN_FindWndPtr
48 * Return a pointer to the WND structure corresponding to a HWND.
50 WND * WIN_FindWndPtr( HWND32 hwnd )
52 WND * ptr;
54 if (!hwnd || HIWORD(hwnd)) return NULL;
55 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
56 if (ptr->dwMagic != WND_MAGIC) return NULL;
57 if (ptr->hwndSelf != hwnd)
59 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
60 hwnd, ptr->hwndSelf );
61 return NULL;
63 return ptr;
67 /***********************************************************************
68 * WIN_DumpWindow
70 * Dump the content of a window structure to stderr.
72 void WIN_DumpWindow( HWND32 hwnd )
74 WND *ptr;
75 char className[80];
76 int i;
78 if (!(ptr = WIN_FindWndPtr( hwnd )))
80 WARN( win, "%04x is not a window handle\n", hwnd );
81 return;
84 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
85 strcpy( className, "#NULL#" );
87 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
88 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
89 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
90 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
91 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
92 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
93 ptr->next, ptr->child, ptr->parent, ptr->owner,
94 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
95 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
96 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
97 ptr->text ? ptr->text : "",
98 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
99 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
100 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
101 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
103 if (ptr->class->cbWndExtra)
105 DUMP( "extra bytes:" );
106 for (i = 0; i < ptr->class->cbWndExtra; i++)
107 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
108 DUMP( "\n" );
110 DUMP( "\n" );
114 /***********************************************************************
115 * WIN_WalkWindows
117 * Walk the windows tree and print each window on stderr.
119 void WIN_WalkWindows( HWND32 hwnd, int indent )
121 WND *ptr;
122 char className[80];
124 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
125 if (!ptr)
127 WARN( win, "Invalid window handle %04x\n", hwnd );
128 return;
131 if (!indent) /* first time around */
132 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
133 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
134 " Text");
136 while (ptr)
138 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
140 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
142 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
143 (DWORD)ptr, ptr->hmemTaskQ, className,
144 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
145 ptr->text?ptr->text:"<null>");
147 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
148 ptr = ptr->next;
152 /***********************************************************************
153 * WIN_UnlinkWindow
155 * Remove a window from the siblings linked list.
157 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
159 WND *wndPtr, **ppWnd;
161 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
162 ppWnd = &wndPtr->parent->child;
163 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
164 *ppWnd = wndPtr->next;
165 return TRUE;
169 /***********************************************************************
170 * WIN_LinkWindow
172 * Insert a window into the siblings linked list.
173 * The window is inserted after the specified window, which can also
174 * be specified as HWND_TOP or HWND_BOTTOM.
176 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
178 WND *wndPtr, **ppWnd;
180 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
184 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
185 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
186 while (*ppWnd) ppWnd = &(*ppWnd)->next;
188 else /* Normal case */
190 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
191 if (!afterPtr) return FALSE;
192 ppWnd = &afterPtr->next;
194 wndPtr->next = *ppWnd;
195 *ppWnd = wndPtr;
196 return TRUE;
200 /***********************************************************************
201 * WIN_FindWinToRepaint
203 * Find a window that needs repaint.
205 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
207 HWND32 hwndRet;
208 WND *pWnd = pWndDesktop;
210 /* Note: the desktop window never gets WM_PAINT messages
211 * The real reason why is because Windows DesktopWndProc
212 * does ValidateRgn inside WM_ERASEBKGND handler.
215 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
217 for ( ; pWnd ; pWnd = pWnd->next )
219 if (!(pWnd->dwStyle & WS_VISIBLE))
221 TRACE(win, "skipping window %04x\n",
222 pWnd->hwndSelf );
223 continue;
225 if ((pWnd->hmemTaskQ == hQueue) &&
226 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
228 if (pWnd->child )
229 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
230 return hwndRet;
233 if (!pWnd) return 0;
235 hwndRet = pWnd->hwndSelf;
237 /* look among siblings if we got a transparent window */
238 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
239 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
241 pWnd = pWnd->next;
243 if (pWnd) hwndRet = pWnd->hwndSelf;
244 TRACE(win,"found %04x\n",hwndRet);
245 return hwndRet;
249 /***********************************************************************
250 * WIN_DestroyWindow
252 * Destroy storage associated to a window. "Internals" p.358
254 static WND* WIN_DestroyWindow( WND* wndPtr )
256 HWND32 hwnd = wndPtr->hwndSelf;
257 WND *pWnd;
259 TRACE(win, "%04x\n", wndPtr->hwndSelf );
261 #ifdef CONFIG_IPC
262 if (main_block)
263 DDE_DestroyWindow(wndPtr->hwndSelf);
264 #endif /* CONFIG_IPC */
266 /* free child windows */
268 while ((pWnd = wndPtr->child))
269 wndPtr->child = WIN_DestroyWindow( pWnd );
271 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
273 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
275 WINPOS_CheckInternalPos( hwnd );
276 if( hwnd == GetCapture32()) ReleaseCapture();
278 /* free resources associated with the window */
280 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
281 PROPERTY_RemoveWindowProps( wndPtr );
283 wndPtr->dwMagic = 0; /* Mark it as invalid */
285 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
287 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
288 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
291 /* toss stale messages from the queue */
293 if( wndPtr->hmemTaskQ )
295 int pos;
296 BOOL32 bPostQuit = FALSE;
297 WPARAM32 wQuitParam = 0;
298 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
300 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
302 if( msgQ->messages[pos].msg.message == WM_QUIT )
304 bPostQuit = TRUE;
305 wQuitParam = msgQ->messages[pos].msg.wParam;
307 QUEUE_RemoveMsg(msgQ, pos);
309 /* repost WM_QUIT to make sure this app exits its message loop */
310 if( bPostQuit ) PostQuitMessage32(wQuitParam);
311 wndPtr->hmemTaskQ = 0;
314 if (!(wndPtr->dwStyle & WS_CHILD))
315 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
316 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
317 wndPtr->pDriver->pDestroyWindow( wndPtr );
318 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
319 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
320 wndPtr->hwndSelf = 0;
321 wndPtr->class->cWindows--;
322 wndPtr->class = NULL;
323 pWnd = wndPtr->next;
325 USER_HEAP_FREE( hwnd );
326 return pWnd;
329 /***********************************************************************
330 * WIN_ResetQueueWindows
332 * Reset the queue of all the children of a given window.
333 * Return TRUE if something was done.
335 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
337 BOOL32 ret = FALSE;
339 if (hNew) /* Set a new queue */
341 for (wnd = wnd->child; (wnd); wnd = wnd->next)
343 if (wnd->hmemTaskQ == hQueue)
345 wnd->hmemTaskQ = hNew;
346 ret = TRUE;
348 if (wnd->child)
349 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
352 else /* Queue is being destroyed */
354 while (wnd->child)
356 WND *tmp = wnd->child;
357 ret = FALSE;
358 while (tmp)
360 if (tmp->hmemTaskQ == hQueue)
362 DestroyWindow32( tmp->hwndSelf );
363 ret = TRUE;
364 break;
366 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
367 ret = TRUE;
368 else
369 tmp = tmp->next;
371 if (!ret) break;
374 return ret;
377 /***********************************************************************
378 * WIN_CreateDesktopWindow
380 * Create the desktop window.
382 BOOL32 WIN_CreateDesktopWindow(void)
384 CLASS *class;
385 HWND32 hwndDesktop;
387 TRACE(win,"Creating desktop window\n");
389 if (!ICONTITLE_Init() ||
390 !WINPOS_CreateInternalPosAtom() ||
391 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
392 return FALSE;
394 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
395 if (!hwndDesktop) return FALSE;
396 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
398 pWndDesktop->next = NULL;
399 pWndDesktop->child = NULL;
400 pWndDesktop->parent = NULL;
401 pWndDesktop->owner = NULL;
402 pWndDesktop->class = class;
403 pWndDesktop->dwMagic = WND_MAGIC;
404 pWndDesktop->hwndSelf = hwndDesktop;
405 pWndDesktop->hInstance = 0;
406 pWndDesktop->rectWindow.left = 0;
407 pWndDesktop->rectWindow.top = 0;
408 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
409 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
410 pWndDesktop->rectClient = pWndDesktop->rectWindow;
411 pWndDesktop->text = NULL;
412 pWndDesktop->hmemTaskQ = GetFastQueue();
413 pWndDesktop->hrgnUpdate = 0;
414 pWndDesktop->hwndLastActive = hwndDesktop;
415 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
416 WS_CLIPSIBLINGS;
417 pWndDesktop->dwExStyle = 0;
418 pWndDesktop->dce = NULL;
419 pWndDesktop->pVScroll = NULL;
420 pWndDesktop->pHScroll = NULL;
421 pWndDesktop->pProp = NULL;
422 pWndDesktop->wIDmenu = 0;
423 pWndDesktop->helpContext = 0;
424 pWndDesktop->flags = 0;
425 pWndDesktop->hSysMenu = 0;
426 pWndDesktop->userdata = 0;
427 pWndDesktop->pDriver = &X11DRV_WND_Driver;
428 pWndDesktop->winproc = (WNDPROC16)class->winproc;
430 /* FIXME: How do we know if it should be Unicode or not */
431 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
432 return FALSE;
434 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
435 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
436 return TRUE;
440 /***********************************************************************
441 * WIN_CreateWindowEx
443 * Implementation of CreateWindowEx().
445 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
446 BOOL32 win32, BOOL32 unicode )
448 CLASS *classPtr;
449 WND *wndPtr;
450 HWND16 hwnd, hwndLinkAfter;
451 POINT32 maxSize, maxPos, minTrack, maxTrack;
452 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
454 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
455 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
456 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
457 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
458 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
460 /* Find the parent window */
462 if (cs->hwndParent)
464 /* Make sure parent is valid */
465 if (!IsWindow32( cs->hwndParent ))
467 WARN( win, "Bad parent %04x\n", cs->hwndParent );
468 return 0;
470 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
471 WARN( win, "No parent for child window\n" );
472 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
475 /* Find the window class */
476 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
478 char buffer[256];
479 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
480 WARN( win, "Bad class '%s'\n", buffer );
481 return 0;
484 /* Fix the coordinates */
486 if (cs->x == CW_USEDEFAULT32)
488 PDB32 *pdb = PROCESS_Current();
489 if ( !(cs->style & (WS_CHILD | WS_POPUP))
490 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
492 cs->x = pdb->env_db->startup_info->dwX;
493 cs->y = pdb->env_db->startup_info->dwY;
495 else
497 cs->x = 0;
498 cs->y = 0;
501 if (cs->cx == CW_USEDEFAULT32)
503 PDB32 *pdb = PROCESS_Current();
504 if ( !(cs->style & (WS_CHILD | WS_POPUP))
505 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
507 cs->cx = pdb->env_db->startup_info->dwXSize;
508 cs->cy = pdb->env_db->startup_info->dwYSize;
510 else
512 cs->cx = 600; /* FIXME */
513 cs->cy = 400;
517 /* Create the window structure */
519 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
520 - sizeof(wndPtr->wExtra) )))
522 TRACE(win, "out of memory\n" );
523 return 0;
526 /* Fill the window structure */
528 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
529 wndPtr->next = NULL;
530 wndPtr->child = NULL;
532 if ((cs->style & WS_CHILD) && cs->hwndParent)
534 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
535 wndPtr->owner = NULL;
537 else
539 wndPtr->parent = pWndDesktop;
540 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
541 wndPtr->owner = NULL;
542 else
543 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
546 wndPtr->pDriver = &X11DRV_WND_Driver;
547 wndPtr->window = 0;
548 wndPtr->class = classPtr;
549 wndPtr->winproc = classPtr->winproc;
550 wndPtr->dwMagic = WND_MAGIC;
551 wndPtr->hwndSelf = hwnd;
552 wndPtr->hInstance = cs->hInstance;
553 wndPtr->text = NULL;
554 wndPtr->hmemTaskQ = GetFastQueue();
555 wndPtr->hrgnUpdate = 0;
556 wndPtr->hwndLastActive = hwnd;
557 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
558 wndPtr->dwExStyle = cs->dwExStyle;
559 wndPtr->wIDmenu = 0;
560 wndPtr->helpContext = 0;
561 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
562 wndPtr->pVScroll = NULL;
563 wndPtr->pHScroll = NULL;
564 wndPtr->pProp = NULL;
565 wndPtr->userdata = 0;
566 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
567 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
569 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
571 /* Call the WH_CBT hook */
573 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
574 ? HWND_BOTTOM : HWND_TOP;
576 if (HOOK_IsHooked( WH_CBT ))
578 CBT_CREATEWND32A cbtc;
579 LRESULT ret;
581 cbtc.lpcs = cs;
582 cbtc.hwndInsertAfter = hwndLinkAfter;
583 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
584 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
585 if (ret)
587 TRACE(win, "CBT-hook returned 0\n");
588 USER_HEAP_FREE( hwnd );
589 return 0;
593 /* Increment class window counter */
595 classPtr->cWindows++;
597 /* Correct the window style */
599 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
601 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
602 wndPtr->flags |= WIN_NEED_SIZE;
604 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
606 /* Get class or window DC if needed */
608 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
609 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
610 else wndPtr->dce = NULL;
612 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
614 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
616 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
617 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
618 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
619 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
620 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
623 if(cs->style & WS_CHILD)
625 if(cs->cx < 0) cs->cx = 0;
626 if(cs->cy < 0) cs->cy = 0;
628 else
630 if (cs->cx <= 0) cs->cx = 1;
631 if (cs->cy <= 0) cs->cy = 1;
634 wndPtr->rectWindow.left = cs->x;
635 wndPtr->rectWindow.top = cs->y;
636 wndPtr->rectWindow.right = cs->x + cs->cx;
637 wndPtr->rectWindow.bottom = cs->y + cs->cy;
638 wndPtr->rectClient = wndPtr->rectWindow;
640 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
641 return FALSE;
643 /* Set the window menu */
645 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
647 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
648 else
650 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
651 if (classPtr->menuNameA)
652 cs->hMenu = HIWORD(classPtr->menuNameA) ?
653 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
654 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
655 #else
656 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
657 if (menuName)
659 if (HIWORD(cs->hInstance))
660 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
661 else
662 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
664 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
666 #endif
669 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
671 /* Send the WM_CREATE message
672 * Perhaps we shouldn't allow width/height changes as well.
673 * See p327 in "Internals".
676 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
678 localSend32 = unicode ? SendMessage32W : SendMessage32A;
679 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
681 /* Insert the window in the linked list */
683 WIN_LinkWindow( hwnd, hwndLinkAfter );
685 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
686 NULL, NULL, 0, &wndPtr->rectClient );
687 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
688 maxPos.y - wndPtr->rectWindow.top);
689 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
691 /* Send the size messages */
693 if (!(wndPtr->flags & WIN_NEED_SIZE))
695 /* send it anyway */
696 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
697 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
698 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
699 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
700 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
701 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
702 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
703 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
704 SendMessage32A( hwnd, WM_MOVE, 0,
705 MAKELONG( wndPtr->rectClient.left,
706 wndPtr->rectClient.top ) );
709 /* Show the window, maximizing or minimizing if needed */
711 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
713 RECT16 newPos;
714 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
715 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
716 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
717 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
718 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
719 : SWP_NOZORDER | SWP_FRAMECHANGED;
720 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
721 newPos.right, newPos.bottom, swFlag );
724 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
726 /* Notify the parent window only */
728 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
729 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
730 if( !IsWindow32(hwnd) ) return 0;
733 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
735 /* Call WH_SHELL hook */
737 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
738 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
740 TRACE(win, "created window %04x\n", hwnd);
741 return hwnd;
743 WIN_UnlinkWindow( hwnd );
746 /* Abort window creation */
748 WARN(win, "aborted by WM_xxCREATE!\n");
749 WIN_DestroyWindow( wndPtr );
750 return 0;
754 /***********************************************************************
755 * CreateWindow16 (USER.41)
757 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
758 DWORD style, INT16 x, INT16 y, INT16 width,
759 INT16 height, HWND16 parent, HMENU16 menu,
760 HINSTANCE16 instance, LPVOID data )
762 return CreateWindowEx16( 0, className, windowName, style,
763 x, y, width, height, parent, menu, instance, data );
767 /***********************************************************************
768 * CreateWindowEx16 (USER.452)
770 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
771 LPCSTR windowName, DWORD style, INT16 x,
772 INT16 y, INT16 width, INT16 height,
773 HWND16 parent, HMENU16 menu,
774 HINSTANCE16 instance, LPVOID data )
776 ATOM classAtom;
777 CREATESTRUCT32A cs;
779 /* Find the class atom */
781 if (!(classAtom = GlobalFindAtom32A( className )))
783 fprintf( stderr, "CreateWindowEx16: bad class name " );
784 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
785 else fprintf( stderr, "'%s'\n", className );
786 return 0;
789 /* Fix the coordinates */
791 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
792 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
793 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
794 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
796 /* Create the window */
798 cs.lpCreateParams = data;
799 cs.hInstance = (HINSTANCE32)instance;
800 cs.hMenu = (HMENU32)menu;
801 cs.hwndParent = (HWND32)parent;
802 cs.style = style;
803 cs.lpszName = windowName;
804 cs.lpszClass = className;
805 cs.dwExStyle = exStyle;
806 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
810 /***********************************************************************
811 * CreateWindowEx32A (USER32.83)
813 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
814 LPCSTR windowName, DWORD style, INT32 x,
815 INT32 y, INT32 width, INT32 height,
816 HWND32 parent, HMENU32 menu,
817 HINSTANCE32 instance, LPVOID data )
819 ATOM classAtom;
820 CREATESTRUCT32A cs;
822 if(exStyle & WS_EX_MDICHILD)
823 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
824 /* Find the class atom */
826 if (!(classAtom = GlobalFindAtom32A( className )))
828 fprintf( stderr, "CreateWindowEx32A: bad class name " );
829 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
830 else fprintf( stderr, "'%s'\n", className );
831 return 0;
834 /* Create the window */
836 cs.lpCreateParams = data;
837 cs.hInstance = instance;
838 cs.hMenu = menu;
839 cs.hwndParent = parent;
840 cs.x = x;
841 cs.y = y;
842 cs.cx = width;
843 cs.cy = height;
844 cs.style = style;
845 cs.lpszName = windowName;
846 cs.lpszClass = className;
847 cs.dwExStyle = exStyle;
848 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
852 /***********************************************************************
853 * CreateWindowEx32W (USER32.84)
855 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
856 LPCWSTR windowName, DWORD style, INT32 x,
857 INT32 y, INT32 width, INT32 height,
858 HWND32 parent, HMENU32 menu,
859 HINSTANCE32 instance, LPVOID data )
861 ATOM classAtom;
862 CREATESTRUCT32W cs;
864 if(exStyle & WS_EX_MDICHILD)
865 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
867 /* Find the class atom */
869 if (!(classAtom = GlobalFindAtom32W( className )))
871 if (HIWORD(className))
873 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
874 WARN( win, "Bad class name '%s'\n",cn);
875 HeapFree( GetProcessHeap(), 0, cn );
877 else
878 WARN( win, "Bad class name %p\n", className );
879 return 0;
882 /* Create the window */
884 cs.lpCreateParams = data;
885 cs.hInstance = instance;
886 cs.hMenu = menu;
887 cs.hwndParent = parent;
888 cs.x = x;
889 cs.y = y;
890 cs.cx = width;
891 cs.cy = height;
892 cs.style = style;
893 cs.lpszName = windowName;
894 cs.lpszClass = className;
895 cs.dwExStyle = exStyle;
896 /* Note: we rely on the fact that CREATESTRUCT32A and */
897 /* CREATESTRUCT32W have the same layout. */
898 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
902 /***********************************************************************
903 * WIN_CheckFocus
905 static void WIN_CheckFocus( WND* pWnd )
907 if( GetFocus16() == pWnd->hwndSelf )
908 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
911 /***********************************************************************
912 * WIN_SendDestroyMsg
914 static void WIN_SendDestroyMsg( WND* pWnd )
916 WIN_CheckFocus(pWnd);
918 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
919 if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd );
921 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
923 if( IsWindow32(pWnd->hwndSelf) )
925 WND* pChild = pWnd->child;
926 while( pChild )
928 WIN_SendDestroyMsg( pChild );
929 pChild = pChild->next;
931 WIN_CheckFocus(pWnd);
933 else
934 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
938 /***********************************************************************
939 * DestroyWindow16 (USER.53)
941 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
943 return DestroyWindow32(hwnd);
947 /***********************************************************************
948 * DestroyWindow32 (USER32.135)
950 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
952 WND * wndPtr;
954 TRACE(win, "(%04x)\n", hwnd);
956 /* Initialization */
958 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
959 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
961 /* Call hooks */
963 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
964 return FALSE;
966 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
968 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
969 /* FIXME: clean up palette - see "Internals" p.352 */
972 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
973 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
975 /* Notify the parent window only */
976 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
977 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
978 if( !IsWindow32(hwnd) ) return TRUE;
981 if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */
983 /* Hide the window */
985 if (wndPtr->dwStyle & WS_VISIBLE)
987 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
988 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
989 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
990 if (!IsWindow32(hwnd)) return TRUE;
993 /* Recursively destroy owned windows */
995 if( !(wndPtr->dwStyle & WS_CHILD) )
997 /* make sure top menu popup doesn't get destroyed */
998 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1000 for (;;)
1002 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1003 while (siblingPtr)
1005 if (siblingPtr->owner == wndPtr)
1007 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1008 break;
1009 else
1010 siblingPtr->owner = NULL;
1012 siblingPtr = siblingPtr->next;
1014 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1015 else break;
1018 if( !Options.managed || EVENT_CheckFocus() )
1019 WINPOS_ActivateOtherWindow(wndPtr);
1021 if( wndPtr->owner &&
1022 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1023 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1026 /* Send destroy messages */
1028 WIN_SendDestroyMsg( wndPtr );
1029 if (!IsWindow32(hwnd)) return TRUE;
1031 /* Unlink now so we won't bother with the children later on */
1033 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1035 /* Destroy the window storage */
1037 WIN_DestroyWindow( wndPtr );
1038 return TRUE;
1042 /***********************************************************************
1043 * CloseWindow16 (USER.43)
1045 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1047 return CloseWindow32( hwnd );
1051 /***********************************************************************
1052 * CloseWindow32 (USER32.56)
1054 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1056 WND * wndPtr = WIN_FindWndPtr( hwnd );
1057 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1058 ShowWindow32( hwnd, SW_MINIMIZE );
1059 return TRUE;
1063 /***********************************************************************
1064 * OpenIcon16 (USER.44)
1066 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1068 return OpenIcon32( hwnd );
1072 /***********************************************************************
1073 * OpenIcon32 (USER32.410)
1075 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1077 if (!IsIconic32( hwnd )) return FALSE;
1078 ShowWindow32( hwnd, SW_SHOWNORMAL );
1079 return TRUE;
1083 /***********************************************************************
1084 * WIN_FindWindow
1086 * Implementation of FindWindow() and FindWindowEx().
1088 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1089 LPCSTR title )
1091 WND *pWnd;
1092 CLASS *pClass = NULL;
1094 if (child)
1096 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1097 if (parent)
1099 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1101 else if (pWnd->parent != pWndDesktop) return 0;
1102 pWnd = pWnd->next;
1104 else
1106 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1107 pWnd = pWnd->child;
1109 if (!pWnd) return 0;
1111 /* For a child window, all siblings will have the same hInstance, */
1112 /* so we can look for the class once and for all. */
1114 if (className && (pWnd->dwStyle & WS_CHILD))
1116 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1117 return 0;
1121 for ( ; pWnd; pWnd = pWnd->next)
1123 if (className && !(pWnd->dwStyle & WS_CHILD))
1125 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1126 continue; /* Skip this window */
1129 if (pClass && (pWnd->class != pClass))
1130 continue; /* Not the right class */
1132 /* Now check the title */
1134 if (!title) return pWnd->hwndSelf;
1135 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1137 return 0;
1142 /***********************************************************************
1143 * FindWindow16 (USER.50)
1145 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1147 return FindWindowEx16( 0, 0, className, title );
1151 /***********************************************************************
1152 * FindWindowEx16 (USER.427)
1154 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1155 SEGPTR className, LPCSTR title )
1157 ATOM atom = 0;
1159 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1160 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1161 title ? title : "");
1163 if (className)
1165 /* If the atom doesn't exist, then no class */
1166 /* with this name exists either. */
1167 if (!(atom = GlobalFindAtom16( className ))) return 0;
1169 return WIN_FindWindow( parent, child, atom, title );
1173 /***********************************************************************
1174 * FindWindow32A (USER32.198)
1176 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1178 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1179 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1180 return ret;
1184 /***********************************************************************
1185 * FindWindowEx32A (USER32.199)
1187 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1188 LPCSTR className, LPCSTR title )
1190 ATOM atom = 0;
1192 if (className)
1194 /* If the atom doesn't exist, then no class */
1195 /* with this name exists either. */
1196 if (!(atom = GlobalFindAtom32A( className )))
1198 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1199 return 0;
1202 return WIN_FindWindow( parent, child, atom, title );
1206 /***********************************************************************
1207 * FindWindowEx32W (USER32.200)
1209 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1210 LPCWSTR className, LPCWSTR title )
1212 ATOM atom = 0;
1213 char *buffer;
1214 HWND32 hwnd;
1216 if (className)
1218 /* If the atom doesn't exist, then no class */
1219 /* with this name exists either. */
1220 if (!(atom = GlobalFindAtom32W( className )))
1222 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1223 return 0;
1226 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1227 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1228 HeapFree( GetProcessHeap(), 0, buffer );
1229 return hwnd;
1233 /***********************************************************************
1234 * FindWindow32W (USER32.201)
1236 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1238 return FindWindowEx32W( 0, 0, className, title );
1242 /**********************************************************************
1243 * WIN_GetDesktop
1245 WND *WIN_GetDesktop(void)
1247 return pWndDesktop;
1251 /**********************************************************************
1252 * GetDesktopWindow16 (USER.286)
1254 HWND16 WINAPI GetDesktopWindow16(void)
1256 return (HWND16)pWndDesktop->hwndSelf;
1260 /**********************************************************************
1261 * GetDesktopWindow32 (USER32.232)
1263 HWND32 WINAPI GetDesktopWindow32(void)
1265 return pWndDesktop->hwndSelf;
1269 /**********************************************************************
1270 * GetDesktopHwnd (USER.278)
1272 * Exactly the same thing as GetDesktopWindow(), but not documented.
1273 * Don't ask me why...
1275 HWND16 WINAPI GetDesktopHwnd(void)
1277 return (HWND16)pWndDesktop->hwndSelf;
1281 /*******************************************************************
1282 * EnableWindow16 (USER.34)
1284 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1286 return EnableWindow32( hwnd, enable );
1290 /*******************************************************************
1291 * EnableWindow32 (USER32.172)
1293 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1295 WND *wndPtr;
1297 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1298 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1300 /* Enable window */
1301 wndPtr->dwStyle &= ~WS_DISABLED;
1302 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1303 return TRUE;
1305 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1307 /* Disable window */
1308 wndPtr->dwStyle |= WS_DISABLED;
1309 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1310 SetFocus32( 0 ); /* A disabled window can't have the focus */
1311 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1312 ReleaseCapture(); /* A disabled window can't capture the mouse */
1313 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1314 return FALSE;
1316 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1320 /***********************************************************************
1321 * IsWindowEnabled16 (USER.35)
1323 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1325 return IsWindowEnabled32(hWnd);
1329 /***********************************************************************
1330 * IsWindowEnabled32 (USER32.349)
1332 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1334 WND * wndPtr;
1336 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1337 return !(wndPtr->dwStyle & WS_DISABLED);
1341 /***********************************************************************
1342 * IsWindowUnicode (USER32.350)
1344 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1346 WND * wndPtr;
1348 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1349 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1353 /**********************************************************************
1354 * GetWindowWord16 (USER.133)
1356 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1358 return GetWindowWord32( hwnd, offset );
1362 /**********************************************************************
1363 * GetWindowWord32 (USER32.314)
1365 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1367 WND * wndPtr = WIN_FindWndPtr( hwnd );
1368 if (!wndPtr) return 0;
1369 if (offset >= 0)
1371 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1373 WARN( win, "Invalid offset %d\n", offset );
1374 return 0;
1376 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1378 switch(offset)
1380 case GWW_ID:
1381 if (HIWORD(wndPtr->wIDmenu))
1382 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1383 wndPtr->wIDmenu);
1384 return (WORD)wndPtr->wIDmenu;
1385 case GWW_HWNDPARENT:
1386 return wndPtr->parent ?
1387 wndPtr->parent->hwndSelf : (
1388 wndPtr->owner ?
1389 wndPtr->owner->hwndSelf :
1391 case GWW_HINSTANCE:
1392 if (HIWORD(wndPtr->hInstance))
1393 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1394 wndPtr->hInstance);
1395 return (WORD)wndPtr->hInstance;
1396 default:
1397 WARN( win, "Invalid offset %d\n", offset );
1398 return 0;
1403 /**********************************************************************
1404 * WIN_GetWindowInstance
1406 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1408 WND * wndPtr = WIN_FindWndPtr( hwnd );
1409 if (!wndPtr) return (HINSTANCE32)0;
1410 return wndPtr->hInstance;
1414 /**********************************************************************
1415 * SetWindowWord16 (USER.134)
1417 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1419 return SetWindowWord32( hwnd, offset, newval );
1423 /**********************************************************************
1424 * SetWindowWord32 (USER32.524)
1426 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1428 WORD *ptr, retval;
1429 WND * wndPtr = WIN_FindWndPtr( hwnd );
1430 if (!wndPtr) return 0;
1431 if (offset >= 0)
1433 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1435 WARN( win, "Invalid offset %d\n", offset );
1436 return 0;
1438 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1440 else switch(offset)
1442 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1443 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1444 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1445 default:
1446 WARN( win, "Invalid offset %d\n", offset );
1447 return 0;
1449 retval = *ptr;
1450 *ptr = newval;
1451 return retval;
1455 /**********************************************************************
1456 * WIN_GetWindowLong
1458 * Helper function for GetWindowLong().
1460 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1462 LONG retval;
1463 WND * wndPtr = WIN_FindWndPtr( hwnd );
1464 if (!wndPtr) return 0;
1465 if (offset >= 0)
1467 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1469 WARN( win, "Invalid offset %d\n", offset );
1470 return 0;
1472 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1473 /* Special case for dialog window procedure */
1474 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1475 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1476 return retval;
1478 switch(offset)
1480 case GWL_USERDATA: return wndPtr->userdata;
1481 case GWL_STYLE: return wndPtr->dwStyle;
1482 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1483 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1484 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1485 type );
1486 case GWL_HWNDPARENT: return wndPtr->parent ?
1487 (HWND32)wndPtr->parent->hwndSelf : 0;
1488 case GWL_HINSTANCE: return wndPtr->hInstance;
1489 default:
1490 WARN( win, "Unknown offset %d\n", offset );
1492 return 0;
1496 /**********************************************************************
1497 * WIN_SetWindowLong
1499 * Helper function for SetWindowLong().
1501 * 0 is the failure code. However, in the case of failure SetLastError
1502 * must be set to distinguish between a 0 return value and a failure.
1504 * FIXME: The error values for SetLastError may not be right. Can
1505 * someone check with the real thing?
1507 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1508 WINDOWPROCTYPE type )
1510 LONG *ptr, retval;
1511 WND * wndPtr = WIN_FindWndPtr( hwnd );
1512 STYLESTRUCT style;
1514 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1516 if (!wndPtr)
1518 /* Is this the right error? */
1519 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1520 return 0;
1523 if (offset >= 0)
1525 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1527 WARN( win, "Invalid offset %d\n", offset );
1529 /* Is this the right error? */
1530 SetLastError( ERROR_OUTOFMEMORY );
1532 return 0;
1534 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1535 /* Special case for dialog window procedure */
1536 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1538 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1539 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1540 type, WIN_PROC_WINDOW );
1541 return retval;
1544 else switch(offset)
1546 case GWL_ID:
1547 ptr = (DWORD*)&wndPtr->wIDmenu;
1548 break;
1549 case GWL_HINSTANCE:
1550 return SetWindowWord32( hwnd, offset, newval );
1551 case GWL_WNDPROC:
1552 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1553 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1554 type, WIN_PROC_WINDOW );
1555 return retval;
1556 case GWL_STYLE:
1557 style.styleOld = wndPtr->dwStyle;
1558 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1559 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1561 if (wndPtr->flags & WIN_ISWIN32)
1562 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1563 wndPtr->dwStyle = style.styleNew;
1564 if (wndPtr->flags & WIN_ISWIN32)
1565 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1566 return style.styleOld;
1568 case GWL_USERDATA:
1569 ptr = &wndPtr->userdata;
1570 break;
1571 case GWL_EXSTYLE:
1572 style.styleOld = wndPtr->dwExStyle;
1573 style.styleNew = newval;
1574 if (wndPtr->flags & WIN_ISWIN32)
1575 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1576 wndPtr->dwExStyle = newval;
1577 if (wndPtr->flags & WIN_ISWIN32)
1578 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1579 return style.styleOld;
1581 default:
1582 WARN( win, "Invalid offset %d\n", offset );
1584 /* Don't think this is right error but it should do */
1585 SetLastError( ERROR_OUTOFMEMORY );
1587 return 0;
1589 retval = *ptr;
1590 *ptr = newval;
1591 return retval;
1595 /**********************************************************************
1596 * GetWindowLong16 (USER.135)
1598 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1600 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1604 /**********************************************************************
1605 * GetWindowLong32A (USER32.305)
1607 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1609 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1613 /**********************************************************************
1614 * GetWindowLong32W (USER32.306)
1616 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1618 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1622 /**********************************************************************
1623 * SetWindowLong16 (USER.136)
1625 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1627 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1631 /**********************************************************************
1632 * SetWindowLong32A (USER32.517)
1634 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1636 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1640 /**********************************************************************
1641 * SetWindowLong32W (USER32.518) Set window attribute
1643 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1644 * value in a window's extra memory.
1646 * The _hwnd_ parameter specifies the window. is the handle to a
1647 * window that has extra memory. The _newval_ parameter contains the
1648 * new attribute or extra memory value. If positive, the _offset_
1649 * parameter is the byte-addressed location in the window's extra
1650 * memory to set. If negative, _offset_ specifies the window
1651 * attribute to set, and should be one of the following values:
1653 * GWL_EXSTYLE The window's extended window style
1655 * GWL_STYLE The window's window style.
1657 * GWL_WNDPROC Pointer to the window's window procedure.
1659 * GWL_HINSTANCE The window's pplication instance handle.
1661 * GWL_ID The window's identifier.
1663 * GWL_USERDATA The window's user-specified data.
1665 * If the window is a dialog box, the _offset_ parameter can be one of
1666 * the following values:
1668 * DWL_DLGPROC The address of the window's dialog box procedure.
1670 * DWL_MSGRESULT The return value of a message
1671 * that the dialog box procedure processed.
1673 * DWL_USER Application specific information.
1675 * RETURNS
1677 * If successful, returns the previous value located at _offset_. Otherwise,
1678 * returns 0.
1680 * NOTES
1682 * Extra memory for a window class is specified by a nonzero cbWndExtra
1683 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1684 * time of class creation.
1686 * Using GWL_WNDPROC to set a new window procedure effectively creates
1687 * a window subclass. Use CallWindowProc() in the new windows procedure
1688 * to pass messages to the superclass's window procedure.
1690 * The user data is reserved for use by the application which created
1691 * the window.
1693 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1694 * instead, call the EnableWindow() function to change the window's
1695 * disabled state.
1697 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1698 * SetParent() instead.
1700 * BUGS
1702 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1704 * CONFORMANCE
1706 * ECMA-234, Win32
1709 LONG WINAPI SetWindowLong32W(
1710 HWND32 hwnd, /* window to alter */
1711 INT32 offset, /* offset, in bytes, of location to alter */
1712 LONG newval /* new value of location */
1714 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1718 /*******************************************************************
1719 * GetWindowText16 (USER.36)
1721 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1723 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1727 /*******************************************************************
1728 * GetWindowText32A (USER32.309)
1730 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1732 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1733 (LPARAM)lpString );
1736 /*******************************************************************
1737 * InternalGetWindowText (USER32.326)
1739 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1741 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1742 return GetWindowText32W(hwnd,lpString,nMaxCount);
1746 /*******************************************************************
1747 * GetWindowText32W (USER32.312)
1749 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1751 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1752 (LPARAM)lpString );
1756 /*******************************************************************
1757 * SetWindowText16 (USER.37)
1759 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1761 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1765 /*******************************************************************
1766 * SetWindowText32A (USER32.521)
1768 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1770 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1774 /*******************************************************************
1775 * SetWindowText32W (USER32.523)
1777 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1779 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1783 /*******************************************************************
1784 * GetWindowTextLength16 (USER.38)
1786 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1788 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1792 /*******************************************************************
1793 * GetWindowTextLength32A (USER32.310)
1795 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1797 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1800 /*******************************************************************
1801 * GetWindowTextLength32W (USER32.311)
1803 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1805 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1809 /*******************************************************************
1810 * IsWindow16 (USER.47)
1812 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1814 return IsWindow32( hwnd );
1817 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1819 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1820 HWND16 hwnd = (HWND16)stack[2];
1822 AX_reg(context) = IsWindow32( hwnd );
1823 ES_reg(context) = USER_HeapSel;
1827 /*******************************************************************
1828 * IsWindow32 (USER32.348)
1830 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1832 WND * wndPtr = WIN_FindWndPtr( hwnd );
1833 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1837 /*****************************************************************
1838 * GetParent16 (USER.46)
1840 HWND16 WINAPI GetParent16( HWND16 hwnd )
1842 return (HWND16)GetParent32( hwnd );
1846 /*****************************************************************
1847 * GetParent32 (USER32.278)
1849 HWND32 WINAPI GetParent32( HWND32 hwnd )
1851 WND *wndPtr = WIN_FindWndPtr(hwnd);
1852 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1853 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1854 return wndPtr ? wndPtr->hwndSelf : 0;
1857 /*****************************************************************
1858 * WIN_GetTopParent
1860 * Get the top-level parent for a child window.
1862 WND* WIN_GetTopParentPtr( WND* pWnd )
1864 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1865 return pWnd;
1868 /*****************************************************************
1869 * WIN_GetTopParent
1871 * Get the top-level parent for a child window.
1873 HWND32 WIN_GetTopParent( HWND32 hwnd )
1875 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1876 return wndPtr ? wndPtr->hwndSelf : 0;
1880 /*****************************************************************
1881 * SetParent16 (USER.233)
1883 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1885 return SetParent32( hwndChild, hwndNewParent );
1889 /*****************************************************************
1890 * SetParent32 (USER32.495)
1892 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1894 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1895 WND *pWndNewParent =
1896 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1897 WND *pWndOldParent =
1898 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1900 return pWndOldParent?pWndOldParent->hwndSelf:0;
1903 /*******************************************************************
1904 * IsChild16 (USER.48)
1906 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1908 return IsChild32(parent,child);
1912 /*******************************************************************
1913 * IsChild32 (USER32.339)
1915 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1917 WND * wndPtr = WIN_FindWndPtr( child );
1918 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1920 wndPtr = wndPtr->parent;
1921 if (wndPtr->hwndSelf == parent) return TRUE;
1923 return FALSE;
1927 /***********************************************************************
1928 * IsWindowVisible16 (USER.49)
1930 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1932 return IsWindowVisible32(hwnd);
1936 /***********************************************************************
1937 * IsWindowVisible32 (USER32.351)
1939 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1941 WND *wndPtr = WIN_FindWndPtr( hwnd );
1942 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1944 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1945 wndPtr = wndPtr->parent;
1947 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1951 /***********************************************************************
1952 * WIN_IsWindowDrawable
1954 * hwnd is drawable when it is visible, all parents are not
1955 * minimized, and it is itself not minimized unless we are
1956 * trying to draw its default class icon.
1958 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1960 if( (wnd->dwStyle & WS_MINIMIZE &&
1961 icon && wnd->class->hIcon) ||
1962 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1963 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1964 if( wnd->dwStyle & WS_MINIMIZE ||
1965 !(wnd->dwStyle & WS_VISIBLE) ) break;
1966 return (wnd == NULL);
1970 /*******************************************************************
1971 * GetTopWindow16 (USER.229)
1973 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1975 return GetTopWindow32(hwnd);
1979 /*******************************************************************
1980 * GetTopWindow32 (USER.229)
1982 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1984 WND * wndPtr = WIN_FindWndPtr( hwnd );
1985 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1986 else return 0;
1990 /*******************************************************************
1991 * GetWindow16 (USER.262)
1993 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
1995 return GetWindow32( hwnd,rel );
1999 /*******************************************************************
2000 * GetWindow32 (USER32.302)
2002 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2004 WND * wndPtr = WIN_FindWndPtr( hwnd );
2005 if (!wndPtr) return 0;
2006 switch(rel)
2008 case GW_HWNDFIRST:
2009 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2010 else return 0;
2012 case GW_HWNDLAST:
2013 if (!wndPtr->parent) return 0; /* Desktop window */
2014 while (wndPtr->next) wndPtr = wndPtr->next;
2015 return wndPtr->hwndSelf;
2017 case GW_HWNDNEXT:
2018 if (!wndPtr->next) return 0;
2019 return wndPtr->next->hwndSelf;
2021 case GW_HWNDPREV:
2022 if (!wndPtr->parent) return 0; /* Desktop window */
2023 wndPtr = wndPtr->parent->child; /* First sibling */
2024 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2025 while (wndPtr->next)
2027 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2028 wndPtr = wndPtr->next;
2030 return 0;
2032 case GW_OWNER:
2033 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2035 case GW_CHILD:
2036 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2038 return 0;
2042 /*******************************************************************
2043 * GetNextWindow16 (USER.230)
2045 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2047 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2048 return GetWindow16( hwnd, flag );
2051 /*******************************************************************
2052 * ShowOwnedPopups16 (USER.265)
2054 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2056 ShowOwnedPopups32( owner, fShow );
2060 /*******************************************************************
2061 * ShowOwnedPopups32 (USER32.531)
2063 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2065 WND *pWnd = pWndDesktop->child;
2066 while (pWnd)
2068 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2069 (pWnd->dwStyle & WS_POPUP))
2070 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2071 pWnd = pWnd->next;
2073 return TRUE;
2077 /*******************************************************************
2078 * GetLastActivePopup16 (USER.287)
2080 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2082 return GetLastActivePopup32( hwnd );
2085 /*******************************************************************
2086 * GetLastActivePopup32 (USER32.256)
2088 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2090 WND *wndPtr;
2091 wndPtr = WIN_FindWndPtr(hwnd);
2092 if (wndPtr == NULL) return hwnd;
2093 return wndPtr->hwndLastActive;
2097 /*******************************************************************
2098 * WIN_BuildWinArray
2100 * Build an array of pointers to the children of a given window.
2101 * The array must be freed with HeapFree(SystemHeap). Return NULL
2102 * when no windows are found.
2104 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2106 WND **list, **ppWnd;
2107 WND *pWnd;
2108 UINT32 count, skipOwned, skipHidden;
2109 DWORD skipFlags;
2111 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2112 skipOwned = bwaFlags & BWA_SKIPOWNED;
2113 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2114 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2116 /* First count the windows */
2118 if (!wndPtr) wndPtr = pWndDesktop;
2119 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2121 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2122 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2125 if( count )
2127 /* Now build the list of all windows */
2129 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2131 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2133 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2134 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2136 *ppWnd++ = pWnd;
2137 count++;
2140 *ppWnd = NULL;
2142 else count = 0;
2143 } else list = NULL;
2145 if( pTotal ) *pTotal = count;
2146 return list;
2150 /*******************************************************************
2151 * EnumWindows16 (USER.54)
2153 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2155 WND **list, **ppWnd;
2157 /* We have to build a list of all windows first, to avoid */
2158 /* unpleasant side-effects, for instance if the callback */
2159 /* function changes the Z-order of the windows. */
2161 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2163 /* Now call the callback function for every window */
2165 for (ppWnd = list; *ppWnd; ppWnd++)
2167 /* Make sure that the window still exists */
2168 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2169 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2171 HeapFree( SystemHeap, 0, list );
2172 return TRUE;
2176 /*******************************************************************
2177 * EnumWindows32 (USER32.193)
2179 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2181 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2185 /**********************************************************************
2186 * EnumTaskWindows16 (USER.225)
2188 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2189 LPARAM lParam )
2191 WND **list, **ppWnd;
2193 /* This function is the same as EnumWindows(), */
2194 /* except for an added check on the window's task. */
2196 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2198 /* Now call the callback function for every window */
2200 for (ppWnd = list; *ppWnd; ppWnd++)
2202 /* Make sure that the window still exists */
2203 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2204 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2205 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2207 HeapFree( SystemHeap, 0, list );
2208 return TRUE;
2212 /**********************************************************************
2213 * EnumThreadWindows (USER32.190)
2215 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2217 THDB *tdb = THREAD_ID_TO_THDB(id);
2219 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2223 /**********************************************************************
2224 * WIN_EnumChildWindows
2226 * Helper function for EnumChildWindows().
2228 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2229 LPARAM lParam )
2231 WND **childList;
2232 BOOL16 ret = FALSE;
2234 for ( ; *ppWnd; ppWnd++)
2236 /* Make sure that the window still exists */
2237 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2238 /* Build children list first */
2239 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2240 ret = func( (*ppWnd)->hwndSelf, lParam );
2241 if (childList)
2243 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2244 HeapFree( SystemHeap, 0, childList );
2246 if (!ret) return FALSE;
2248 return TRUE;
2252 /**********************************************************************
2253 * EnumChildWindows16 (USER.55)
2255 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2256 LPARAM lParam )
2258 WND **list, *pParent;
2260 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2261 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2262 WIN_EnumChildWindows( list, func, lParam );
2263 HeapFree( SystemHeap, 0, list );
2264 return TRUE;
2268 /**********************************************************************
2269 * EnumChildWindows32 (USER32.178)
2271 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2272 LPARAM lParam )
2274 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2275 lParam );
2279 /*******************************************************************
2280 * AnyPopup16 (USER.52)
2282 BOOL16 WINAPI AnyPopup16(void)
2284 return AnyPopup32();
2288 /*******************************************************************
2289 * AnyPopup32 (USER32.4)
2291 BOOL32 WINAPI AnyPopup32(void)
2293 WND *wndPtr;
2294 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2295 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2296 return FALSE;
2300 /*******************************************************************
2301 * FlashWindow16 (USER.105)
2303 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2305 return FlashWindow32( hWnd, bInvert );
2309 /*******************************************************************
2310 * FlashWindow32 (USER32.202)
2312 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2314 WND *wndPtr = WIN_FindWndPtr(hWnd);
2316 TRACE(win,"%04x\n", hWnd);
2318 if (!wndPtr) return FALSE;
2320 if (wndPtr->dwStyle & WS_MINIMIZE)
2322 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2324 HDC32 hDC = GetDC32(hWnd);
2326 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2327 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2329 ReleaseDC32( hWnd, hDC );
2330 wndPtr->flags |= WIN_NCACTIVATED;
2332 else
2334 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2335 RDW_UPDATENOW | RDW_FRAME, 0 );
2336 wndPtr->flags &= ~WIN_NCACTIVATED;
2338 return TRUE;
2340 else
2342 WPARAM16 wparam;
2343 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2344 else wparam = (hWnd == GetActiveWindow32());
2346 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2347 return wparam;
2352 /*******************************************************************
2353 * SetSysModalWindow16 (USER.188)
2355 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2357 HWND32 hWndOldModal = hwndSysModal;
2358 hwndSysModal = hWnd;
2359 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2360 return hWndOldModal;
2364 /*******************************************************************
2365 * GetSysModalWindow16 (USER.52)
2367 HWND16 WINAPI GetSysModalWindow16(void)
2369 return hwndSysModal;
2373 /*******************************************************************
2374 * GetWindowContextHelpId (USER32.303)
2376 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2378 WND *wnd = WIN_FindWndPtr( hwnd );
2379 if (!wnd) return 0;
2380 return wnd->helpContext;
2384 /*******************************************************************
2385 * SetWindowContextHelpId (USER32.515)
2387 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2389 WND *wnd = WIN_FindWndPtr( hwnd );
2390 if (!wnd) return FALSE;
2391 wnd->helpContext = id;
2392 return TRUE;
2396 /*******************************************************************
2397 * DRAG_QueryUpdate
2399 * recursively find a child that contains spDragInfo->pt point
2400 * and send WM_QUERYDROPOBJECT
2402 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2404 BOOL16 wParam,bResult = 0;
2405 POINT32 pt;
2406 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2407 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2408 RECT32 tempRect;
2410 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2412 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2414 GetWindowRect32(hQueryWnd,&tempRect);
2416 if( !PtInRect32(&tempRect,pt) ||
2417 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2418 return 0;
2420 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2422 tempRect = ptrQueryWnd->rectClient;
2423 if(ptrQueryWnd->dwStyle & WS_CHILD)
2424 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2425 (LPPOINT32)&tempRect, 2 );
2427 if (PtInRect32( &tempRect, pt))
2429 wParam = 0;
2431 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2432 if( ptrWnd->dwStyle & WS_VISIBLE )
2434 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2435 if (PtInRect32( &tempRect, pt )) break;
2438 if(ptrWnd)
2440 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2441 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2442 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2443 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2444 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2447 if(bResult) return bResult;
2449 else wParam = 1;
2451 else wParam = 1;
2453 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2455 ptrDragInfo->hScope = hQueryWnd;
2457 bResult = ( bNoSend )
2458 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2459 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2460 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2461 if( !bResult )
2462 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2464 return bResult;
2468 /*******************************************************************
2469 * DragDetect (USER.465)
2471 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2473 POINT32 pt32;
2474 CONV_POINT16TO32( &pt, &pt32 );
2475 return DragDetect32( hWnd, pt32 );
2478 /*******************************************************************
2479 * DragDetect32 (USER32.151)
2481 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2483 MSG16 msg;
2484 RECT16 rect;
2486 rect.left = pt.x - wDragWidth;
2487 rect.right = pt.x + wDragWidth;
2489 rect.top = pt.y - wDragHeight;
2490 rect.bottom = pt.y + wDragHeight;
2492 SetCapture32(hWnd);
2494 while(1)
2496 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2498 if( msg.message == WM_LBUTTONUP )
2500 ReleaseCapture();
2501 return 0;
2503 if( msg.message == WM_MOUSEMOVE )
2505 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2507 ReleaseCapture();
2508 return 1;
2512 WaitMessage();
2514 return 0;
2517 /******************************************************************************
2518 * DragObject16 (USER.464)
2520 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2521 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2523 MSG16 msg;
2524 LPDRAGINFO lpDragInfo;
2525 SEGPTR spDragInfo;
2526 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2527 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2528 WND *wndPtr = WIN_FindWndPtr(hWnd);
2529 HCURSOR16 hCurrentCursor = 0;
2530 HWND16 hCurrentWnd = 0;
2532 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2533 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2535 if( !lpDragInfo || !spDragInfo ) return 0L;
2537 hBummer = LoadCursor16(0, IDC_BUMMER16);
2539 if( !hBummer || !wndPtr )
2541 GlobalFree16(hDragInfo);
2542 return 0L;
2545 if(hCursor)
2547 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2549 GlobalFree16(hDragInfo);
2550 return 0L;
2553 if( hDragCursor == hCursor ) hDragCursor = 0;
2554 else hCursor = hDragCursor;
2556 hOldCursor = SetCursor32(hDragCursor);
2559 lpDragInfo->hWnd = hWnd;
2560 lpDragInfo->hScope = 0;
2561 lpDragInfo->wFlags = wObj;
2562 lpDragInfo->hList = szList; /* near pointer! */
2563 lpDragInfo->hOfStruct = hOfStruct;
2564 lpDragInfo->l = 0L;
2566 SetCapture32(hWnd);
2567 ShowCursor32( TRUE );
2571 do{ WaitMessage(); }
2572 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2574 *(lpDragInfo+1) = *lpDragInfo;
2576 lpDragInfo->pt = msg.pt;
2578 /* update DRAGINFO struct */
2579 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2581 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2582 hCurrentCursor = hCursor;
2583 else
2585 hCurrentCursor = hBummer;
2586 lpDragInfo->hScope = 0;
2588 if( hCurrentCursor )
2589 SetCursor32(hCurrentCursor);
2591 /* send WM_DRAGLOOP */
2592 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2593 (LPARAM) spDragInfo );
2594 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2595 if( hCurrentWnd != lpDragInfo->hScope )
2597 if( hCurrentWnd )
2598 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2599 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2600 HIWORD(spDragInfo)) );
2601 hCurrentWnd = lpDragInfo->hScope;
2602 if( hCurrentWnd )
2603 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2605 else
2606 if( hCurrentWnd )
2607 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2609 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2611 ReleaseCapture();
2612 ShowCursor32( FALSE );
2614 if( hCursor )
2616 SetCursor32( hOldCursor );
2617 if (hDragCursor) DestroyCursor32( hDragCursor );
2620 if( hCurrentCursor != hBummer )
2621 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2622 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2623 else
2624 msg.lParam = 0;
2625 GlobalFree16(hDragInfo);
2627 return (DWORD)(msg.lParam);