Authors: Adrian Thurston <adriant@corel.ca>, Zygo Blaxell <zblaxell@corel.ca>
[wine/multimedia.git] / windows / win.c
blob2f50efc89c8270db708298769efba458ba3d118a
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "sysmetrics.h"
18 #include "cursoricon.h"
19 #include "heap.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "shm_main_blk.h"
27 #include "dde_proc.h"
28 #include "clipboard.h"
29 #include "winproc.h"
30 #include "task.h"
31 #include "thread.h"
32 #include "process.h"
33 #include "debug.h"
34 #include "winerror.h"
35 #include "mdi.h"
36 #include "local.h"
37 #include "desktop.h"
39 #ifndef X_DISPLAY_MISSING
40 extern DESKTOP_DRIVER X11DRV_DESKTOP_Driver;
41 extern WND_DRIVER X11DRV_WND_Driver;
42 #else /* X_DISPLAY_MISSING */
43 extern DESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
44 extern WND_DRIVER TTYDRV_WND_Driver;
45 #endif /* X_DISPLAY_MISSING */
47 /* Desktop window */
48 static WND *pWndDesktop = NULL;
50 static HWND32 hwndSysModal = 0;
52 static WORD wDragWidth = 4;
53 static WORD wDragHeight= 3;
55 /***********************************************************************
56 * WIN_FindWndPtr
58 * Return a pointer to the WND structure corresponding to a HWND.
60 WND * WIN_FindWndPtr( HWND32 hwnd )
62 WND * ptr;
64 if (!hwnd || HIWORD(hwnd)) return NULL;
65 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
66 if (ptr->dwMagic != WND_MAGIC) return NULL;
67 if (ptr->hwndSelf != hwnd)
69 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
70 hwnd, ptr->hwndSelf );
71 return NULL;
73 return ptr;
77 /***********************************************************************
78 * WIN_DumpWindow
80 * Dump the content of a window structure to stderr.
82 void WIN_DumpWindow( HWND32 hwnd )
84 WND *ptr;
85 char className[80];
86 int i;
88 if (!(ptr = WIN_FindWndPtr( hwnd )))
90 WARN( win, "%04x is not a window handle\n", hwnd );
91 return;
94 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
95 strcpy( className, "#NULL#" );
97 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
98 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
99 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
100 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
101 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
102 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
103 ptr->next, ptr->child, ptr->parent, ptr->owner,
104 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
105 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
106 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
107 ptr->text ? ptr->text : "",
108 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
109 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
110 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
111 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
113 if (ptr->class->cbWndExtra)
115 DUMP( "extra bytes:" );
116 for (i = 0; i < ptr->class->cbWndExtra; i++)
117 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
118 DUMP( "\n" );
120 DUMP( "\n" );
124 /***********************************************************************
125 * WIN_WalkWindows
127 * Walk the windows tree and print each window on stderr.
129 void WIN_WalkWindows( HWND32 hwnd, int indent )
131 WND *ptr;
132 char className[80];
134 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
135 if (!ptr)
137 WARN( win, "Invalid window handle %04x\n", hwnd );
138 return;
141 if (!indent) /* first time around */
142 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
143 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
144 " Text");
146 while (ptr)
148 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
150 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
152 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
153 (DWORD)ptr, ptr->hmemTaskQ, className,
154 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
155 ptr->text?ptr->text:"<null>");
157 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
158 ptr = ptr->next;
162 /***********************************************************************
163 * WIN_UnlinkWindow
165 * Remove a window from the siblings linked list.
167 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
169 WND *wndPtr, **ppWnd;
171 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
172 ppWnd = &wndPtr->parent->child;
173 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
174 *ppWnd = wndPtr->next;
175 return TRUE;
179 /***********************************************************************
180 * WIN_LinkWindow
182 * Insert a window into the siblings linked list.
183 * The window is inserted after the specified window, which can also
184 * be specified as HWND_TOP or HWND_BOTTOM.
186 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
188 WND *wndPtr, **ppWnd;
190 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
192 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
194 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
195 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
196 while (*ppWnd) ppWnd = &(*ppWnd)->next;
198 else /* Normal case */
200 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
201 if (!afterPtr) return FALSE;
202 ppWnd = &afterPtr->next;
204 wndPtr->next = *ppWnd;
205 *ppWnd = wndPtr;
206 return TRUE;
210 /***********************************************************************
211 * WIN_FindWinToRepaint
213 * Find a window that needs repaint.
215 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
217 HWND32 hwndRet;
218 WND *pWnd = pWndDesktop;
220 /* Note: the desktop window never gets WM_PAINT messages
221 * The real reason why is because Windows DesktopWndProc
222 * does ValidateRgn inside WM_ERASEBKGND handler.
225 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
227 for ( ; pWnd ; pWnd = pWnd->next )
229 if (!(pWnd->dwStyle & WS_VISIBLE))
231 TRACE(win, "skipping window %04x\n",
232 pWnd->hwndSelf );
233 continue;
235 if ((pWnd->hmemTaskQ == hQueue) &&
236 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
238 if (pWnd->child )
239 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
240 return hwndRet;
243 if (!pWnd) return 0;
245 hwndRet = pWnd->hwndSelf;
247 /* look among siblings if we got a transparent window */
248 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
249 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
251 pWnd = pWnd->next;
253 if (pWnd) hwndRet = pWnd->hwndSelf;
254 TRACE(win,"found %04x\n",hwndRet);
255 return hwndRet;
259 /***********************************************************************
260 * WIN_DestroyWindow
262 * Destroy storage associated to a window. "Internals" p.358
264 static WND* WIN_DestroyWindow( WND* wndPtr )
266 HWND32 hwnd = wndPtr->hwndSelf;
267 WND *pWnd;
269 TRACE(win, "%04x\n", wndPtr->hwndSelf );
271 #ifdef CONFIG_IPC
272 if (main_block)
273 DDE_DestroyWindow(wndPtr->hwndSelf);
274 #endif /* CONFIG_IPC */
276 /* free child windows */
278 while ((pWnd = wndPtr->child))
279 wndPtr->child = WIN_DestroyWindow( pWnd );
281 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
283 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
285 WINPOS_CheckInternalPos( wndPtr );
286 if( hwnd == GetCapture32()) ReleaseCapture();
288 /* free resources associated with the window */
290 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
291 PROPERTY_RemoveWindowProps( wndPtr );
293 wndPtr->dwMagic = 0; /* Mark it as invalid */
295 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
297 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
298 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
301 /* toss stale messages from the queue */
303 if( wndPtr->hmemTaskQ )
305 BOOL32 bPostQuit = FALSE;
306 WPARAM32 wQuitParam = 0;
307 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
308 QMSG *qmsg;
310 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
312 if( qmsg->msg.message == WM_QUIT )
314 bPostQuit = TRUE;
315 wQuitParam = qmsg->msg.wParam;
317 QUEUE_RemoveMsg(msgQ, qmsg);
320 QUEUE_Unlock(msgQ);
322 /* repost WM_QUIT to make sure this app exits its message loop */
323 if( bPostQuit ) PostQuitMessage32(wQuitParam);
324 wndPtr->hmemTaskQ = 0;
327 if (!(wndPtr->dwStyle & WS_CHILD))
328 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
329 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
330 wndPtr->pDriver->pDestroyWindow( wndPtr );
331 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
332 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
333 wndPtr->hwndSelf = 0;
334 wndPtr->class->cWindows--;
335 wndPtr->class = NULL;
336 pWnd = wndPtr->next;
338 wndPtr->pDriver->pFinalize(wndPtr);
339 USER_HEAP_FREE( hwnd );
340 return pWnd;
343 /***********************************************************************
344 * WIN_ResetQueueWindows
346 * Reset the queue of all the children of a given window.
347 * Return TRUE if something was done.
349 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
351 BOOL32 ret = FALSE;
353 if (hNew) /* Set a new queue */
355 for (wnd = wnd->child; (wnd); wnd = wnd->next)
357 if (wnd->hmemTaskQ == hQueue)
359 wnd->hmemTaskQ = hNew;
360 ret = TRUE;
362 if (wnd->child)
363 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
366 else /* Queue is being destroyed */
368 while (wnd->child)
370 WND *tmp = wnd->child;
371 ret = FALSE;
372 while (tmp)
374 if (tmp->hmemTaskQ == hQueue)
376 DestroyWindow32( tmp->hwndSelf );
377 ret = TRUE;
378 break;
380 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
381 ret = TRUE;
382 else
383 tmp = tmp->next;
385 if (!ret) break;
388 return ret;
391 /***********************************************************************
392 * WIN_CreateDesktopWindow
394 * Create the desktop window.
396 BOOL32 WIN_CreateDesktopWindow(void)
398 CLASS *class;
399 HWND32 hwndDesktop;
400 DESKTOP *pDesktop;
402 TRACE(win,"Creating desktop window\n");
404 if (!ICONTITLE_Init() ||
405 !WINPOS_CreateInternalPosAtom() ||
406 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
407 return FALSE;
409 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
410 if (!hwndDesktop) return FALSE;
411 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
413 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
414 #ifndef X_DISPLAY_MISSING
415 pDesktop->pDriver = &X11DRV_DESKTOP_Driver;
416 pWndDesktop->pDriver = &X11DRV_WND_Driver;
417 #else /* X_DISPLAY_MISSING */
418 pDesktop->pDriver = &TTYDRV_DESKTOP_Driver;
419 pWndDesktop->pDriver = &TTYDRV_WND_Driver;
420 #endif /* X_DISPLAY_MISSING */
422 pDesktop->pDriver->pInitialize(pDesktop);
423 pWndDesktop->pDriver->pInitialize(pWndDesktop);
425 pWndDesktop->next = NULL;
426 pWndDesktop->child = NULL;
427 pWndDesktop->parent = NULL;
428 pWndDesktop->owner = NULL;
429 pWndDesktop->class = class;
430 pWndDesktop->dwMagic = WND_MAGIC;
431 pWndDesktop->hwndSelf = hwndDesktop;
432 pWndDesktop->hInstance = 0;
433 pWndDesktop->rectWindow.left = 0;
434 pWndDesktop->rectWindow.top = 0;
435 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
436 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
437 pWndDesktop->rectClient = pWndDesktop->rectWindow;
438 pWndDesktop->text = NULL;
439 pWndDesktop->hmemTaskQ = GetFastQueue();
440 pWndDesktop->hrgnUpdate = 0;
441 pWndDesktop->hwndLastActive = hwndDesktop;
442 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
443 WS_CLIPSIBLINGS;
444 pWndDesktop->dwExStyle = 0;
445 pWndDesktop->dce = NULL;
446 pWndDesktop->pVScroll = NULL;
447 pWndDesktop->pHScroll = NULL;
448 pWndDesktop->pProp = NULL;
449 pWndDesktop->wIDmenu = 0;
450 pWndDesktop->helpContext = 0;
451 pWndDesktop->flags = 0;
452 pWndDesktop->hSysMenu = 0;
453 pWndDesktop->userdata = 0;
454 pWndDesktop->winproc = (WNDPROC16)class->winproc;
456 /* FIXME: How do we know if it should be Unicode or not */
457 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
458 return FALSE;
460 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
461 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
462 return TRUE;
466 /***********************************************************************
467 * WIN_CreateWindowEx
469 * Implementation of CreateWindowEx().
471 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
472 BOOL32 win32, BOOL32 unicode )
474 CLASS *classPtr;
475 WND *wndPtr;
476 HWND16 hwnd, hwndLinkAfter;
477 POINT32 maxSize, maxPos, minTrack, maxTrack;
478 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
480 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
481 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
482 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
483 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
484 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
486 /* Find the parent window */
488 if (cs->hwndParent)
490 /* Make sure parent is valid */
491 if (!IsWindow32( cs->hwndParent ))
493 WARN( win, "Bad parent %04x\n", cs->hwndParent );
494 return 0;
496 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
497 WARN( win, "No parent for child window\n" );
498 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
501 /* Find the window class */
502 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
504 char buffer[256];
505 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
506 WARN( win, "Bad class '%s'\n", buffer );
507 return 0;
510 /* Fix the coordinates */
512 if (cs->x == CW_USEDEFAULT32)
514 PDB32 *pdb = PROCESS_Current();
515 if ( !(cs->style & (WS_CHILD | WS_POPUP))
516 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
518 cs->x = pdb->env_db->startup_info->dwX;
519 cs->y = pdb->env_db->startup_info->dwY;
521 else
523 cs->x = 0;
524 cs->y = 0;
527 if (cs->cx == CW_USEDEFAULT32)
529 PDB32 *pdb = PROCESS_Current();
530 if ( !(cs->style & (WS_CHILD | WS_POPUP))
531 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
533 cs->cx = pdb->env_db->startup_info->dwXSize;
534 cs->cy = pdb->env_db->startup_info->dwYSize;
536 else
538 cs->cx = 600; /* FIXME */
539 cs->cy = 400;
543 /* Create the window structure */
545 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
546 - sizeof(wndPtr->wExtra) )))
548 TRACE(win, "out of memory\n" );
549 return 0;
552 /* Fill the window structure */
554 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
555 wndPtr->next = NULL;
556 wndPtr->child = NULL;
558 if ((cs->style & WS_CHILD) && cs->hwndParent)
560 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
561 wndPtr->owner = NULL;
563 else
565 wndPtr->parent = pWndDesktop;
566 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
567 wndPtr->owner = NULL;
568 else
569 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
572 wndPtr->pDriver = wndPtr->parent->pDriver;
573 wndPtr->pDriver->pInitialize(wndPtr);
575 wndPtr->class = classPtr;
576 wndPtr->winproc = classPtr->winproc;
577 wndPtr->dwMagic = WND_MAGIC;
578 wndPtr->hwndSelf = hwnd;
579 wndPtr->hInstance = cs->hInstance;
580 wndPtr->text = NULL;
581 wndPtr->hmemTaskQ = GetFastQueue();
582 wndPtr->hrgnUpdate = 0;
583 wndPtr->hwndLastActive = hwnd;
584 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
585 wndPtr->dwExStyle = cs->dwExStyle;
586 wndPtr->wIDmenu = 0;
587 wndPtr->helpContext = 0;
588 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
589 wndPtr->pVScroll = NULL;
590 wndPtr->pHScroll = NULL;
591 wndPtr->pProp = NULL;
592 wndPtr->userdata = 0;
593 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
594 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
596 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
598 /* Call the WH_CBT hook */
600 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
601 ? HWND_BOTTOM : HWND_TOP;
603 if (HOOK_IsHooked( WH_CBT ))
605 CBT_CREATEWND32A cbtc;
606 LRESULT ret;
608 cbtc.lpcs = cs;
609 cbtc.hwndInsertAfter = hwndLinkAfter;
610 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
611 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
612 if (ret)
614 TRACE(win, "CBT-hook returned 0\n");
615 wndPtr->pDriver->pFinalize(wndPtr);
616 USER_HEAP_FREE( hwnd );
617 return 0;
621 /* Increment class window counter */
623 classPtr->cWindows++;
625 /* Correct the window style */
627 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
629 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
630 wndPtr->flags |= WIN_NEED_SIZE;
632 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
634 /* Get class or window DC if needed */
636 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
637 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
638 else wndPtr->dce = NULL;
640 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
642 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
644 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
645 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
646 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
647 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
648 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
651 if(cs->style & WS_CHILD)
653 if(cs->cx < 0) cs->cx = 0;
654 if(cs->cy < 0) cs->cy = 0;
656 else
658 if (cs->cx <= 0) cs->cx = 1;
659 if (cs->cy <= 0) cs->cy = 1;
662 wndPtr->rectWindow.left = cs->x;
663 wndPtr->rectWindow.top = cs->y;
664 wndPtr->rectWindow.right = cs->x + cs->cx;
665 wndPtr->rectWindow.bottom = cs->y + cs->cy;
666 wndPtr->rectClient = wndPtr->rectWindow;
668 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
669 return FALSE;
671 /* Set the window menu */
673 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
675 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
676 else
678 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
679 if (classPtr->menuNameA)
680 cs->hMenu = HIWORD(classPtr->menuNameA) ?
681 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
682 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
683 #else
684 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
685 if (menuName)
687 if (HIWORD(cs->hInstance))
688 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
689 else
690 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
692 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
694 #endif
697 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
699 /* Send the WM_CREATE message
700 * Perhaps we shouldn't allow width/height changes as well.
701 * See p327 in "Internals".
704 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
706 localSend32 = unicode ? SendMessage32W : SendMessage32A;
707 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
709 /* Insert the window in the linked list */
711 WIN_LinkWindow( hwnd, hwndLinkAfter );
713 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
714 NULL, NULL, 0, &wndPtr->rectClient );
715 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
716 maxPos.y - wndPtr->rectWindow.top);
717 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
719 /* Send the size messages */
721 if (!(wndPtr->flags & WIN_NEED_SIZE))
723 /* send it anyway */
724 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
725 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
726 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
727 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
728 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
729 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
730 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
731 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
732 SendMessage32A( hwnd, WM_MOVE, 0,
733 MAKELONG( wndPtr->rectClient.left,
734 wndPtr->rectClient.top ) );
737 /* Show the window, maximizing or minimizing if needed */
739 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
741 RECT16 newPos;
742 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
743 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
744 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
745 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32())
746 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
747 : SWP_NOZORDER | SWP_FRAMECHANGED;
748 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
749 newPos.right, newPos.bottom, swFlag );
752 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
754 /* Notify the parent window only */
756 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
757 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
758 if( !IsWindow32(hwnd) ) return 0;
761 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
763 /* Call WH_SHELL hook */
765 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
766 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
768 TRACE(win, "created window %04x\n", hwnd);
769 return hwnd;
771 WIN_UnlinkWindow( hwnd );
774 /* Abort window creation */
776 WARN(win, "aborted by WM_xxCREATE!\n");
777 WIN_DestroyWindow( wndPtr );
778 return 0;
782 /***********************************************************************
783 * CreateWindow16 (USER.41)
785 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
786 DWORD style, INT16 x, INT16 y, INT16 width,
787 INT16 height, HWND16 parent, HMENU16 menu,
788 HINSTANCE16 instance, LPVOID data )
790 return CreateWindowEx16( 0, className, windowName, style,
791 x, y, width, height, parent, menu, instance, data );
795 /***********************************************************************
796 * CreateWindowEx16 (USER.452)
798 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
799 LPCSTR windowName, DWORD style, INT16 x,
800 INT16 y, INT16 width, INT16 height,
801 HWND16 parent, HMENU16 menu,
802 HINSTANCE16 instance, LPVOID data )
804 ATOM classAtom;
805 CREATESTRUCT32A cs;
807 /* Find the class atom */
809 if (!(classAtom = GlobalFindAtom32A( className )))
811 fprintf( stderr, "CreateWindowEx16: bad class name " );
812 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
813 else fprintf( stderr, "'%s'\n", className );
814 return 0;
817 /* Fix the coordinates */
819 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
820 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
821 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
822 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
824 /* Create the window */
826 cs.lpCreateParams = data;
827 cs.hInstance = (HINSTANCE32)instance;
828 cs.hMenu = (HMENU32)menu;
829 cs.hwndParent = (HWND32)parent;
830 cs.style = style;
831 cs.lpszName = windowName;
832 cs.lpszClass = className;
833 cs.dwExStyle = exStyle;
834 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
838 /***********************************************************************
839 * CreateWindowEx32A (USER32.83)
841 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
842 LPCSTR windowName, DWORD style, INT32 x,
843 INT32 y, INT32 width, INT32 height,
844 HWND32 parent, HMENU32 menu,
845 HINSTANCE32 instance, LPVOID data )
847 ATOM classAtom;
848 CREATESTRUCT32A cs;
850 if(exStyle & WS_EX_MDICHILD)
851 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
852 /* Find the class atom */
854 if (!(classAtom = GlobalFindAtom32A( className )))
856 fprintf( stderr, "CreateWindowEx32A: bad class name " );
857 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
858 else fprintf( stderr, "'%s'\n", className );
859 return 0;
862 /* Create the window */
864 cs.lpCreateParams = data;
865 cs.hInstance = instance;
866 cs.hMenu = menu;
867 cs.hwndParent = parent;
868 cs.x = x;
869 cs.y = y;
870 cs.cx = width;
871 cs.cy = height;
872 cs.style = style;
873 cs.lpszName = windowName;
874 cs.lpszClass = className;
875 cs.dwExStyle = exStyle;
876 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
880 /***********************************************************************
881 * CreateWindowEx32W (USER32.84)
883 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
884 LPCWSTR windowName, DWORD style, INT32 x,
885 INT32 y, INT32 width, INT32 height,
886 HWND32 parent, HMENU32 menu,
887 HINSTANCE32 instance, LPVOID data )
889 ATOM classAtom;
890 CREATESTRUCT32W cs;
892 if(exStyle & WS_EX_MDICHILD)
893 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
895 /* Find the class atom */
897 if (!(classAtom = GlobalFindAtom32W( className )))
899 if (HIWORD(className))
901 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
902 WARN( win, "Bad class name '%s'\n",cn);
903 HeapFree( GetProcessHeap(), 0, cn );
905 else
906 WARN( win, "Bad class name %p\n", className );
907 return 0;
910 /* Create the window */
912 cs.lpCreateParams = data;
913 cs.hInstance = instance;
914 cs.hMenu = menu;
915 cs.hwndParent = parent;
916 cs.x = x;
917 cs.y = y;
918 cs.cx = width;
919 cs.cy = height;
920 cs.style = style;
921 cs.lpszName = windowName;
922 cs.lpszClass = className;
923 cs.dwExStyle = exStyle;
924 /* Note: we rely on the fact that CREATESTRUCT32A and */
925 /* CREATESTRUCT32W have the same layout. */
926 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
930 /***********************************************************************
931 * WIN_CheckFocus
933 static void WIN_CheckFocus( WND* pWnd )
935 if( GetFocus16() == pWnd->hwndSelf )
936 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
939 /***********************************************************************
940 * WIN_SendDestroyMsg
942 static void WIN_SendDestroyMsg( WND* pWnd )
944 WIN_CheckFocus(pWnd);
946 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
947 CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
949 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
951 if( IsWindow32(pWnd->hwndSelf) )
953 WND* pChild = pWnd->child;
954 while( pChild )
956 WIN_SendDestroyMsg( pChild );
957 pChild = pChild->next;
959 WIN_CheckFocus(pWnd);
961 else
962 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
966 /***********************************************************************
967 * DestroyWindow16 (USER.53)
969 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
971 return DestroyWindow32(hwnd);
975 /***********************************************************************
976 * DestroyWindow32 (USER32.135)
978 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
980 WND * wndPtr;
982 TRACE(win, "(%04x)\n", hwnd);
984 /* Initialization */
986 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
987 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
989 /* Call hooks */
991 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
992 return FALSE;
994 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
996 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
997 /* FIXME: clean up palette - see "Internals" p.352 */
1000 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1001 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1003 /* Notify the parent window only */
1004 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1005 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1006 if( !IsWindow32(hwnd) ) return TRUE;
1009 CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1011 /* Hide the window */
1013 if (wndPtr->dwStyle & WS_VISIBLE)
1015 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1016 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1017 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1018 if (!IsWindow32(hwnd)) return TRUE;
1021 /* Recursively destroy owned windows */
1023 if( !(wndPtr->dwStyle & WS_CHILD) )
1025 /* make sure top menu popup doesn't get destroyed */
1026 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1028 for (;;)
1030 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1031 while (siblingPtr)
1033 if (siblingPtr->owner == wndPtr)
1035 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1036 break;
1037 else
1038 siblingPtr->owner = NULL;
1040 siblingPtr = siblingPtr->next;
1042 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1043 else break;
1046 if( !Options.managed || EVENT_CheckFocus() )
1047 WINPOS_ActivateOtherWindow(wndPtr);
1049 if( wndPtr->owner &&
1050 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1051 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1054 /* Send destroy messages */
1056 WIN_SendDestroyMsg( wndPtr );
1057 if (!IsWindow32(hwnd)) return TRUE;
1059 /* Unlink now so we won't bother with the children later on */
1061 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1063 /* Destroy the window storage */
1065 WIN_DestroyWindow( wndPtr );
1066 return TRUE;
1070 /***********************************************************************
1071 * CloseWindow16 (USER.43)
1073 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1075 return CloseWindow32( hwnd );
1079 /***********************************************************************
1080 * CloseWindow32 (USER32.56)
1082 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1084 WND * wndPtr = WIN_FindWndPtr( hwnd );
1085 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1086 ShowWindow32( hwnd, SW_MINIMIZE );
1087 return TRUE;
1091 /***********************************************************************
1092 * OpenIcon16 (USER.44)
1094 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1096 return OpenIcon32( hwnd );
1100 /***********************************************************************
1101 * OpenIcon32 (USER32.410)
1103 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1105 if (!IsIconic32( hwnd )) return FALSE;
1106 ShowWindow32( hwnd, SW_SHOWNORMAL );
1107 return TRUE;
1111 /***********************************************************************
1112 * WIN_FindWindow
1114 * Implementation of FindWindow() and FindWindowEx().
1116 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1117 LPCSTR title )
1119 WND *pWnd;
1120 CLASS *pClass = NULL;
1122 if (child)
1124 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1125 if (parent)
1127 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1129 else if (pWnd->parent != pWndDesktop) return 0;
1130 pWnd = pWnd->next;
1132 else
1134 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1135 pWnd = pWnd->child;
1137 if (!pWnd) return 0;
1139 /* For a child window, all siblings will have the same hInstance, */
1140 /* so we can look for the class once and for all. */
1142 if (className && (pWnd->dwStyle & WS_CHILD))
1144 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1145 return 0;
1149 for ( ; pWnd; pWnd = pWnd->next)
1151 if (className && !(pWnd->dwStyle & WS_CHILD))
1153 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1154 continue; /* Skip this window */
1157 if (pClass && (pWnd->class != pClass))
1158 continue; /* Not the right class */
1160 /* Now check the title */
1162 if (!title) return pWnd->hwndSelf;
1163 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1165 return 0;
1170 /***********************************************************************
1171 * FindWindow16 (USER.50)
1173 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1175 return FindWindowEx16( 0, 0, className, title );
1179 /***********************************************************************
1180 * FindWindowEx16 (USER.427)
1182 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1183 SEGPTR className, LPCSTR title )
1185 ATOM atom = 0;
1187 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1188 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1189 title ? title : "");
1191 if (className)
1193 /* If the atom doesn't exist, then no class */
1194 /* with this name exists either. */
1195 if (!(atom = GlobalFindAtom16( className ))) return 0;
1197 return WIN_FindWindow( parent, child, atom, title );
1201 /***********************************************************************
1202 * FindWindow32A (USER32.198)
1204 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1206 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1207 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1208 return ret;
1212 /***********************************************************************
1213 * FindWindowEx32A (USER32.199)
1215 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1216 LPCSTR className, LPCSTR title )
1218 ATOM atom = 0;
1220 if (className)
1222 /* If the atom doesn't exist, then no class */
1223 /* with this name exists either. */
1224 if (!(atom = GlobalFindAtom32A( className )))
1226 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1227 return 0;
1230 return WIN_FindWindow( parent, child, atom, title );
1234 /***********************************************************************
1235 * FindWindowEx32W (USER32.200)
1237 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1238 LPCWSTR className, LPCWSTR title )
1240 ATOM atom = 0;
1241 char *buffer;
1242 HWND32 hwnd;
1244 if (className)
1246 /* If the atom doesn't exist, then no class */
1247 /* with this name exists either. */
1248 if (!(atom = GlobalFindAtom32W( className )))
1250 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1251 return 0;
1254 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1255 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1256 HeapFree( GetProcessHeap(), 0, buffer );
1257 return hwnd;
1261 /***********************************************************************
1262 * FindWindow32W (USER32.201)
1264 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1266 return FindWindowEx32W( 0, 0, className, title );
1270 /**********************************************************************
1271 * WIN_GetDesktop
1273 WND *WIN_GetDesktop(void)
1275 return pWndDesktop;
1279 /**********************************************************************
1280 * GetDesktopWindow16 (USER.286)
1282 HWND16 WINAPI GetDesktopWindow16(void)
1284 return (HWND16)pWndDesktop->hwndSelf;
1288 /**********************************************************************
1289 * GetDesktopWindow32 (USER32.232)
1291 HWND32 WINAPI GetDesktopWindow32(void)
1293 return pWndDesktop->hwndSelf;
1297 /**********************************************************************
1298 * GetDesktopHwnd (USER.278)
1300 * Exactly the same thing as GetDesktopWindow(), but not documented.
1301 * Don't ask me why...
1303 HWND16 WINAPI GetDesktopHwnd(void)
1305 return (HWND16)pWndDesktop->hwndSelf;
1309 /*******************************************************************
1310 * EnableWindow16 (USER.34)
1312 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1314 return EnableWindow32( hwnd, enable );
1318 /*******************************************************************
1319 * EnableWindow32 (USER32.172)
1321 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1323 WND *wndPtr;
1325 TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1327 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1328 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1330 /* Enable window */
1331 wndPtr->dwStyle &= ~WS_DISABLED;
1332 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1333 return TRUE;
1335 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1337 /* Disable window */
1338 wndPtr->dwStyle |= WS_DISABLED;
1339 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1341 SetFocus32( 0 ); /* A disabled window can't have the focus */
1343 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1345 ReleaseCapture(); /* A disabled window can't capture the mouse */
1347 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1348 return FALSE;
1350 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1354 /***********************************************************************
1355 * IsWindowEnabled16 (USER.35)
1357 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1359 return IsWindowEnabled32(hWnd);
1363 /***********************************************************************
1364 * IsWindowEnabled32 (USER32.349)
1366 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1368 WND * wndPtr;
1370 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1371 return !(wndPtr->dwStyle & WS_DISABLED);
1375 /***********************************************************************
1376 * IsWindowUnicode (USER32.350)
1378 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1380 WND * wndPtr;
1382 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1383 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1387 /**********************************************************************
1388 * GetWindowWord16 (USER.133)
1390 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1392 return GetWindowWord32( hwnd, offset );
1396 /**********************************************************************
1397 * GetWindowWord32 (USER32.314)
1399 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1401 WND * wndPtr = WIN_FindWndPtr( hwnd );
1402 if (!wndPtr) return 0;
1403 if (offset >= 0)
1405 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1407 WARN( win, "Invalid offset %d\n", offset );
1408 return 0;
1410 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1412 switch(offset)
1414 case GWW_ID:
1415 if (HIWORD(wndPtr->wIDmenu))
1416 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1417 wndPtr->wIDmenu);
1418 return (WORD)wndPtr->wIDmenu;
1419 case GWW_HWNDPARENT:
1420 return wndPtr->parent ?
1421 wndPtr->parent->hwndSelf : (
1422 wndPtr->owner ?
1423 wndPtr->owner->hwndSelf :
1425 case GWW_HINSTANCE:
1426 if (HIWORD(wndPtr->hInstance))
1427 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1428 wndPtr->hInstance);
1429 return (WORD)wndPtr->hInstance;
1430 default:
1431 WARN( win, "Invalid offset %d\n", offset );
1432 return 0;
1437 /**********************************************************************
1438 * WIN_GetWindowInstance
1440 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1442 WND * wndPtr = WIN_FindWndPtr( hwnd );
1443 if (!wndPtr) return (HINSTANCE32)0;
1444 return wndPtr->hInstance;
1448 /**********************************************************************
1449 * SetWindowWord16 (USER.134)
1451 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1453 return SetWindowWord32( hwnd, offset, newval );
1457 /**********************************************************************
1458 * SetWindowWord32 (USER32.524)
1460 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1462 WORD *ptr, retval;
1463 WND * wndPtr = WIN_FindWndPtr( hwnd );
1464 if (!wndPtr) return 0;
1465 if (offset >= 0)
1467 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1469 WARN( win, "Invalid offset %d\n", offset );
1470 return 0;
1472 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1474 else switch(offset)
1476 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1477 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1478 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1479 default:
1480 WARN( win, "Invalid offset %d\n", offset );
1481 return 0;
1483 retval = *ptr;
1484 *ptr = newval;
1485 return retval;
1489 /**********************************************************************
1490 * WIN_GetWindowLong
1492 * Helper function for GetWindowLong().
1494 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1496 LONG retval;
1497 WND * wndPtr = WIN_FindWndPtr( hwnd );
1498 if (!wndPtr) return 0;
1499 if (offset >= 0)
1501 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1503 WARN( win, "Invalid offset %d\n", offset );
1504 return 0;
1506 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1507 /* Special case for dialog window procedure */
1508 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1509 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1510 return retval;
1512 switch(offset)
1514 case GWL_USERDATA: return wndPtr->userdata;
1515 case GWL_STYLE: return wndPtr->dwStyle;
1516 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1517 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1518 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1519 type );
1520 case GWL_HWNDPARENT: return wndPtr->parent ?
1521 (HWND32)wndPtr->parent->hwndSelf : 0;
1522 case GWL_HINSTANCE: return wndPtr->hInstance;
1523 default:
1524 WARN( win, "Unknown offset %d\n", offset );
1526 return 0;
1530 /**********************************************************************
1531 * WIN_SetWindowLong
1533 * Helper function for SetWindowLong().
1535 * 0 is the failure code. However, in the case of failure SetLastError
1536 * must be set to distinguish between a 0 return value and a failure.
1538 * FIXME: The error values for SetLastError may not be right. Can
1539 * someone check with the real thing?
1541 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1542 WINDOWPROCTYPE type )
1544 LONG *ptr, retval;
1545 WND * wndPtr = WIN_FindWndPtr( hwnd );
1546 STYLESTRUCT style;
1548 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1550 if (!wndPtr)
1552 /* Is this the right error? */
1553 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1554 return 0;
1557 if (offset >= 0)
1559 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1561 WARN( win, "Invalid offset %d\n", offset );
1563 /* Is this the right error? */
1564 SetLastError( ERROR_OUTOFMEMORY );
1566 return 0;
1568 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1569 /* Special case for dialog window procedure */
1570 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1572 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1573 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1574 type, WIN_PROC_WINDOW );
1575 return retval;
1578 else switch(offset)
1580 case GWL_ID:
1581 ptr = (DWORD*)&wndPtr->wIDmenu;
1582 break;
1583 case GWL_HINSTANCE:
1584 return SetWindowWord32( hwnd, offset, newval );
1585 case GWL_WNDPROC:
1586 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1587 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1588 type, WIN_PROC_WINDOW );
1589 return retval;
1590 case GWL_STYLE:
1591 style.styleOld = wndPtr->dwStyle;
1592 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1593 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1595 if (wndPtr->flags & WIN_ISWIN32)
1596 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1597 wndPtr->dwStyle = style.styleNew;
1598 if (wndPtr->flags & WIN_ISWIN32)
1599 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1600 return style.styleOld;
1602 case GWL_USERDATA:
1603 ptr = &wndPtr->userdata;
1604 break;
1605 case GWL_EXSTYLE:
1606 style.styleOld = wndPtr->dwExStyle;
1607 style.styleNew = newval;
1608 if (wndPtr->flags & WIN_ISWIN32)
1609 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1610 wndPtr->dwExStyle = newval;
1611 if (wndPtr->flags & WIN_ISWIN32)
1612 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1613 return style.styleOld;
1615 default:
1616 WARN( win, "Invalid offset %d\n", offset );
1618 /* Don't think this is right error but it should do */
1619 SetLastError( ERROR_OUTOFMEMORY );
1621 return 0;
1623 retval = *ptr;
1624 *ptr = newval;
1625 return retval;
1629 /**********************************************************************
1630 * GetWindowLong16 (USER.135)
1632 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1634 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1638 /**********************************************************************
1639 * GetWindowLong32A (USER32.305)
1641 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1643 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1647 /**********************************************************************
1648 * GetWindowLong32W (USER32.306)
1650 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1652 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1656 /**********************************************************************
1657 * SetWindowLong16 (USER.136)
1659 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1661 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1665 /**********************************************************************
1666 * SetWindowLong32A (USER32.517)
1668 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1670 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1674 /**********************************************************************
1675 * SetWindowLong32W (USER32.518) Set window attribute
1677 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1678 * value in a window's extra memory.
1680 * The _hwnd_ parameter specifies the window. is the handle to a
1681 * window that has extra memory. The _newval_ parameter contains the
1682 * new attribute or extra memory value. If positive, the _offset_
1683 * parameter is the byte-addressed location in the window's extra
1684 * memory to set. If negative, _offset_ specifies the window
1685 * attribute to set, and should be one of the following values:
1687 * GWL_EXSTYLE The window's extended window style
1689 * GWL_STYLE The window's window style.
1691 * GWL_WNDPROC Pointer to the window's window procedure.
1693 * GWL_HINSTANCE The window's pplication instance handle.
1695 * GWL_ID The window's identifier.
1697 * GWL_USERDATA The window's user-specified data.
1699 * If the window is a dialog box, the _offset_ parameter can be one of
1700 * the following values:
1702 * DWL_DLGPROC The address of the window's dialog box procedure.
1704 * DWL_MSGRESULT The return value of a message
1705 * that the dialog box procedure processed.
1707 * DWL_USER Application specific information.
1709 * RETURNS
1711 * If successful, returns the previous value located at _offset_. Otherwise,
1712 * returns 0.
1714 * NOTES
1716 * Extra memory for a window class is specified by a nonzero cbWndExtra
1717 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1718 * time of class creation.
1720 * Using GWL_WNDPROC to set a new window procedure effectively creates
1721 * a window subclass. Use CallWindowProc() in the new windows procedure
1722 * to pass messages to the superclass's window procedure.
1724 * The user data is reserved for use by the application which created
1725 * the window.
1727 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1728 * instead, call the EnableWindow() function to change the window's
1729 * disabled state.
1731 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1732 * SetParent() instead.
1734 * Win95:
1735 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1736 * it sends WM_STYLECHANGING before changing the settings
1737 * and WM_STYLECHANGED afterwards.
1738 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1740 * BUGS
1742 * GWL_STYLE does not dispatch WM_STYLE... messages.
1744 * CONFORMANCE
1746 * ECMA-234, Win32
1749 LONG WINAPI SetWindowLong32W(
1750 HWND32 hwnd, /* window to alter */
1751 INT32 offset, /* offset, in bytes, of location to alter */
1752 LONG newval /* new value of location */
1754 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1758 /*******************************************************************
1759 * GetWindowText16 (USER.36)
1761 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1763 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1767 /*******************************************************************
1768 * GetWindowText32A (USER32.309)
1770 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1772 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1773 (LPARAM)lpString );
1776 /*******************************************************************
1777 * InternalGetWindowText (USER32.326)
1779 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1781 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1782 return GetWindowText32W(hwnd,lpString,nMaxCount);
1786 /*******************************************************************
1787 * GetWindowText32W (USER32.312)
1789 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1791 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1792 (LPARAM)lpString );
1796 /*******************************************************************
1797 * SetWindowText16 (USER.37)
1799 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1801 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1805 /*******************************************************************
1806 * SetWindowText32A (USER32.521)
1808 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1810 return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1814 /*******************************************************************
1815 * SetWindowText32W (USER32.523)
1817 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1819 return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1823 /*******************************************************************
1824 * GetWindowTextLength16 (USER.38)
1826 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1828 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1832 /*******************************************************************
1833 * GetWindowTextLength32A (USER32.310)
1835 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1837 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1840 /*******************************************************************
1841 * GetWindowTextLength32W (USER32.311)
1843 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1845 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1849 /*******************************************************************
1850 * IsWindow16 (USER.47)
1852 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1854 return IsWindow32( hwnd );
1857 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1859 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1860 HWND16 hwnd = (HWND16)stack[2];
1862 AX_reg(context) = IsWindow32( hwnd );
1863 ES_reg(context) = USER_HeapSel;
1867 /*******************************************************************
1868 * IsWindow32 (USER32.348)
1870 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1872 WND * wndPtr = WIN_FindWndPtr( hwnd );
1873 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1877 /*****************************************************************
1878 * GetParent16 (USER.46)
1880 HWND16 WINAPI GetParent16( HWND16 hwnd )
1882 return (HWND16)GetParent32( hwnd );
1886 /*****************************************************************
1887 * GetParent32 (USER32.278)
1889 HWND32 WINAPI GetParent32( HWND32 hwnd )
1891 WND *wndPtr = WIN_FindWndPtr(hwnd);
1892 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1893 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1894 return wndPtr ? wndPtr->hwndSelf : 0;
1897 /*****************************************************************
1898 * WIN_GetTopParent
1900 * Get the top-level parent for a child window.
1902 WND* WIN_GetTopParentPtr( WND* pWnd )
1904 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1905 return pWnd;
1908 /*****************************************************************
1909 * WIN_GetTopParent
1911 * Get the top-level parent for a child window.
1913 HWND32 WIN_GetTopParent( HWND32 hwnd )
1915 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1916 return wndPtr ? wndPtr->hwndSelf : 0;
1920 /*****************************************************************
1921 * SetParent16 (USER.233)
1923 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1925 return SetParent32( hwndChild, hwndNewParent );
1929 /*****************************************************************
1930 * SetParent32 (USER32.495)
1932 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1934 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1935 WND *pWndNewParent =
1936 (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1937 WND *pWndOldParent =
1938 (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1940 /* SetParent32 additionally needs to make hwndChild the topmost window
1941 in the x-order and send the expected WM_WINDOWPOSCHANGING and
1942 WM_WINDOWPOSCHANGED notification messages.
1944 SetWindowPos32( hwndChild, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1946 return pWndOldParent?pWndOldParent->hwndSelf:0;
1949 /*******************************************************************
1950 * IsChild16 (USER.48)
1952 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1954 return IsChild32(parent,child);
1958 /*******************************************************************
1959 * IsChild32 (USER32.339)
1961 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1963 WND * wndPtr = WIN_FindWndPtr( child );
1964 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1966 wndPtr = wndPtr->parent;
1967 if (wndPtr->hwndSelf == parent) return TRUE;
1969 return FALSE;
1973 /***********************************************************************
1974 * IsWindowVisible16 (USER.49)
1976 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1978 return IsWindowVisible32(hwnd);
1982 /***********************************************************************
1983 * IsWindowVisible32 (USER32.351)
1985 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1987 WND *wndPtr = WIN_FindWndPtr( hwnd );
1988 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1990 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1991 wndPtr = wndPtr->parent;
1993 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1997 /***********************************************************************
1998 * WIN_IsWindowDrawable
2000 * hwnd is drawable when it is visible, all parents are not
2001 * minimized, and it is itself not minimized unless we are
2002 * trying to draw its default class icon.
2004 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2006 if( (wnd->dwStyle & WS_MINIMIZE &&
2007 icon && wnd->class->hIcon) ||
2008 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2009 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2010 if( wnd->dwStyle & WS_MINIMIZE ||
2011 !(wnd->dwStyle & WS_VISIBLE) ) break;
2012 return (wnd == NULL);
2016 /*******************************************************************
2017 * GetTopWindow16 (USER.229)
2019 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2021 return GetTopWindow32(hwnd);
2025 /*******************************************************************
2026 * GetTopWindow32 (USER.229)
2028 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2030 WND * wndPtr = WIN_FindWndPtr( hwnd );
2031 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2032 else return 0;
2036 /*******************************************************************
2037 * GetWindow16 (USER.262)
2039 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2041 return GetWindow32( hwnd,rel );
2045 /*******************************************************************
2046 * GetWindow32 (USER32.302)
2048 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2050 WND * wndPtr = WIN_FindWndPtr( hwnd );
2051 if (!wndPtr) return 0;
2052 switch(rel)
2054 case GW_HWNDFIRST:
2055 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2056 else return 0;
2058 case GW_HWNDLAST:
2059 if (!wndPtr->parent) return 0; /* Desktop window */
2060 while (wndPtr->next) wndPtr = wndPtr->next;
2061 return wndPtr->hwndSelf;
2063 case GW_HWNDNEXT:
2064 if (!wndPtr->next) return 0;
2065 return wndPtr->next->hwndSelf;
2067 case GW_HWNDPREV:
2068 if (!wndPtr->parent) return 0; /* Desktop window */
2069 wndPtr = wndPtr->parent->child; /* First sibling */
2070 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2071 while (wndPtr->next)
2073 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2074 wndPtr = wndPtr->next;
2076 return 0;
2078 case GW_OWNER:
2079 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2081 case GW_CHILD:
2082 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2084 return 0;
2088 /*******************************************************************
2089 * GetNextWindow16 (USER.230)
2091 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2093 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2094 return GetWindow16( hwnd, flag );
2097 /*******************************************************************
2098 * ShowOwnedPopups16 (USER.265)
2100 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2102 ShowOwnedPopups32( owner, fShow );
2106 /*******************************************************************
2107 * ShowOwnedPopups32 (USER32.531)
2109 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2111 WND *pWnd = pWndDesktop->child;
2112 while (pWnd)
2114 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2115 (pWnd->dwStyle & WS_POPUP))
2116 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2117 pWnd = pWnd->next;
2119 return TRUE;
2123 /*******************************************************************
2124 * GetLastActivePopup16 (USER.287)
2126 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2128 return GetLastActivePopup32( hwnd );
2131 /*******************************************************************
2132 * GetLastActivePopup32 (USER32.256)
2134 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2136 WND *wndPtr;
2137 wndPtr = WIN_FindWndPtr(hwnd);
2138 if (wndPtr == NULL) return hwnd;
2139 return wndPtr->hwndLastActive;
2143 /*******************************************************************
2144 * WIN_BuildWinArray
2146 * Build an array of pointers to the children of a given window.
2147 * The array must be freed with HeapFree(SystemHeap). Return NULL
2148 * when no windows are found.
2150 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2152 WND **list, **ppWnd;
2153 WND *pWnd;
2154 UINT32 count, skipOwned, skipHidden;
2155 DWORD skipFlags;
2157 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2158 skipOwned = bwaFlags & BWA_SKIPOWNED;
2159 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2160 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2162 /* First count the windows */
2164 if (!wndPtr) wndPtr = pWndDesktop;
2165 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2167 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2168 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2171 if( count )
2173 /* Now build the list of all windows */
2175 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2177 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2179 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2180 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2182 *ppWnd++ = pWnd;
2183 count++;
2186 *ppWnd = NULL;
2188 else count = 0;
2189 } else list = NULL;
2191 if( pTotal ) *pTotal = count;
2192 return list;
2196 /*******************************************************************
2197 * EnumWindows16 (USER.54)
2199 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2201 WND **list, **ppWnd;
2203 /* We have to build a list of all windows first, to avoid */
2204 /* unpleasant side-effects, for instance if the callback */
2205 /* function changes the Z-order of the windows. */
2207 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2209 /* Now call the callback function for every window */
2211 for (ppWnd = list; *ppWnd; ppWnd++)
2213 /* Make sure that the window still exists */
2214 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2215 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2217 HeapFree( SystemHeap, 0, list );
2218 return TRUE;
2222 /*******************************************************************
2223 * EnumWindows32 (USER32.193)
2225 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2227 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2231 /**********************************************************************
2232 * EnumTaskWindows16 (USER.225)
2234 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2235 LPARAM lParam )
2237 WND **list, **ppWnd;
2239 /* This function is the same as EnumWindows(), */
2240 /* except for an added check on the window's task. */
2242 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2244 /* Now call the callback function for every window */
2246 for (ppWnd = list; *ppWnd; ppWnd++)
2248 /* Make sure that the window still exists */
2249 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2250 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2251 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2253 HeapFree( SystemHeap, 0, list );
2254 return TRUE;
2258 /**********************************************************************
2259 * EnumThreadWindows (USER32.190)
2261 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2263 THDB *tdb = THREAD_ID_TO_THDB(id);
2265 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2269 /**********************************************************************
2270 * WIN_EnumChildWindows
2272 * Helper function for EnumChildWindows().
2274 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2275 LPARAM lParam )
2277 WND **childList;
2278 BOOL16 ret = FALSE;
2280 for ( ; *ppWnd; ppWnd++)
2282 /* Make sure that the window still exists */
2283 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2284 /* Build children list first */
2285 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2286 ret = func( (*ppWnd)->hwndSelf, lParam );
2287 if (childList)
2289 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2290 HeapFree( SystemHeap, 0, childList );
2292 if (!ret) return FALSE;
2294 return TRUE;
2298 /**********************************************************************
2299 * EnumChildWindows16 (USER.55)
2301 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2302 LPARAM lParam )
2304 WND **list, *pParent;
2306 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2307 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2308 WIN_EnumChildWindows( list, func, lParam );
2309 HeapFree( SystemHeap, 0, list );
2310 return TRUE;
2314 /**********************************************************************
2315 * EnumChildWindows32 (USER32.178)
2317 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2318 LPARAM lParam )
2320 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2321 lParam );
2325 /*******************************************************************
2326 * AnyPopup16 (USER.52)
2328 BOOL16 WINAPI AnyPopup16(void)
2330 return AnyPopup32();
2334 /*******************************************************************
2335 * AnyPopup32 (USER32.4)
2337 BOOL32 WINAPI AnyPopup32(void)
2339 WND *wndPtr;
2340 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2341 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2342 return FALSE;
2346 /*******************************************************************
2347 * FlashWindow16 (USER.105)
2349 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2351 return FlashWindow32( hWnd, bInvert );
2355 /*******************************************************************
2356 * FlashWindow32 (USER32.202)
2358 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2360 WND *wndPtr = WIN_FindWndPtr(hWnd);
2362 TRACE(win,"%04x\n", hWnd);
2364 if (!wndPtr) return FALSE;
2366 if (wndPtr->dwStyle & WS_MINIMIZE)
2368 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2370 HDC32 hDC = GetDC32(hWnd);
2372 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2373 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2375 ReleaseDC32( hWnd, hDC );
2376 wndPtr->flags |= WIN_NCACTIVATED;
2378 else
2380 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2381 RDW_UPDATENOW | RDW_FRAME, 0 );
2382 wndPtr->flags &= ~WIN_NCACTIVATED;
2384 return TRUE;
2386 else
2388 WPARAM16 wparam;
2389 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2390 else wparam = (hWnd == GetActiveWindow32());
2392 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2393 return wparam;
2398 /*******************************************************************
2399 * SetSysModalWindow16 (USER.188)
2401 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2403 HWND32 hWndOldModal = hwndSysModal;
2404 hwndSysModal = hWnd;
2405 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2406 return hWndOldModal;
2410 /*******************************************************************
2411 * GetSysModalWindow16 (USER.52)
2413 HWND16 WINAPI GetSysModalWindow16(void)
2415 return hwndSysModal;
2419 /*******************************************************************
2420 * GetWindowContextHelpId (USER32.303)
2422 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2424 WND *wnd = WIN_FindWndPtr( hwnd );
2425 if (!wnd) return 0;
2426 return wnd->helpContext;
2430 /*******************************************************************
2431 * SetWindowContextHelpId (USER32.515)
2433 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2435 WND *wnd = WIN_FindWndPtr( hwnd );
2436 if (!wnd) return FALSE;
2437 wnd->helpContext = id;
2438 return TRUE;
2442 /*******************************************************************
2443 * DRAG_QueryUpdate
2445 * recursively find a child that contains spDragInfo->pt point
2446 * and send WM_QUERYDROPOBJECT
2448 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2450 BOOL16 wParam,bResult = 0;
2451 POINT32 pt;
2452 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2453 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2454 RECT32 tempRect;
2456 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2458 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2460 GetWindowRect32(hQueryWnd,&tempRect);
2462 if( !PtInRect32(&tempRect,pt) ||
2463 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2464 return 0;
2466 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2468 tempRect = ptrQueryWnd->rectClient;
2469 if(ptrQueryWnd->dwStyle & WS_CHILD)
2470 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2471 (LPPOINT32)&tempRect, 2 );
2473 if (PtInRect32( &tempRect, pt))
2475 wParam = 0;
2477 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2478 if( ptrWnd->dwStyle & WS_VISIBLE )
2480 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2481 if (PtInRect32( &tempRect, pt )) break;
2484 if(ptrWnd)
2486 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2487 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2488 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2489 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2490 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2493 if(bResult) return bResult;
2495 else wParam = 1;
2497 else wParam = 1;
2499 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2501 ptrDragInfo->hScope = hQueryWnd;
2503 bResult = ( bNoSend )
2504 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2505 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2506 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2507 if( !bResult )
2508 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2510 return bResult;
2514 /*******************************************************************
2515 * DragDetect (USER.465)
2517 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2519 POINT32 pt32;
2520 CONV_POINT16TO32( &pt, &pt32 );
2521 return DragDetect32( hWnd, pt32 );
2524 /*******************************************************************
2525 * DragDetect32 (USER32.151)
2527 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2529 MSG16 msg;
2530 RECT16 rect;
2532 rect.left = pt.x - wDragWidth;
2533 rect.right = pt.x + wDragWidth;
2535 rect.top = pt.y - wDragHeight;
2536 rect.bottom = pt.y + wDragHeight;
2538 SetCapture32(hWnd);
2540 while(1)
2542 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2544 if( msg.message == WM_LBUTTONUP )
2546 ReleaseCapture();
2547 return 0;
2549 if( msg.message == WM_MOUSEMOVE )
2551 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2553 ReleaseCapture();
2554 return 1;
2558 WaitMessage();
2560 return 0;
2563 /******************************************************************************
2564 * DragObject16 (USER.464)
2566 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2567 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2569 MSG16 msg;
2570 LPDRAGINFO lpDragInfo;
2571 SEGPTR spDragInfo;
2572 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2573 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2574 WND *wndPtr = WIN_FindWndPtr(hWnd);
2575 HCURSOR16 hCurrentCursor = 0;
2576 HWND16 hCurrentWnd = 0;
2578 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2579 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2581 if( !lpDragInfo || !spDragInfo ) return 0L;
2583 hBummer = LoadCursor16(0, IDC_BUMMER16);
2585 if( !hBummer || !wndPtr )
2587 GlobalFree16(hDragInfo);
2588 return 0L;
2591 if(hCursor)
2593 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2595 GlobalFree16(hDragInfo);
2596 return 0L;
2599 if( hDragCursor == hCursor ) hDragCursor = 0;
2600 else hCursor = hDragCursor;
2602 hOldCursor = SetCursor32(hDragCursor);
2605 lpDragInfo->hWnd = hWnd;
2606 lpDragInfo->hScope = 0;
2607 lpDragInfo->wFlags = wObj;
2608 lpDragInfo->hList = szList; /* near pointer! */
2609 lpDragInfo->hOfStruct = hOfStruct;
2610 lpDragInfo->l = 0L;
2612 SetCapture32(hWnd);
2613 ShowCursor32( TRUE );
2617 do{ WaitMessage(); }
2618 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2620 *(lpDragInfo+1) = *lpDragInfo;
2622 lpDragInfo->pt = msg.pt;
2624 /* update DRAGINFO struct */
2625 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2627 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2628 hCurrentCursor = hCursor;
2629 else
2631 hCurrentCursor = hBummer;
2632 lpDragInfo->hScope = 0;
2634 if( hCurrentCursor )
2635 SetCursor32(hCurrentCursor);
2637 /* send WM_DRAGLOOP */
2638 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2639 (LPARAM) spDragInfo );
2640 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2641 if( hCurrentWnd != lpDragInfo->hScope )
2643 if( hCurrentWnd )
2644 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2645 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2646 HIWORD(spDragInfo)) );
2647 hCurrentWnd = lpDragInfo->hScope;
2648 if( hCurrentWnd )
2649 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2651 else
2652 if( hCurrentWnd )
2653 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2655 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2657 ReleaseCapture();
2658 ShowCursor32( FALSE );
2660 if( hCursor )
2662 SetCursor32( hOldCursor );
2663 if (hDragCursor) DestroyCursor32( hDragCursor );
2666 if( hCurrentCursor != hBummer )
2667 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2668 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2669 else
2670 msg.lParam = 0;
2671 GlobalFree16(hDragInfo);
2673 return (DWORD)(msg.lParam);