Delphi 2.0 needs to allocate a bitmap bigger than 4096 bits wide.
[wine.git] / windows / win.c
blob10b1612369c7644749b1cebb9dcf19dfc2051d61
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 wndPtr->pDriver->pFinalize(wndPtr);
326 USER_HEAP_FREE( hwnd );
327 return pWnd;
330 /***********************************************************************
331 * WIN_ResetQueueWindows
333 * Reset the queue of all the children of a given window.
334 * Return TRUE if something was done.
336 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
338 BOOL32 ret = FALSE;
340 if (hNew) /* Set a new queue */
342 for (wnd = wnd->child; (wnd); wnd = wnd->next)
344 if (wnd->hmemTaskQ == hQueue)
346 wnd->hmemTaskQ = hNew;
347 ret = TRUE;
349 if (wnd->child)
350 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
353 else /* Queue is being destroyed */
355 while (wnd->child)
357 WND *tmp = wnd->child;
358 ret = FALSE;
359 while (tmp)
361 if (tmp->hmemTaskQ == hQueue)
363 DestroyWindow32( tmp->hwndSelf );
364 ret = TRUE;
365 break;
367 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
368 ret = TRUE;
369 else
370 tmp = tmp->next;
372 if (!ret) break;
375 return ret;
378 /***********************************************************************
379 * WIN_CreateDesktopWindow
381 * Create the desktop window.
383 BOOL32 WIN_CreateDesktopWindow(void)
385 CLASS *class;
386 HWND32 hwndDesktop;
388 TRACE(win,"Creating desktop window\n");
390 if (!ICONTITLE_Init() ||
391 !WINPOS_CreateInternalPosAtom() ||
392 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
393 return FALSE;
395 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
396 if (!hwndDesktop) return FALSE;
397 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
399 pWndDesktop->pDriver = &X11DRV_WND_Driver;
400 pWndDesktop->pDriver->pInitialize(pWndDesktop);
402 pWndDesktop->next = NULL;
403 pWndDesktop->child = NULL;
404 pWndDesktop->parent = NULL;
405 pWndDesktop->owner = NULL;
406 pWndDesktop->class = class;
407 pWndDesktop->dwMagic = WND_MAGIC;
408 pWndDesktop->hwndSelf = hwndDesktop;
409 pWndDesktop->hInstance = 0;
410 pWndDesktop->rectWindow.left = 0;
411 pWndDesktop->rectWindow.top = 0;
412 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
413 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
414 pWndDesktop->rectClient = pWndDesktop->rectWindow;
415 pWndDesktop->text = NULL;
416 pWndDesktop->hmemTaskQ = GetFastQueue();
417 pWndDesktop->hrgnUpdate = 0;
418 pWndDesktop->hwndLastActive = hwndDesktop;
419 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
420 WS_CLIPSIBLINGS;
421 pWndDesktop->dwExStyle = 0;
422 pWndDesktop->dce = NULL;
423 pWndDesktop->pVScroll = NULL;
424 pWndDesktop->pHScroll = NULL;
425 pWndDesktop->pProp = NULL;
426 pWndDesktop->wIDmenu = 0;
427 pWndDesktop->helpContext = 0;
428 pWndDesktop->flags = 0;
429 pWndDesktop->hSysMenu = 0;
430 pWndDesktop->userdata = 0;
431 pWndDesktop->winproc = (WNDPROC16)class->winproc;
433 /* FIXME: How do we know if it should be Unicode or not */
434 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
435 return FALSE;
437 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
438 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
439 return TRUE;
443 /***********************************************************************
444 * WIN_CreateWindowEx
446 * Implementation of CreateWindowEx().
448 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
449 BOOL32 win32, BOOL32 unicode )
451 CLASS *classPtr;
452 WND *wndPtr;
453 HWND16 hwnd, hwndLinkAfter;
454 POINT32 maxSize, maxPos, minTrack, maxTrack;
455 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
457 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
458 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
459 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
460 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
461 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
463 /* Find the parent window */
465 if (cs->hwndParent)
467 /* Make sure parent is valid */
468 if (!IsWindow32( cs->hwndParent ))
470 WARN( win, "Bad parent %04x\n", cs->hwndParent );
471 return 0;
473 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
474 WARN( win, "No parent for child window\n" );
475 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
478 /* Find the window class */
479 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
481 char buffer[256];
482 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
483 WARN( win, "Bad class '%s'\n", buffer );
484 return 0;
487 /* Fix the coordinates */
489 if (cs->x == CW_USEDEFAULT32)
491 PDB32 *pdb = PROCESS_Current();
492 if ( !(cs->style & (WS_CHILD | WS_POPUP))
493 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
495 cs->x = pdb->env_db->startup_info->dwX;
496 cs->y = pdb->env_db->startup_info->dwY;
498 else
500 cs->x = 0;
501 cs->y = 0;
504 if (cs->cx == CW_USEDEFAULT32)
506 PDB32 *pdb = PROCESS_Current();
507 if ( !(cs->style & (WS_CHILD | WS_POPUP))
508 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
510 cs->cx = pdb->env_db->startup_info->dwXSize;
511 cs->cy = pdb->env_db->startup_info->dwYSize;
513 else
515 cs->cx = 600; /* FIXME */
516 cs->cy = 400;
520 /* Create the window structure */
522 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
523 - sizeof(wndPtr->wExtra) )))
525 TRACE(win, "out of memory\n" );
526 return 0;
529 /* Fill the window structure */
531 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
532 wndPtr->next = NULL;
533 wndPtr->child = NULL;
535 if ((cs->style & WS_CHILD) && cs->hwndParent)
537 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
538 wndPtr->owner = NULL;
540 else
542 wndPtr->parent = pWndDesktop;
543 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
544 wndPtr->owner = NULL;
545 else
546 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
549 wndPtr->pDriver = wndPtr->parent->pDriver;
550 wndPtr->pDriver->pInitialize(wndPtr);
552 wndPtr->class = classPtr;
553 wndPtr->winproc = classPtr->winproc;
554 wndPtr->dwMagic = WND_MAGIC;
555 wndPtr->hwndSelf = hwnd;
556 wndPtr->hInstance = cs->hInstance;
557 wndPtr->text = NULL;
558 wndPtr->hmemTaskQ = GetFastQueue();
559 wndPtr->hrgnUpdate = 0;
560 wndPtr->hwndLastActive = hwnd;
561 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
562 wndPtr->dwExStyle = cs->dwExStyle;
563 wndPtr->wIDmenu = 0;
564 wndPtr->helpContext = 0;
565 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
566 wndPtr->pVScroll = NULL;
567 wndPtr->pHScroll = NULL;
568 wndPtr->pProp = NULL;
569 wndPtr->userdata = 0;
570 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
571 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
573 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
575 /* Call the WH_CBT hook */
577 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
578 ? HWND_BOTTOM : HWND_TOP;
580 if (HOOK_IsHooked( WH_CBT ))
582 CBT_CREATEWND32A cbtc;
583 LRESULT ret;
585 cbtc.lpcs = cs;
586 cbtc.hwndInsertAfter = hwndLinkAfter;
587 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
588 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
589 if (ret)
591 TRACE(win, "CBT-hook returned 0\n");
592 wndPtr->pDriver->pFinalize(wndPtr);
593 USER_HEAP_FREE( hwnd );
594 return 0;
598 /* Increment class window counter */
600 classPtr->cWindows++;
602 /* Correct the window style */
604 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
606 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
607 wndPtr->flags |= WIN_NEED_SIZE;
609 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
611 /* Get class or window DC if needed */
613 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
614 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
615 else wndPtr->dce = NULL;
617 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
619 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
621 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
622 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
623 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
624 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
625 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
628 if(cs->style & WS_CHILD)
630 if(cs->cx < 0) cs->cx = 0;
631 if(cs->cy < 0) cs->cy = 0;
633 else
635 if (cs->cx <= 0) cs->cx = 1;
636 if (cs->cy <= 0) cs->cy = 1;
639 wndPtr->rectWindow.left = cs->x;
640 wndPtr->rectWindow.top = cs->y;
641 wndPtr->rectWindow.right = cs->x + cs->cx;
642 wndPtr->rectWindow.bottom = cs->y + cs->cy;
643 wndPtr->rectClient = wndPtr->rectWindow;
645 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
646 return FALSE;
648 /* Set the window menu */
650 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
652 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
653 else
655 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
656 if (classPtr->menuNameA)
657 cs->hMenu = HIWORD(classPtr->menuNameA) ?
658 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
659 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
660 #else
661 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
662 if (menuName)
664 if (HIWORD(cs->hInstance))
665 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
666 else
667 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
669 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
671 #endif
674 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
676 /* Send the WM_CREATE message
677 * Perhaps we shouldn't allow width/height changes as well.
678 * See p327 in "Internals".
681 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
683 localSend32 = unicode ? SendMessage32W : SendMessage32A;
684 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
686 /* Insert the window in the linked list */
688 WIN_LinkWindow( hwnd, hwndLinkAfter );
690 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
691 NULL, NULL, 0, &wndPtr->rectClient );
692 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
693 maxPos.y - wndPtr->rectWindow.top);
694 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
696 /* Send the size messages */
698 if (!(wndPtr->flags & WIN_NEED_SIZE))
700 /* send it anyway */
701 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
702 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
703 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
704 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
705 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
706 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
707 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
708 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
709 SendMessage32A( hwnd, WM_MOVE, 0,
710 MAKELONG( wndPtr->rectClient.left,
711 wndPtr->rectClient.top ) );
714 /* Show the window, maximizing or minimizing if needed */
716 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
718 RECT16 newPos;
719 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
720 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
721 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
722 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
723 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
724 : SWP_NOZORDER | SWP_FRAMECHANGED;
725 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
726 newPos.right, newPos.bottom, swFlag );
729 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
731 /* Notify the parent window only */
733 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
734 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
735 if( !IsWindow32(hwnd) ) return 0;
738 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
740 /* Call WH_SHELL hook */
742 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
743 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
745 TRACE(win, "created window %04x\n", hwnd);
746 return hwnd;
748 WIN_UnlinkWindow( hwnd );
751 /* Abort window creation */
753 WARN(win, "aborted by WM_xxCREATE!\n");
754 WIN_DestroyWindow( wndPtr );
755 return 0;
759 /***********************************************************************
760 * CreateWindow16 (USER.41)
762 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
763 DWORD style, INT16 x, INT16 y, INT16 width,
764 INT16 height, HWND16 parent, HMENU16 menu,
765 HINSTANCE16 instance, LPVOID data )
767 return CreateWindowEx16( 0, className, windowName, style,
768 x, y, width, height, parent, menu, instance, data );
772 /***********************************************************************
773 * CreateWindowEx16 (USER.452)
775 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
776 LPCSTR windowName, DWORD style, INT16 x,
777 INT16 y, INT16 width, INT16 height,
778 HWND16 parent, HMENU16 menu,
779 HINSTANCE16 instance, LPVOID data )
781 ATOM classAtom;
782 CREATESTRUCT32A cs;
784 /* Find the class atom */
786 if (!(classAtom = GlobalFindAtom32A( className )))
788 fprintf( stderr, "CreateWindowEx16: bad class name " );
789 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
790 else fprintf( stderr, "'%s'\n", className );
791 return 0;
794 /* Fix the coordinates */
796 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
797 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
798 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
799 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
801 /* Create the window */
803 cs.lpCreateParams = data;
804 cs.hInstance = (HINSTANCE32)instance;
805 cs.hMenu = (HMENU32)menu;
806 cs.hwndParent = (HWND32)parent;
807 cs.style = style;
808 cs.lpszName = windowName;
809 cs.lpszClass = className;
810 cs.dwExStyle = exStyle;
811 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
815 /***********************************************************************
816 * CreateWindowEx32A (USER32.83)
818 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
819 LPCSTR windowName, DWORD style, INT32 x,
820 INT32 y, INT32 width, INT32 height,
821 HWND32 parent, HMENU32 menu,
822 HINSTANCE32 instance, LPVOID data )
824 ATOM classAtom;
825 CREATESTRUCT32A cs;
827 if(exStyle & WS_EX_MDICHILD)
828 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
829 /* Find the class atom */
831 if (!(classAtom = GlobalFindAtom32A( className )))
833 fprintf( stderr, "CreateWindowEx32A: bad class name " );
834 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
835 else fprintf( stderr, "'%s'\n", className );
836 return 0;
839 /* Create the window */
841 cs.lpCreateParams = data;
842 cs.hInstance = instance;
843 cs.hMenu = menu;
844 cs.hwndParent = parent;
845 cs.x = x;
846 cs.y = y;
847 cs.cx = width;
848 cs.cy = height;
849 cs.style = style;
850 cs.lpszName = windowName;
851 cs.lpszClass = className;
852 cs.dwExStyle = exStyle;
853 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
857 /***********************************************************************
858 * CreateWindowEx32W (USER32.84)
860 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
861 LPCWSTR windowName, DWORD style, INT32 x,
862 INT32 y, INT32 width, INT32 height,
863 HWND32 parent, HMENU32 menu,
864 HINSTANCE32 instance, LPVOID data )
866 ATOM classAtom;
867 CREATESTRUCT32W cs;
869 if(exStyle & WS_EX_MDICHILD)
870 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
872 /* Find the class atom */
874 if (!(classAtom = GlobalFindAtom32W( className )))
876 if (HIWORD(className))
878 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
879 WARN( win, "Bad class name '%s'\n",cn);
880 HeapFree( GetProcessHeap(), 0, cn );
882 else
883 WARN( win, "Bad class name %p\n", className );
884 return 0;
887 /* Create the window */
889 cs.lpCreateParams = data;
890 cs.hInstance = instance;
891 cs.hMenu = menu;
892 cs.hwndParent = parent;
893 cs.x = x;
894 cs.y = y;
895 cs.cx = width;
896 cs.cy = height;
897 cs.style = style;
898 cs.lpszName = windowName;
899 cs.lpszClass = className;
900 cs.dwExStyle = exStyle;
901 /* Note: we rely on the fact that CREATESTRUCT32A and */
902 /* CREATESTRUCT32W have the same layout. */
903 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
907 /***********************************************************************
908 * WIN_CheckFocus
910 static void WIN_CheckFocus( WND* pWnd )
912 if( GetFocus16() == pWnd->hwndSelf )
913 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
916 /***********************************************************************
917 * WIN_SendDestroyMsg
919 static void WIN_SendDestroyMsg( WND* pWnd )
921 WIN_CheckFocus(pWnd);
923 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
924 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
926 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
928 if( IsWindow32(pWnd->hwndSelf) )
930 WND* pChild = pWnd->child;
931 while( pChild )
933 WIN_SendDestroyMsg( pChild );
934 pChild = pChild->next;
936 WIN_CheckFocus(pWnd);
938 else
939 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
943 /***********************************************************************
944 * DestroyWindow16 (USER.53)
946 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
948 return DestroyWindow32(hwnd);
952 /***********************************************************************
953 * DestroyWindow32 (USER32.135)
955 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
957 WND * wndPtr;
959 TRACE(win, "(%04x)\n", hwnd);
961 /* Initialization */
963 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
964 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
966 /* Call hooks */
968 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
969 return FALSE;
971 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
973 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
974 /* FIXME: clean up palette - see "Internals" p.352 */
977 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
978 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
980 /* Notify the parent window only */
981 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
982 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
983 if( !IsWindow32(hwnd) ) return TRUE;
986 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
988 /* Hide the window */
990 if (wndPtr->dwStyle & WS_VISIBLE)
992 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
993 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
994 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
995 if (!IsWindow32(hwnd)) return TRUE;
998 /* Recursively destroy owned windows */
1000 if( !(wndPtr->dwStyle & WS_CHILD) )
1002 /* make sure top menu popup doesn't get destroyed */
1003 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1005 for (;;)
1007 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1008 while (siblingPtr)
1010 if (siblingPtr->owner == wndPtr)
1012 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1013 break;
1014 else
1015 siblingPtr->owner = NULL;
1017 siblingPtr = siblingPtr->next;
1019 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1020 else break;
1023 if( !Options.managed || EVENT_CheckFocus() )
1024 WINPOS_ActivateOtherWindow(wndPtr);
1026 if( wndPtr->owner &&
1027 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1028 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1031 /* Send destroy messages */
1033 WIN_SendDestroyMsg( wndPtr );
1034 if (!IsWindow32(hwnd)) return TRUE;
1036 /* Unlink now so we won't bother with the children later on */
1038 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1040 /* Destroy the window storage */
1042 WIN_DestroyWindow( wndPtr );
1043 return TRUE;
1047 /***********************************************************************
1048 * CloseWindow16 (USER.43)
1050 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1052 return CloseWindow32( hwnd );
1056 /***********************************************************************
1057 * CloseWindow32 (USER32.56)
1059 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1061 WND * wndPtr = WIN_FindWndPtr( hwnd );
1062 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1063 ShowWindow32( hwnd, SW_MINIMIZE );
1064 return TRUE;
1068 /***********************************************************************
1069 * OpenIcon16 (USER.44)
1071 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1073 return OpenIcon32( hwnd );
1077 /***********************************************************************
1078 * OpenIcon32 (USER32.410)
1080 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1082 if (!IsIconic32( hwnd )) return FALSE;
1083 ShowWindow32( hwnd, SW_SHOWNORMAL );
1084 return TRUE;
1088 /***********************************************************************
1089 * WIN_FindWindow
1091 * Implementation of FindWindow() and FindWindowEx().
1093 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1094 LPCSTR title )
1096 WND *pWnd;
1097 CLASS *pClass = NULL;
1099 if (child)
1101 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1102 if (parent)
1104 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1106 else if (pWnd->parent != pWndDesktop) return 0;
1107 pWnd = pWnd->next;
1109 else
1111 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1112 pWnd = pWnd->child;
1114 if (!pWnd) return 0;
1116 /* For a child window, all siblings will have the same hInstance, */
1117 /* so we can look for the class once and for all. */
1119 if (className && (pWnd->dwStyle & WS_CHILD))
1121 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1122 return 0;
1126 for ( ; pWnd; pWnd = pWnd->next)
1128 if (className && !(pWnd->dwStyle & WS_CHILD))
1130 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1131 continue; /* Skip this window */
1134 if (pClass && (pWnd->class != pClass))
1135 continue; /* Not the right class */
1137 /* Now check the title */
1139 if (!title) return pWnd->hwndSelf;
1140 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1142 return 0;
1147 /***********************************************************************
1148 * FindWindow16 (USER.50)
1150 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1152 return FindWindowEx16( 0, 0, className, title );
1156 /***********************************************************************
1157 * FindWindowEx16 (USER.427)
1159 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1160 SEGPTR className, LPCSTR title )
1162 ATOM atom = 0;
1164 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1165 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1166 title ? title : "");
1168 if (className)
1170 /* If the atom doesn't exist, then no class */
1171 /* with this name exists either. */
1172 if (!(atom = GlobalFindAtom16( className ))) return 0;
1174 return WIN_FindWindow( parent, child, atom, title );
1178 /***********************************************************************
1179 * FindWindow32A (USER32.198)
1181 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1183 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1184 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1185 return ret;
1189 /***********************************************************************
1190 * FindWindowEx32A (USER32.199)
1192 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1193 LPCSTR className, LPCSTR title )
1195 ATOM atom = 0;
1197 if (className)
1199 /* If the atom doesn't exist, then no class */
1200 /* with this name exists either. */
1201 if (!(atom = GlobalFindAtom32A( className )))
1203 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1204 return 0;
1207 return WIN_FindWindow( parent, child, atom, title );
1211 /***********************************************************************
1212 * FindWindowEx32W (USER32.200)
1214 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1215 LPCWSTR className, LPCWSTR title )
1217 ATOM atom = 0;
1218 char *buffer;
1219 HWND32 hwnd;
1221 if (className)
1223 /* If the atom doesn't exist, then no class */
1224 /* with this name exists either. */
1225 if (!(atom = GlobalFindAtom32W( className )))
1227 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1228 return 0;
1231 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1232 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1233 HeapFree( GetProcessHeap(), 0, buffer );
1234 return hwnd;
1238 /***********************************************************************
1239 * FindWindow32W (USER32.201)
1241 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1243 return FindWindowEx32W( 0, 0, className, title );
1247 /**********************************************************************
1248 * WIN_GetDesktop
1250 WND *WIN_GetDesktop(void)
1252 return pWndDesktop;
1256 /**********************************************************************
1257 * GetDesktopWindow16 (USER.286)
1259 HWND16 WINAPI GetDesktopWindow16(void)
1261 return (HWND16)pWndDesktop->hwndSelf;
1265 /**********************************************************************
1266 * GetDesktopWindow32 (USER32.232)
1268 HWND32 WINAPI GetDesktopWindow32(void)
1270 return pWndDesktop->hwndSelf;
1274 /**********************************************************************
1275 * GetDesktopHwnd (USER.278)
1277 * Exactly the same thing as GetDesktopWindow(), but not documented.
1278 * Don't ask me why...
1280 HWND16 WINAPI GetDesktopHwnd(void)
1282 return (HWND16)pWndDesktop->hwndSelf;
1286 /*******************************************************************
1287 * EnableWindow16 (USER.34)
1289 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1291 return EnableWindow32( hwnd, enable );
1295 /*******************************************************************
1296 * EnableWindow32 (USER32.172)
1298 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1300 WND *wndPtr;
1302 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1303 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1305 /* Enable window */
1306 wndPtr->dwStyle &= ~WS_DISABLED;
1307 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1308 return TRUE;
1310 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1312 /* Disable window */
1313 wndPtr->dwStyle |= WS_DISABLED;
1314 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1315 SetFocus32( 0 ); /* A disabled window can't have the focus */
1316 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1317 ReleaseCapture(); /* A disabled window can't capture the mouse */
1318 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1319 return FALSE;
1321 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1325 /***********************************************************************
1326 * IsWindowEnabled16 (USER.35)
1328 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1330 return IsWindowEnabled32(hWnd);
1334 /***********************************************************************
1335 * IsWindowEnabled32 (USER32.349)
1337 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1339 WND * wndPtr;
1341 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1342 return !(wndPtr->dwStyle & WS_DISABLED);
1346 /***********************************************************************
1347 * IsWindowUnicode (USER32.350)
1349 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1351 WND * wndPtr;
1353 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1354 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1358 /**********************************************************************
1359 * GetWindowWord16 (USER.133)
1361 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1363 return GetWindowWord32( hwnd, offset );
1367 /**********************************************************************
1368 * GetWindowWord32 (USER32.314)
1370 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1372 WND * wndPtr = WIN_FindWndPtr( hwnd );
1373 if (!wndPtr) return 0;
1374 if (offset >= 0)
1376 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1378 WARN( win, "Invalid offset %d\n", offset );
1379 return 0;
1381 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1383 switch(offset)
1385 case GWW_ID:
1386 if (HIWORD(wndPtr->wIDmenu))
1387 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1388 wndPtr->wIDmenu);
1389 return (WORD)wndPtr->wIDmenu;
1390 case GWW_HWNDPARENT:
1391 return wndPtr->parent ?
1392 wndPtr->parent->hwndSelf : (
1393 wndPtr->owner ?
1394 wndPtr->owner->hwndSelf :
1396 case GWW_HINSTANCE:
1397 if (HIWORD(wndPtr->hInstance))
1398 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1399 wndPtr->hInstance);
1400 return (WORD)wndPtr->hInstance;
1401 default:
1402 WARN( win, "Invalid offset %d\n", offset );
1403 return 0;
1408 /**********************************************************************
1409 * WIN_GetWindowInstance
1411 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1413 WND * wndPtr = WIN_FindWndPtr( hwnd );
1414 if (!wndPtr) return (HINSTANCE32)0;
1415 return wndPtr->hInstance;
1419 /**********************************************************************
1420 * SetWindowWord16 (USER.134)
1422 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1424 return SetWindowWord32( hwnd, offset, newval );
1428 /**********************************************************************
1429 * SetWindowWord32 (USER32.524)
1431 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1433 WORD *ptr, retval;
1434 WND * wndPtr = WIN_FindWndPtr( hwnd );
1435 if (!wndPtr) return 0;
1436 if (offset >= 0)
1438 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1440 WARN( win, "Invalid offset %d\n", offset );
1441 return 0;
1443 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1445 else switch(offset)
1447 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1448 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1449 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1450 default:
1451 WARN( win, "Invalid offset %d\n", offset );
1452 return 0;
1454 retval = *ptr;
1455 *ptr = newval;
1456 return retval;
1460 /**********************************************************************
1461 * WIN_GetWindowLong
1463 * Helper function for GetWindowLong().
1465 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1467 LONG retval;
1468 WND * wndPtr = WIN_FindWndPtr( hwnd );
1469 if (!wndPtr) return 0;
1470 if (offset >= 0)
1472 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1474 WARN( win, "Invalid offset %d\n", offset );
1475 return 0;
1477 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1478 /* Special case for dialog window procedure */
1479 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1480 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1481 return retval;
1483 switch(offset)
1485 case GWL_USERDATA: return wndPtr->userdata;
1486 case GWL_STYLE: return wndPtr->dwStyle;
1487 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1488 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1489 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1490 type );
1491 case GWL_HWNDPARENT: return wndPtr->parent ?
1492 (HWND32)wndPtr->parent->hwndSelf : 0;
1493 case GWL_HINSTANCE: return wndPtr->hInstance;
1494 default:
1495 WARN( win, "Unknown offset %d\n", offset );
1497 return 0;
1501 /**********************************************************************
1502 * WIN_SetWindowLong
1504 * Helper function for SetWindowLong().
1506 * 0 is the failure code. However, in the case of failure SetLastError
1507 * must be set to distinguish between a 0 return value and a failure.
1509 * FIXME: The error values for SetLastError may not be right. Can
1510 * someone check with the real thing?
1512 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1513 WINDOWPROCTYPE type )
1515 LONG *ptr, retval;
1516 WND * wndPtr = WIN_FindWndPtr( hwnd );
1517 STYLESTRUCT style;
1519 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1521 if (!wndPtr)
1523 /* Is this the right error? */
1524 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1525 return 0;
1528 if (offset >= 0)
1530 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1532 WARN( win, "Invalid offset %d\n", offset );
1534 /* Is this the right error? */
1535 SetLastError( ERROR_OUTOFMEMORY );
1537 return 0;
1539 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1540 /* Special case for dialog window procedure */
1541 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1543 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1544 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1545 type, WIN_PROC_WINDOW );
1546 return retval;
1549 else switch(offset)
1551 case GWL_ID:
1552 ptr = (DWORD*)&wndPtr->wIDmenu;
1553 break;
1554 case GWL_HINSTANCE:
1555 return SetWindowWord32( hwnd, offset, newval );
1556 case GWL_WNDPROC:
1557 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1558 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1559 type, WIN_PROC_WINDOW );
1560 return retval;
1561 case GWL_STYLE:
1562 style.styleOld = wndPtr->dwStyle;
1563 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1564 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1566 if (wndPtr->flags & WIN_ISWIN32)
1567 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1568 wndPtr->dwStyle = style.styleNew;
1569 if (wndPtr->flags & WIN_ISWIN32)
1570 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1571 return style.styleOld;
1573 case GWL_USERDATA:
1574 ptr = &wndPtr->userdata;
1575 break;
1576 case GWL_EXSTYLE:
1577 style.styleOld = wndPtr->dwExStyle;
1578 style.styleNew = newval;
1579 if (wndPtr->flags & WIN_ISWIN32)
1580 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1581 wndPtr->dwExStyle = newval;
1582 if (wndPtr->flags & WIN_ISWIN32)
1583 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1584 return style.styleOld;
1586 default:
1587 WARN( win, "Invalid offset %d\n", offset );
1589 /* Don't think this is right error but it should do */
1590 SetLastError( ERROR_OUTOFMEMORY );
1592 return 0;
1594 retval = *ptr;
1595 *ptr = newval;
1596 return retval;
1600 /**********************************************************************
1601 * GetWindowLong16 (USER.135)
1603 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1605 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1609 /**********************************************************************
1610 * GetWindowLong32A (USER32.305)
1612 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1614 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1618 /**********************************************************************
1619 * GetWindowLong32W (USER32.306)
1621 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1623 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1627 /**********************************************************************
1628 * SetWindowLong16 (USER.136)
1630 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1632 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1636 /**********************************************************************
1637 * SetWindowLong32A (USER32.517)
1639 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1641 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1645 /**********************************************************************
1646 * SetWindowLong32W (USER32.518) Set window attribute
1648 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1649 * value in a window's extra memory.
1651 * The _hwnd_ parameter specifies the window. is the handle to a
1652 * window that has extra memory. The _newval_ parameter contains the
1653 * new attribute or extra memory value. If positive, the _offset_
1654 * parameter is the byte-addressed location in the window's extra
1655 * memory to set. If negative, _offset_ specifies the window
1656 * attribute to set, and should be one of the following values:
1658 * GWL_EXSTYLE The window's extended window style
1660 * GWL_STYLE The window's window style.
1662 * GWL_WNDPROC Pointer to the window's window procedure.
1664 * GWL_HINSTANCE The window's pplication instance handle.
1666 * GWL_ID The window's identifier.
1668 * GWL_USERDATA The window's user-specified data.
1670 * If the window is a dialog box, the _offset_ parameter can be one of
1671 * the following values:
1673 * DWL_DLGPROC The address of the window's dialog box procedure.
1675 * DWL_MSGRESULT The return value of a message
1676 * that the dialog box procedure processed.
1678 * DWL_USER Application specific information.
1680 * RETURNS
1682 * If successful, returns the previous value located at _offset_. Otherwise,
1683 * returns 0.
1685 * NOTES
1687 * Extra memory for a window class is specified by a nonzero cbWndExtra
1688 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1689 * time of class creation.
1691 * Using GWL_WNDPROC to set a new window procedure effectively creates
1692 * a window subclass. Use CallWindowProc() in the new windows procedure
1693 * to pass messages to the superclass's window procedure.
1695 * The user data is reserved for use by the application which created
1696 * the window.
1698 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1699 * instead, call the EnableWindow() function to change the window's
1700 * disabled state.
1702 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1703 * SetParent() instead.
1705 * BUGS
1707 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1709 * CONFORMANCE
1711 * ECMA-234, Win32
1714 LONG WINAPI SetWindowLong32W(
1715 HWND32 hwnd, /* window to alter */
1716 INT32 offset, /* offset, in bytes, of location to alter */
1717 LONG newval /* new value of location */
1719 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1723 /*******************************************************************
1724 * GetWindowText16 (USER.36)
1726 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1728 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1732 /*******************************************************************
1733 * GetWindowText32A (USER32.309)
1735 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1737 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1738 (LPARAM)lpString );
1741 /*******************************************************************
1742 * InternalGetWindowText (USER32.326)
1744 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1746 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1747 return GetWindowText32W(hwnd,lpString,nMaxCount);
1751 /*******************************************************************
1752 * GetWindowText32W (USER32.312)
1754 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1756 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1757 (LPARAM)lpString );
1761 /*******************************************************************
1762 * SetWindowText16 (USER.37)
1764 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1766 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1770 /*******************************************************************
1771 * SetWindowText32A (USER32.521)
1773 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1775 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1779 /*******************************************************************
1780 * SetWindowText32W (USER32.523)
1782 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1784 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1788 /*******************************************************************
1789 * GetWindowTextLength16 (USER.38)
1791 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1793 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1797 /*******************************************************************
1798 * GetWindowTextLength32A (USER32.310)
1800 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1802 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1805 /*******************************************************************
1806 * GetWindowTextLength32W (USER32.311)
1808 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1810 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1814 /*******************************************************************
1815 * IsWindow16 (USER.47)
1817 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1819 return IsWindow32( hwnd );
1822 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1824 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1825 HWND16 hwnd = (HWND16)stack[2];
1827 AX_reg(context) = IsWindow32( hwnd );
1828 ES_reg(context) = USER_HeapSel;
1832 /*******************************************************************
1833 * IsWindow32 (USER32.348)
1835 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1837 WND * wndPtr = WIN_FindWndPtr( hwnd );
1838 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1842 /*****************************************************************
1843 * GetParent16 (USER.46)
1845 HWND16 WINAPI GetParent16( HWND16 hwnd )
1847 return (HWND16)GetParent32( hwnd );
1851 /*****************************************************************
1852 * GetParent32 (USER32.278)
1854 HWND32 WINAPI GetParent32( HWND32 hwnd )
1856 WND *wndPtr = WIN_FindWndPtr(hwnd);
1857 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1858 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1859 return wndPtr ? wndPtr->hwndSelf : 0;
1862 /*****************************************************************
1863 * WIN_GetTopParent
1865 * Get the top-level parent for a child window.
1867 WND* WIN_GetTopParentPtr( WND* pWnd )
1869 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1870 return pWnd;
1873 /*****************************************************************
1874 * WIN_GetTopParent
1876 * Get the top-level parent for a child window.
1878 HWND32 WIN_GetTopParent( HWND32 hwnd )
1880 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1881 return wndPtr ? wndPtr->hwndSelf : 0;
1885 /*****************************************************************
1886 * SetParent16 (USER.233)
1888 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1890 return SetParent32( hwndChild, hwndNewParent );
1894 /*****************************************************************
1895 * SetParent32 (USER32.495)
1897 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1899 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1900 WND *pWndNewParent =
1901 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1902 WND *pWndOldParent =
1903 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1905 return pWndOldParent?pWndOldParent->hwndSelf:0;
1908 /*******************************************************************
1909 * IsChild16 (USER.48)
1911 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1913 return IsChild32(parent,child);
1917 /*******************************************************************
1918 * IsChild32 (USER32.339)
1920 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1922 WND * wndPtr = WIN_FindWndPtr( child );
1923 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1925 wndPtr = wndPtr->parent;
1926 if (wndPtr->hwndSelf == parent) return TRUE;
1928 return FALSE;
1932 /***********************************************************************
1933 * IsWindowVisible16 (USER.49)
1935 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1937 return IsWindowVisible32(hwnd);
1941 /***********************************************************************
1942 * IsWindowVisible32 (USER32.351)
1944 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1946 WND *wndPtr = WIN_FindWndPtr( hwnd );
1947 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1949 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1950 wndPtr = wndPtr->parent;
1952 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1956 /***********************************************************************
1957 * WIN_IsWindowDrawable
1959 * hwnd is drawable when it is visible, all parents are not
1960 * minimized, and it is itself not minimized unless we are
1961 * trying to draw its default class icon.
1963 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1965 if( (wnd->dwStyle & WS_MINIMIZE &&
1966 icon && wnd->class->hIcon) ||
1967 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1968 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1969 if( wnd->dwStyle & WS_MINIMIZE ||
1970 !(wnd->dwStyle & WS_VISIBLE) ) break;
1971 return (wnd == NULL);
1975 /*******************************************************************
1976 * GetTopWindow16 (USER.229)
1978 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
1980 return GetTopWindow32(hwnd);
1984 /*******************************************************************
1985 * GetTopWindow32 (USER.229)
1987 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
1989 WND * wndPtr = WIN_FindWndPtr( hwnd );
1990 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1991 else return 0;
1995 /*******************************************************************
1996 * GetWindow16 (USER.262)
1998 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2000 return GetWindow32( hwnd,rel );
2004 /*******************************************************************
2005 * GetWindow32 (USER32.302)
2007 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2009 WND * wndPtr = WIN_FindWndPtr( hwnd );
2010 if (!wndPtr) return 0;
2011 switch(rel)
2013 case GW_HWNDFIRST:
2014 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2015 else return 0;
2017 case GW_HWNDLAST:
2018 if (!wndPtr->parent) return 0; /* Desktop window */
2019 while (wndPtr->next) wndPtr = wndPtr->next;
2020 return wndPtr->hwndSelf;
2022 case GW_HWNDNEXT:
2023 if (!wndPtr->next) return 0;
2024 return wndPtr->next->hwndSelf;
2026 case GW_HWNDPREV:
2027 if (!wndPtr->parent) return 0; /* Desktop window */
2028 wndPtr = wndPtr->parent->child; /* First sibling */
2029 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2030 while (wndPtr->next)
2032 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2033 wndPtr = wndPtr->next;
2035 return 0;
2037 case GW_OWNER:
2038 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2040 case GW_CHILD:
2041 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2043 return 0;
2047 /*******************************************************************
2048 * GetNextWindow16 (USER.230)
2050 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2052 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2053 return GetWindow16( hwnd, flag );
2056 /*******************************************************************
2057 * ShowOwnedPopups16 (USER.265)
2059 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2061 ShowOwnedPopups32( owner, fShow );
2065 /*******************************************************************
2066 * ShowOwnedPopups32 (USER32.531)
2068 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2070 WND *pWnd = pWndDesktop->child;
2071 while (pWnd)
2073 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2074 (pWnd->dwStyle & WS_POPUP))
2075 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2076 pWnd = pWnd->next;
2078 return TRUE;
2082 /*******************************************************************
2083 * GetLastActivePopup16 (USER.287)
2085 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2087 return GetLastActivePopup32( hwnd );
2090 /*******************************************************************
2091 * GetLastActivePopup32 (USER32.256)
2093 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2095 WND *wndPtr;
2096 wndPtr = WIN_FindWndPtr(hwnd);
2097 if (wndPtr == NULL) return hwnd;
2098 return wndPtr->hwndLastActive;
2102 /*******************************************************************
2103 * WIN_BuildWinArray
2105 * Build an array of pointers to the children of a given window.
2106 * The array must be freed with HeapFree(SystemHeap). Return NULL
2107 * when no windows are found.
2109 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2111 WND **list, **ppWnd;
2112 WND *pWnd;
2113 UINT32 count, skipOwned, skipHidden;
2114 DWORD skipFlags;
2116 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2117 skipOwned = bwaFlags & BWA_SKIPOWNED;
2118 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2119 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2121 /* First count the windows */
2123 if (!wndPtr) wndPtr = pWndDesktop;
2124 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2126 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2127 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2130 if( count )
2132 /* Now build the list of all windows */
2134 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2136 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2138 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2139 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2141 *ppWnd++ = pWnd;
2142 count++;
2145 *ppWnd = NULL;
2147 else count = 0;
2148 } else list = NULL;
2150 if( pTotal ) *pTotal = count;
2151 return list;
2155 /*******************************************************************
2156 * EnumWindows16 (USER.54)
2158 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2160 WND **list, **ppWnd;
2162 /* We have to build a list of all windows first, to avoid */
2163 /* unpleasant side-effects, for instance if the callback */
2164 /* function changes the Z-order of the windows. */
2166 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2168 /* Now call the callback function for every window */
2170 for (ppWnd = list; *ppWnd; ppWnd++)
2172 /* Make sure that the window still exists */
2173 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2174 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2176 HeapFree( SystemHeap, 0, list );
2177 return TRUE;
2181 /*******************************************************************
2182 * EnumWindows32 (USER32.193)
2184 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2186 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2190 /**********************************************************************
2191 * EnumTaskWindows16 (USER.225)
2193 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2194 LPARAM lParam )
2196 WND **list, **ppWnd;
2198 /* This function is the same as EnumWindows(), */
2199 /* except for an added check on the window's task. */
2201 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2203 /* Now call the callback function for every window */
2205 for (ppWnd = list; *ppWnd; ppWnd++)
2207 /* Make sure that the window still exists */
2208 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2209 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2210 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2212 HeapFree( SystemHeap, 0, list );
2213 return TRUE;
2217 /**********************************************************************
2218 * EnumThreadWindows (USER32.190)
2220 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2222 THDB *tdb = THREAD_ID_TO_THDB(id);
2224 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2228 /**********************************************************************
2229 * WIN_EnumChildWindows
2231 * Helper function for EnumChildWindows().
2233 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2234 LPARAM lParam )
2236 WND **childList;
2237 BOOL16 ret = FALSE;
2239 for ( ; *ppWnd; ppWnd++)
2241 /* Make sure that the window still exists */
2242 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2243 /* Build children list first */
2244 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2245 ret = func( (*ppWnd)->hwndSelf, lParam );
2246 if (childList)
2248 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2249 HeapFree( SystemHeap, 0, childList );
2251 if (!ret) return FALSE;
2253 return TRUE;
2257 /**********************************************************************
2258 * EnumChildWindows16 (USER.55)
2260 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2261 LPARAM lParam )
2263 WND **list, *pParent;
2265 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2266 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2267 WIN_EnumChildWindows( list, func, lParam );
2268 HeapFree( SystemHeap, 0, list );
2269 return TRUE;
2273 /**********************************************************************
2274 * EnumChildWindows32 (USER32.178)
2276 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2277 LPARAM lParam )
2279 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2280 lParam );
2284 /*******************************************************************
2285 * AnyPopup16 (USER.52)
2287 BOOL16 WINAPI AnyPopup16(void)
2289 return AnyPopup32();
2293 /*******************************************************************
2294 * AnyPopup32 (USER32.4)
2296 BOOL32 WINAPI AnyPopup32(void)
2298 WND *wndPtr;
2299 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2300 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2301 return FALSE;
2305 /*******************************************************************
2306 * FlashWindow16 (USER.105)
2308 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2310 return FlashWindow32( hWnd, bInvert );
2314 /*******************************************************************
2315 * FlashWindow32 (USER32.202)
2317 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2319 WND *wndPtr = WIN_FindWndPtr(hWnd);
2321 TRACE(win,"%04x\n", hWnd);
2323 if (!wndPtr) return FALSE;
2325 if (wndPtr->dwStyle & WS_MINIMIZE)
2327 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2329 HDC32 hDC = GetDC32(hWnd);
2331 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2332 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2334 ReleaseDC32( hWnd, hDC );
2335 wndPtr->flags |= WIN_NCACTIVATED;
2337 else
2339 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2340 RDW_UPDATENOW | RDW_FRAME, 0 );
2341 wndPtr->flags &= ~WIN_NCACTIVATED;
2343 return TRUE;
2345 else
2347 WPARAM16 wparam;
2348 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2349 else wparam = (hWnd == GetActiveWindow32());
2351 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2352 return wparam;
2357 /*******************************************************************
2358 * SetSysModalWindow16 (USER.188)
2360 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2362 HWND32 hWndOldModal = hwndSysModal;
2363 hwndSysModal = hWnd;
2364 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2365 return hWndOldModal;
2369 /*******************************************************************
2370 * GetSysModalWindow16 (USER.52)
2372 HWND16 WINAPI GetSysModalWindow16(void)
2374 return hwndSysModal;
2378 /*******************************************************************
2379 * GetWindowContextHelpId (USER32.303)
2381 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2383 WND *wnd = WIN_FindWndPtr( hwnd );
2384 if (!wnd) return 0;
2385 return wnd->helpContext;
2389 /*******************************************************************
2390 * SetWindowContextHelpId (USER32.515)
2392 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2394 WND *wnd = WIN_FindWndPtr( hwnd );
2395 if (!wnd) return FALSE;
2396 wnd->helpContext = id;
2397 return TRUE;
2401 /*******************************************************************
2402 * DRAG_QueryUpdate
2404 * recursively find a child that contains spDragInfo->pt point
2405 * and send WM_QUERYDROPOBJECT
2407 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2409 BOOL16 wParam,bResult = 0;
2410 POINT32 pt;
2411 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2412 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2413 RECT32 tempRect;
2415 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2417 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2419 GetWindowRect32(hQueryWnd,&tempRect);
2421 if( !PtInRect32(&tempRect,pt) ||
2422 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2423 return 0;
2425 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2427 tempRect = ptrQueryWnd->rectClient;
2428 if(ptrQueryWnd->dwStyle & WS_CHILD)
2429 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2430 (LPPOINT32)&tempRect, 2 );
2432 if (PtInRect32( &tempRect, pt))
2434 wParam = 0;
2436 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2437 if( ptrWnd->dwStyle & WS_VISIBLE )
2439 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2440 if (PtInRect32( &tempRect, pt )) break;
2443 if(ptrWnd)
2445 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2446 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2447 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2448 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2449 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2452 if(bResult) return bResult;
2454 else wParam = 1;
2456 else wParam = 1;
2458 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2460 ptrDragInfo->hScope = hQueryWnd;
2462 bResult = ( bNoSend )
2463 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2464 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2465 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2466 if( !bResult )
2467 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2469 return bResult;
2473 /*******************************************************************
2474 * DragDetect (USER.465)
2476 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2478 POINT32 pt32;
2479 CONV_POINT16TO32( &pt, &pt32 );
2480 return DragDetect32( hWnd, pt32 );
2483 /*******************************************************************
2484 * DragDetect32 (USER32.151)
2486 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2488 MSG16 msg;
2489 RECT16 rect;
2491 rect.left = pt.x - wDragWidth;
2492 rect.right = pt.x + wDragWidth;
2494 rect.top = pt.y - wDragHeight;
2495 rect.bottom = pt.y + wDragHeight;
2497 SetCapture32(hWnd);
2499 while(1)
2501 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2503 if( msg.message == WM_LBUTTONUP )
2505 ReleaseCapture();
2506 return 0;
2508 if( msg.message == WM_MOUSEMOVE )
2510 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2512 ReleaseCapture();
2513 return 1;
2517 WaitMessage();
2519 return 0;
2522 /******************************************************************************
2523 * DragObject16 (USER.464)
2525 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2526 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2528 MSG16 msg;
2529 LPDRAGINFO lpDragInfo;
2530 SEGPTR spDragInfo;
2531 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2532 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2533 WND *wndPtr = WIN_FindWndPtr(hWnd);
2534 HCURSOR16 hCurrentCursor = 0;
2535 HWND16 hCurrentWnd = 0;
2537 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2538 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2540 if( !lpDragInfo || !spDragInfo ) return 0L;
2542 hBummer = LoadCursor16(0, IDC_BUMMER16);
2544 if( !hBummer || !wndPtr )
2546 GlobalFree16(hDragInfo);
2547 return 0L;
2550 if(hCursor)
2552 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2554 GlobalFree16(hDragInfo);
2555 return 0L;
2558 if( hDragCursor == hCursor ) hDragCursor = 0;
2559 else hCursor = hDragCursor;
2561 hOldCursor = SetCursor32(hDragCursor);
2564 lpDragInfo->hWnd = hWnd;
2565 lpDragInfo->hScope = 0;
2566 lpDragInfo->wFlags = wObj;
2567 lpDragInfo->hList = szList; /* near pointer! */
2568 lpDragInfo->hOfStruct = hOfStruct;
2569 lpDragInfo->l = 0L;
2571 SetCapture32(hWnd);
2572 ShowCursor32( TRUE );
2576 do{ WaitMessage(); }
2577 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2579 *(lpDragInfo+1) = *lpDragInfo;
2581 lpDragInfo->pt = msg.pt;
2583 /* update DRAGINFO struct */
2584 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2586 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2587 hCurrentCursor = hCursor;
2588 else
2590 hCurrentCursor = hBummer;
2591 lpDragInfo->hScope = 0;
2593 if( hCurrentCursor )
2594 SetCursor32(hCurrentCursor);
2596 /* send WM_DRAGLOOP */
2597 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2598 (LPARAM) spDragInfo );
2599 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2600 if( hCurrentWnd != lpDragInfo->hScope )
2602 if( hCurrentWnd )
2603 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2604 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2605 HIWORD(spDragInfo)) );
2606 hCurrentWnd = lpDragInfo->hScope;
2607 if( hCurrentWnd )
2608 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2610 else
2611 if( hCurrentWnd )
2612 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2614 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2616 ReleaseCapture();
2617 ShowCursor32( FALSE );
2619 if( hCursor )
2621 SetCursor32( hOldCursor );
2622 if (hDragCursor) DestroyCursor32( hDragCursor );
2625 if( hCurrentCursor != hBummer )
2626 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2627 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2628 else
2629 msg.lParam = 0;
2630 GlobalFree16(hDragInfo);
2632 return (DWORD)(msg.lParam);