Added 24->32 packed pixel mapping support to convert.
[wine/multimedia.git] / windows / win.c
blob5eb31a9acc03c697502751bda2dbb18d85f3c427
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "monitor.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "syslevel.h"
35 #include "stackframe.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(win);
39 DECLARE_DEBUG_CHANNEL(msg);
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
96 while ( count-- > 0 )
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? ptr->text : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN("Invalid window handle %04x\n", hwnd );
274 return;
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
280 " Text");
282 while (ptr)
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text?ptr->text:"<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
344 return FALSE;
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE("skipping window %04x\n",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
439 WND *pWnd;
441 TRACE("%04x\n", wndPtr->hwndSelf );
443 /* free child windows */
444 WIN_LockWndPtr(wndPtr->child);
445 while ((pWnd = wndPtr->child))
447 wndPtr->child = WIN_DestroyWindow( pWnd );
448 WIN_ReleaseWndPtr(pWnd);
452 * Clear the update region to make sure no WM_PAINT messages will be
453 * generated for this window while processing the WM_NCDESTROY.
455 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
457 if (wndPtr->hrgnUpdate > 1)
458 DeleteObject( wndPtr->hrgnUpdate );
460 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
462 wndPtr->hrgnUpdate = 0;
466 * Send the WM_NCDESTROY to the window being destroyed.
468 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
470 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
472 WINPOS_CheckInternalPos( wndPtr );
473 if( hwnd == GetCapture()) ReleaseCapture();
475 /* free resources associated with the window */
477 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
478 PROPERTY_RemoveWindowProps( wndPtr );
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 /* toss stale messages from the queue */
484 if( wndPtr->hmemTaskQ )
486 BOOL bPostQuit = FALSE;
487 WPARAM wQuitParam = 0;
488 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
489 QMSG *qmsg;
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
495 bPostQuit = TRUE;
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
501 QUEUE_Unlock(msgQ);
503 /* repost WM_QUIT to make sure this app exits its message loop */
504 if( bPostQuit ) PostQuitMessage(wQuitParam);
505 wndPtr->hmemTaskQ = 0;
508 if (!(wndPtr->dwStyle & WS_CHILD))
509 if (wndPtr->wIDmenu)
511 DestroyMenu( wndPtr->wIDmenu );
512 wndPtr->wIDmenu = 0;
514 if (wndPtr->hSysMenu)
516 DestroyMenu( wndPtr->hSysMenu );
517 wndPtr->hSysMenu = 0;
519 wndPtr->pDriver->pDestroyWindow( wndPtr );
520 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
521 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
522 wndPtr->class->cWindows--;
523 wndPtr->class = NULL;
525 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
527 wndPtr->pDriver->pFinalize(wndPtr);
529 return pWnd;
532 /***********************************************************************
533 * WIN_ResetQueueWindows
535 * Reset the queue of all the children of a given window.
536 * Return TRUE if something was done.
538 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
540 BOOL ret = FALSE;
542 if (hNew) /* Set a new queue */
544 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
546 if (wnd->hmemTaskQ == hQueue)
548 wnd->hmemTaskQ = hNew;
549 ret = TRUE;
551 if (wnd->child)
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
559 while (wnd->child)
561 WND *tmp = WIN_LockWndPtr(wnd->child);
562 WND *tmp2;
563 ret = FALSE;
564 while (tmp)
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
569 ret = TRUE;
570 break;
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
574 ret = TRUE;
575 else
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
582 if (!ret) break;
585 return ret;
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
595 CLASS *class;
596 HWND hwndDesktop;
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
604 return FALSE;
606 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
607 if (!hwndDesktop) return FALSE;
608 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
610 pWndDesktop->pDriver = WND_Driver;
611 pWndDesktop->pDriver->pInitialize(pWndDesktop);
613 pWndDesktop->next = NULL;
614 pWndDesktop->child = NULL;
615 pWndDesktop->parent = NULL;
616 pWndDesktop->owner = NULL;
617 pWndDesktop->class = class;
618 pWndDesktop->dwMagic = WND_MAGIC;
619 pWndDesktop->hwndSelf = hwndDesktop;
620 pWndDesktop->hInstance = 0;
621 pWndDesktop->rectWindow.left = 0;
622 pWndDesktop->rectWindow.top = 0;
623 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
624 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
625 pWndDesktop->rectClient = pWndDesktop->rectWindow;
626 pWndDesktop->text = NULL;
627 pWndDesktop->hmemTaskQ = GetFastQueue16();
628 pWndDesktop->hrgnUpdate = 0;
629 pWndDesktop->hwndLastActive = hwndDesktop;
630 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
631 WS_CLIPSIBLINGS;
632 pWndDesktop->dwExStyle = 0;
633 pWndDesktop->dce = NULL;
634 pWndDesktop->pVScroll = NULL;
635 pWndDesktop->pHScroll = NULL;
636 pWndDesktop->pProp = NULL;
637 pWndDesktop->wIDmenu = 0;
638 pWndDesktop->helpContext = 0;
639 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
640 pWndDesktop->hSysMenu = 0;
641 pWndDesktop->userdata = 0;
642 pWndDesktop->winproc = (WNDPROC16)class->winproc;
643 pWndDesktop->irefCount = 0;
645 /* FIXME: How do we know if it should be Unicode or not */
646 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
647 return FALSE;
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 return TRUE;
655 /***********************************************************************
656 * WIN_CreateWindowEx
658 * Fix the coordinates - Helper for WIN_CreateWindowEx.
659 * returns default show mode in sw.
660 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
662 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
665 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
667 if (cs->style & (WS_CHILD | WS_POPUP))
669 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
670 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
672 else /* overlapped window */
674 STARTUPINFOA info;
676 GetStartupInfoA( &info );
678 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
680 /* Never believe Microsoft's documentation... CreateWindowEx doc says
681 * that if an overlapped window is created with WS_VISIBLE style bit
682 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
683 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
684 * reveals that
686 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
687 * 2) it does not ignore the y parameter as the docs claim; instead, it
688 * uses it as second parameter to ShowWindow() unless y is either
689 * CW_USEDEFAULT or CW_USEDEFAULT16.
691 * The fact that we didn't do 2) caused bogus windows pop up when wine
692 * was running apps that were using this obscure feature. Example -
693 * calc.exe that comes with Win98 (only Win98, it's different from
694 * the one that comes with Win95 and NT)
696 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
697 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
698 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
701 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
703 if (info.dwFlags & STARTF_USESIZE)
705 cs->cx = info.dwXSize;
706 cs->cy = info.dwYSize;
708 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 RECT r;
711 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
712 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /***********************************************************************
721 * WIN_CreateWindowEx
723 * Implementation of CreateWindowEx().
725 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
726 BOOL win32, BOOL unicode )
728 INT sw = SW_SHOW;
729 CLASS *classPtr;
730 WND *wndPtr;
731 HWND retvalue;
732 HWND16 hwnd, hwndLinkAfter;
733 POINT maxSize, maxPos, minTrack, maxTrack;
734 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
736 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
737 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
738 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
739 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
740 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
742 /* Find the parent window */
744 if (cs->hwndParent)
746 /* Make sure parent is valid */
747 if (!IsWindow( cs->hwndParent ))
749 WARN("Bad parent %04x\n", cs->hwndParent );
750 return 0;
752 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
753 WARN("No parent for child window\n" );
754 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
757 /* Find the window class */
758 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
760 WARN("Bad class '%s'\n", cs->lpszClass );
761 return 0;
764 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
766 /* Create the window structure */
768 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
769 - sizeof(wndPtr->wExtra) )))
771 TRACE("out of memory\n" );
772 return 0;
775 /* Fill the window structure */
777 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
778 wndPtr->next = NULL;
779 wndPtr->child = NULL;
781 if ((cs->style & WS_CHILD) && cs->hwndParent)
783 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
784 wndPtr->owner = NULL;
785 WIN_ReleaseWndPtr(wndPtr->parent);
787 else
789 wndPtr->parent = pWndDesktop;
790 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
791 wndPtr->owner = NULL;
792 else
794 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
795 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
796 WIN_ReleaseWndPtr(wndPtr->owner);
797 WIN_ReleaseWndPtr(tmpWnd);
802 wndPtr->pDriver = wndPtr->parent->pDriver;
803 wndPtr->pDriver->pInitialize(wndPtr);
805 wndPtr->class = classPtr;
806 wndPtr->winproc = classPtr->winproc;
807 wndPtr->dwMagic = WND_MAGIC;
808 wndPtr->hwndSelf = hwnd;
809 wndPtr->hInstance = cs->hInstance;
810 wndPtr->text = NULL;
811 wndPtr->hmemTaskQ = GetFastQueue16();
812 wndPtr->hrgnUpdate = 0;
813 wndPtr->hwndLastActive = hwnd;
814 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
815 wndPtr->dwExStyle = cs->dwExStyle;
816 wndPtr->wIDmenu = 0;
817 wndPtr->helpContext = 0;
818 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
819 wndPtr->pVScroll = NULL;
820 wndPtr->pHScroll = NULL;
821 wndPtr->pProp = NULL;
822 wndPtr->userdata = 0;
823 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
824 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
825 wndPtr->irefCount = 1;
827 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
829 /* Call the WH_CBT hook */
831 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
832 ? HWND_BOTTOM : HWND_TOP;
834 if (HOOK_IsHooked( WH_CBT ))
836 CBT_CREATEWNDA cbtc;
837 LRESULT ret;
839 cbtc.lpcs = cs;
840 cbtc.hwndInsertAfter = hwndLinkAfter;
841 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
842 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
843 if (ret)
845 TRACE("CBT-hook returned 0\n");
846 wndPtr->pDriver->pFinalize(wndPtr);
847 USER_HEAP_FREE( hwnd );
848 retvalue = 0;
849 goto end;
853 /* Increment class window counter */
855 classPtr->cWindows++;
857 /* Correct the window style */
859 if (!(cs->style & WS_CHILD))
861 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
862 if (!(cs->style & WS_POPUP))
864 wndPtr->dwStyle |= WS_CAPTION;
865 wndPtr->flags |= WIN_NEED_SIZE;
869 /* Get class or window DC if needed */
871 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
872 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
873 else wndPtr->dce = NULL;
875 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
877 wndPtr->rectWindow.left = cs->x;
878 wndPtr->rectWindow.top = cs->y;
879 wndPtr->rectWindow.right = cs->x + cs->cx;
880 wndPtr->rectWindow.bottom = cs->y + cs->cy;
881 wndPtr->rectClient = wndPtr->rectWindow;
883 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
885 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
887 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
888 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
889 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
890 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
891 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
894 if(cs->style & WS_CHILD)
896 if(cs->cx < 0) cs->cx = 0;
897 if(cs->cy < 0) cs->cy = 0;
899 else
901 if (cs->cx <= 0) cs->cx = 1;
902 if (cs->cy <= 0) cs->cy = 1;
905 wndPtr->rectWindow.left = cs->x;
906 wndPtr->rectWindow.top = cs->y;
907 wndPtr->rectWindow.right = cs->x + cs->cx;
908 wndPtr->rectWindow.bottom = cs->y + cs->cy;
909 wndPtr->rectClient = wndPtr->rectWindow;
911 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
913 retvalue = FALSE;
914 goto end;
917 /* Set the window menu */
919 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
921 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
922 else
924 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
925 if (classPtr->menuNameA)
926 cs->hMenu = HIWORD(classPtr->menuNameA) ?
927 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
928 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
929 #else
930 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
931 if (menuName)
933 if (HIWORD(cs->hInstance))
934 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
935 else
936 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
938 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
940 #endif
943 else wndPtr->wIDmenu = (UINT)cs->hMenu;
945 /* Send the WM_CREATE message
946 * Perhaps we shouldn't allow width/height changes as well.
947 * See p327 in "Internals".
950 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
952 localSend32 = unicode ? SendMessageW : SendMessageA;
953 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
955 /* Insert the window in the linked list */
957 WIN_LinkWindow( hwnd, hwndLinkAfter );
959 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
960 NULL, NULL, 0, &wndPtr->rectClient );
961 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
962 maxPos.y - wndPtr->rectWindow.top);
963 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
965 /* Send the size messages */
967 if (!(wndPtr->flags & WIN_NEED_SIZE))
969 /* send it anyway */
970 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
971 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
972 WARN("sending bogus WM_SIZE message 0x%08lx\n",
973 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
974 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
975 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
976 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
977 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
978 SendMessageA( hwnd, WM_MOVE, 0,
979 MAKELONG( wndPtr->rectClient.left,
980 wndPtr->rectClient.top ) );
983 /* Show the window, maximizing or minimizing if needed */
985 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
987 RECT16 newPos;
988 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
989 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
990 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
991 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
992 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
993 : SWP_NOZORDER | SWP_FRAMECHANGED;
994 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
995 newPos.right, newPos.bottom, swFlag );
998 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1000 /* Notify the parent window only */
1002 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1003 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
1004 if( !IsWindow(hwnd) )
1006 retvalue = 0;
1007 goto end;
1011 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1013 /* Call WH_SHELL hook */
1015 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1016 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1018 TRACE("created window %04x\n", hwnd);
1019 retvalue = hwnd;
1020 goto end;
1022 WIN_UnlinkWindow( hwnd );
1025 /* Abort window creation */
1027 WARN("aborted by WM_xxCREATE!\n");
1028 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1029 retvalue = 0;
1030 end:
1031 WIN_ReleaseWndPtr(wndPtr);
1033 return retvalue;
1037 /***********************************************************************
1038 * CreateWindow16 (USER.41)
1040 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1041 DWORD style, INT16 x, INT16 y, INT16 width,
1042 INT16 height, HWND16 parent, HMENU16 menu,
1043 HINSTANCE16 instance, LPVOID data )
1045 return CreateWindowEx16( 0, className, windowName, style,
1046 x, y, width, height, parent, menu, instance, data );
1050 /***********************************************************************
1051 * CreateWindowEx16 (USER.452)
1053 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1054 LPCSTR windowName, DWORD style, INT16 x,
1055 INT16 y, INT16 width, INT16 height,
1056 HWND16 parent, HMENU16 menu,
1057 HINSTANCE16 instance, LPVOID data )
1059 ATOM classAtom;
1060 CREATESTRUCTA cs;
1061 char buffer[256];
1063 /* Find the class atom */
1065 if (HIWORD(className))
1067 if (!(classAtom = GlobalFindAtomA( className )))
1069 ERR( "bad class name %s\n", debugres_a(className) );
1070 return 0;
1073 else
1075 classAtom = LOWORD(className);
1076 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1078 ERR( "bad atom %x\n", classAtom);
1079 return 0;
1081 className = buffer;
1084 /* Fix the coordinates */
1086 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1087 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1088 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1089 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1091 /* Create the window */
1093 cs.lpCreateParams = data;
1094 cs.hInstance = (HINSTANCE)instance;
1095 cs.hMenu = (HMENU)menu;
1096 cs.hwndParent = (HWND)parent;
1097 cs.style = style;
1098 cs.lpszName = windowName;
1099 cs.lpszClass = className;
1100 cs.dwExStyle = exStyle;
1102 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1106 /***********************************************************************
1107 * CreateWindowExA (USER32.83)
1109 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1110 LPCSTR windowName, DWORD style, INT x,
1111 INT y, INT width, INT height,
1112 HWND parent, HMENU menu,
1113 HINSTANCE instance, LPVOID data )
1115 ATOM classAtom;
1116 CREATESTRUCTA cs;
1117 char buffer[256];
1119 if(!instance)
1120 instance=GetModuleHandleA(NULL);
1122 if(exStyle & WS_EX_MDICHILD)
1123 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1125 /* Find the class atom */
1127 if (HIWORD(className))
1129 if (!(classAtom = GlobalFindAtomA( className )))
1131 ERR( "bad class name %s\n", debugres_a(className) );
1132 return 0;
1135 else
1137 classAtom = LOWORD(className);
1138 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1140 ERR( "bad atom %x\n", classAtom);
1141 return 0;
1143 className = buffer;
1146 /* Create the window */
1148 cs.lpCreateParams = data;
1149 cs.hInstance = instance;
1150 cs.hMenu = menu;
1151 cs.hwndParent = parent;
1152 cs.x = x;
1153 cs.y = y;
1154 cs.cx = width;
1155 cs.cy = height;
1156 cs.style = style;
1157 cs.lpszName = windowName;
1158 cs.lpszClass = className;
1159 cs.dwExStyle = exStyle;
1161 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1165 /***********************************************************************
1166 * CreateWindowExW (USER32.84)
1168 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1169 LPCWSTR windowName, DWORD style, INT x,
1170 INT y, INT width, INT height,
1171 HWND parent, HMENU menu,
1172 HINSTANCE instance, LPVOID data )
1174 ATOM classAtom;
1175 CREATESTRUCTW cs;
1176 WCHAR buffer[256];
1178 if(!instance)
1179 instance=GetModuleHandleA(NULL);
1181 if(exStyle & WS_EX_MDICHILD)
1182 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1184 /* Find the class atom */
1186 if (HIWORD(className))
1188 if (!(classAtom = GlobalFindAtomW( className )))
1190 ERR( "bad class name %s\n", debugres_w(className) );
1191 return 0;
1194 else
1196 classAtom = LOWORD(className);
1197 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1199 ERR( "bad atom %x\n", classAtom);
1200 return 0;
1202 className = buffer;
1205 /* Create the window */
1207 cs.lpCreateParams = data;
1208 cs.hInstance = instance;
1209 cs.hMenu = menu;
1210 cs.hwndParent = parent;
1211 cs.x = x;
1212 cs.y = y;
1213 cs.cx = width;
1214 cs.cy = height;
1215 cs.style = style;
1216 cs.lpszName = windowName;
1217 cs.lpszClass = className;
1218 cs.dwExStyle = exStyle;
1220 /* Note: we rely on the fact that CREATESTRUCTA and */
1221 /* CREATESTRUCTW have the same layout. */
1222 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1226 /***********************************************************************
1227 * WIN_CheckFocus
1229 static void WIN_CheckFocus( WND* pWnd )
1231 if( GetFocus16() == pWnd->hwndSelf )
1232 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1235 /***********************************************************************
1236 * WIN_SendDestroyMsg
1238 static void WIN_SendDestroyMsg( WND* pWnd )
1240 WIN_CheckFocus(pWnd);
1242 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1243 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1246 * Send the WM_DESTROY to the window.
1248 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1251 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1252 * make sure that the window still exists when we come back.
1254 if (IsWindow(pWnd->hwndSelf))
1256 HWND* pWndArray = NULL;
1257 WND* pChild = NULL;
1258 int nKidCount = 0;
1261 * Now, if the window has kids, we have to send WM_DESTROY messages
1262 * recursively to it's kids. It seems that those calls can also
1263 * trigger re-entrant calls to DestroyWindow for the kids so we must
1264 * protect against corruption of the list of siblings. We first build
1265 * a list of HWNDs representing all the kids.
1267 pChild = WIN_LockWndPtr(pWnd->child);
1268 while( pChild )
1270 nKidCount++;
1271 WIN_UpdateWndPtr(&pChild,pChild->next);
1275 * If there are no kids, we're done.
1277 if (nKidCount==0)
1278 return;
1280 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1283 * Sanity check
1285 if (pWndArray==NULL)
1286 return;
1289 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1290 * call, our linked list of siblings should be safe.
1292 nKidCount = 0;
1293 pChild = WIN_LockWndPtr(pWnd->child);
1294 while( pChild )
1296 pWndArray[nKidCount] = pChild->hwndSelf;
1297 nKidCount++;
1298 WIN_UpdateWndPtr(&pChild,pChild->next);
1302 * Now that we have a list, go through that list again and send the destroy
1303 * message to those windows. We are using the HWND to retrieve the
1304 * WND pointer so we are effectively checking that all the kid windows are
1305 * still valid before sending the message.
1307 while (nKidCount>0)
1309 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1311 if (pChild!=NULL)
1313 WIN_SendDestroyMsg( pChild );
1314 WIN_ReleaseWndPtr(pChild);
1319 * Cleanup
1321 HeapFree(GetProcessHeap(), 0, pWndArray);
1322 WIN_CheckFocus(pWnd);
1324 else
1325 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1329 /***********************************************************************
1330 * DestroyWindow16 (USER.53)
1332 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1334 return DestroyWindow(hwnd);
1338 /***********************************************************************
1339 * DestroyWindow (USER32.135)
1341 BOOL WINAPI DestroyWindow( HWND hwnd )
1343 WND * wndPtr;
1344 BOOL retvalue;
1346 TRACE("(%04x)\n", hwnd);
1348 /* Initialization */
1350 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1351 if (wndPtr == pWndDesktop)
1353 retvalue = FALSE; /* Can't destroy desktop */
1354 goto end;
1357 /* Call hooks */
1359 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1361 retvalue = FALSE;
1362 goto end;
1365 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1367 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1368 /* FIXME: clean up palette - see "Internals" p.352 */
1371 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1372 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1374 /* Notify the parent window only */
1375 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1376 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1377 if( !IsWindow(hwnd) )
1379 retvalue = TRUE;
1380 goto end;
1384 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1386 /* Hide the window */
1388 if (wndPtr->dwStyle & WS_VISIBLE)
1390 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1391 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1392 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1393 if (!IsWindow(hwnd))
1395 retvalue = TRUE;
1396 goto end;
1400 /* Recursively destroy owned windows */
1402 if( !(wndPtr->dwStyle & WS_CHILD) )
1404 /* make sure top menu popup doesn't get destroyed */
1405 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1407 for (;;)
1409 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1410 while (siblingPtr)
1412 if (siblingPtr->owner == wndPtr)
1414 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1415 break;
1416 else
1417 siblingPtr->owner = NULL;
1419 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1421 if (siblingPtr)
1423 DestroyWindow( siblingPtr->hwndSelf );
1424 WIN_ReleaseWndPtr(siblingPtr);
1426 else break;
1429 if( !Options.managed || EVENT_CheckFocus() )
1430 WINPOS_ActivateOtherWindow(wndPtr);
1432 if( wndPtr->owner &&
1433 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1434 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1437 /* Send destroy messages */
1439 WIN_SendDestroyMsg( wndPtr );
1440 if (!IsWindow(hwnd))
1442 retvalue = TRUE;
1443 goto end;
1446 /* Unlink now so we won't bother with the children later on */
1448 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1450 /* Destroy the window storage */
1452 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1453 retvalue = TRUE;
1454 end:
1455 WIN_ReleaseWndPtr(wndPtr);
1456 return retvalue;
1460 /***********************************************************************
1461 * CloseWindow16 (USER.43)
1463 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1465 return CloseWindow( hwnd );
1469 /***********************************************************************
1470 * CloseWindow (USER32.56)
1472 BOOL WINAPI CloseWindow( HWND hwnd )
1474 WND * wndPtr = WIN_FindWndPtr( hwnd );
1475 BOOL retvalue;
1477 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1479 retvalue = FALSE;
1480 goto end;
1482 ShowWindow( hwnd, SW_MINIMIZE );
1483 retvalue = TRUE;
1484 end:
1485 WIN_ReleaseWndPtr(wndPtr);
1486 return retvalue;
1491 /***********************************************************************
1492 * OpenIcon16 (USER.44)
1494 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1496 return OpenIcon( hwnd );
1500 /***********************************************************************
1501 * OpenIcon (USER32.410)
1503 BOOL WINAPI OpenIcon( HWND hwnd )
1505 if (!IsIconic( hwnd )) return FALSE;
1506 ShowWindow( hwnd, SW_SHOWNORMAL );
1507 return TRUE;
1511 /***********************************************************************
1512 * WIN_FindWindow
1514 * Implementation of FindWindow() and FindWindowEx().
1516 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1517 LPCSTR title )
1519 WND *pWnd;
1520 HWND retvalue;
1522 if (child)
1524 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1525 if (parent)
1527 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1529 retvalue = 0;
1530 goto end;
1533 else if (pWnd->parent != pWndDesktop)
1535 retvalue = 0;
1536 goto end;
1538 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1540 else
1542 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1544 retvalue = 0;
1545 goto end;
1547 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1549 if (!pWnd)
1551 retvalue = 0;
1552 goto end;
1555 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1557 if (className && (pWnd->class->atomName != className))
1558 continue; /* Not the right class */
1560 /* Now check the title */
1562 if (!title)
1564 retvalue = pWnd->hwndSelf;
1565 goto end;
1567 if (pWnd->text && !strcmp( pWnd->text, title ))
1569 retvalue = pWnd->hwndSelf;
1570 goto end;
1573 retvalue = 0;
1574 end:
1575 WIN_ReleaseWndPtr(pWnd);
1576 return retvalue;
1581 /***********************************************************************
1582 * FindWindow16 (USER.50)
1584 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1586 return FindWindowA( className, title );
1590 /***********************************************************************
1591 * FindWindowEx16 (USER.427)
1593 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1595 return FindWindowExA( parent, child, className, title );
1599 /***********************************************************************
1600 * FindWindowA (USER32.198)
1602 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1604 HWND ret = FindWindowExA( 0, 0, className, title );
1605 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1606 return ret;
1610 /***********************************************************************
1611 * FindWindowExA (USER32.199)
1613 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1614 LPCSTR className, LPCSTR title )
1616 ATOM atom = 0;
1618 if (className)
1620 /* If the atom doesn't exist, then no class */
1621 /* with this name exists either. */
1622 if (!(atom = GlobalFindAtomA( className )))
1624 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1625 return 0;
1628 return WIN_FindWindow( parent, child, atom, title );
1632 /***********************************************************************
1633 * FindWindowExW (USER32.200)
1635 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1636 LPCWSTR className, LPCWSTR title )
1638 ATOM atom = 0;
1639 char *buffer;
1640 HWND hwnd;
1642 if (className)
1644 /* If the atom doesn't exist, then no class */
1645 /* with this name exists either. */
1646 if (!(atom = GlobalFindAtomW( className )))
1648 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1649 return 0;
1652 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1653 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1654 HeapFree( GetProcessHeap(), 0, buffer );
1655 return hwnd;
1659 /***********************************************************************
1660 * FindWindowW (USER32.201)
1662 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1664 return FindWindowExW( 0, 0, className, title );
1668 /**********************************************************************
1669 * WIN_GetDesktop
1670 * returns a locked pointer
1672 WND *WIN_GetDesktop(void)
1674 return WIN_LockWndPtr(pWndDesktop);
1676 /**********************************************************************
1677 * WIN_ReleaseDesktop
1678 * unlock the desktop pointer
1680 void WIN_ReleaseDesktop(void)
1682 WIN_ReleaseWndPtr(pWndDesktop);
1686 /**********************************************************************
1687 * GetDesktopWindow16 (USER.286)
1689 HWND16 WINAPI GetDesktopWindow16(void)
1691 return (HWND16)pWndDesktop->hwndSelf;
1695 /**********************************************************************
1696 * GetDesktopWindow (USER32.232)
1698 HWND WINAPI GetDesktopWindow(void)
1700 if (pWndDesktop) return pWndDesktop->hwndSelf;
1701 ERR( "You need the -desktop option when running with native USER\n" );
1702 ExitProcess(1);
1703 return 0;
1707 /**********************************************************************
1708 * GetDesktopHwnd (USER.278)
1710 * Exactly the same thing as GetDesktopWindow(), but not documented.
1711 * Don't ask me why...
1713 HWND16 WINAPI GetDesktopHwnd16(void)
1715 return (HWND16)pWndDesktop->hwndSelf;
1719 /*******************************************************************
1720 * EnableWindow16 (USER.34)
1722 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1724 return EnableWindow( hwnd, enable );
1728 /*******************************************************************
1729 * EnableWindow (USER32.172)
1731 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1733 WND *wndPtr;
1734 BOOL retvalue;
1736 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1738 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1739 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1741 /* Enable window */
1742 wndPtr->dwStyle &= ~WS_DISABLED;
1744 if( wndPtr->flags & WIN_NATIVE )
1745 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1747 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1748 retvalue = TRUE;
1749 goto end;
1751 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1753 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1755 /* Disable window */
1756 wndPtr->dwStyle |= WS_DISABLED;
1758 if( wndPtr->flags & WIN_NATIVE )
1759 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1761 if (hwnd == GetFocus())
1763 SetFocus( 0 ); /* A disabled window can't have the focus */
1765 if (hwnd == GetCapture())
1767 ReleaseCapture(); /* A disabled window can't capture the mouse */
1769 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1770 retvalue = FALSE;
1771 goto end;
1773 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1774 end:
1775 WIN_ReleaseWndPtr(wndPtr);
1776 return retvalue;
1780 /***********************************************************************
1781 * IsWindowEnabled16 (USER.35)
1783 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1785 return IsWindowEnabled(hWnd);
1789 /***********************************************************************
1790 * IsWindowEnabled (USER32.349)
1792 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1794 WND * wndPtr;
1795 BOOL retvalue;
1797 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1798 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1799 WIN_ReleaseWndPtr(wndPtr);
1800 return retvalue;
1805 /***********************************************************************
1806 * IsWindowUnicode (USER32.350)
1808 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1810 WND * wndPtr;
1811 BOOL retvalue;
1813 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1814 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1815 WIN_ReleaseWndPtr(wndPtr);
1816 return retvalue;
1820 /**********************************************************************
1821 * GetWindowWord16 (USER.133)
1823 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1825 return GetWindowWord( hwnd, offset );
1829 /**********************************************************************
1830 * GetWindowWord (USER32.314)
1832 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1834 WORD retvalue;
1835 WND * wndPtr = WIN_FindWndPtr( hwnd );
1836 if (!wndPtr) return 0;
1837 if (offset >= 0)
1839 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1841 WARN("Invalid offset %d\n", offset );
1842 retvalue = 0;
1843 goto end;
1845 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1846 goto end;
1848 switch(offset)
1850 case GWW_ID:
1851 if (HIWORD(wndPtr->wIDmenu))
1852 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1853 wndPtr->wIDmenu);
1854 retvalue = (WORD)wndPtr->wIDmenu;
1855 goto end;
1856 case GWW_HWNDPARENT:
1857 retvalue = GetParent(hwnd);
1858 goto end;
1859 case GWW_HINSTANCE:
1860 if (HIWORD(wndPtr->hInstance))
1861 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1862 wndPtr->hInstance);
1863 retvalue = (WORD)wndPtr->hInstance;
1864 goto end;
1865 default:
1866 WARN("Invalid offset %d\n", offset );
1867 retvalue = 0;
1868 goto end;
1870 end:
1871 WIN_ReleaseWndPtr(wndPtr);
1872 return retvalue;
1875 /**********************************************************************
1876 * SetWindowWord16 (USER.134)
1878 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1880 return SetWindowWord( hwnd, offset, newval );
1884 /**********************************************************************
1885 * SetWindowWord (USER32.524)
1887 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1889 WORD *ptr, retval;
1890 WND * wndPtr = WIN_FindWndPtr( hwnd );
1891 if (!wndPtr) return 0;
1892 if (offset >= 0)
1894 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1896 WARN("Invalid offset %d\n", offset );
1897 retval = 0;
1898 goto end;
1900 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1902 else switch(offset)
1904 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1905 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1906 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1907 goto end;
1908 default:
1909 WARN("Invalid offset %d\n", offset );
1910 retval = 0;
1911 goto end;
1913 retval = *ptr;
1914 *ptr = newval;
1915 end:
1916 WIN_ReleaseWndPtr(wndPtr);
1917 return retval;
1921 /**********************************************************************
1922 * WIN_GetWindowLong
1924 * Helper function for GetWindowLong().
1926 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1928 LONG retvalue;
1929 WND * wndPtr = WIN_FindWndPtr( hwnd );
1930 if (!wndPtr) return 0;
1931 if (offset >= 0)
1933 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1935 WARN("Invalid offset %d\n", offset );
1936 retvalue = 0;
1937 goto end;
1939 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1940 /* Special case for dialog window procedure */
1941 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1943 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1944 goto end;
1946 goto end;
1948 switch(offset)
1950 case GWL_USERDATA: retvalue = wndPtr->userdata;
1951 goto end;
1952 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1953 goto end;
1954 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1955 goto end;
1956 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1957 goto end;
1958 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1959 type );
1960 goto end;
1961 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1962 goto end;
1963 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1964 goto end;
1965 default:
1966 WARN("Unknown offset %d\n", offset );
1968 retvalue = 0;
1969 end:
1970 WIN_ReleaseWndPtr(wndPtr);
1971 return retvalue;
1975 /**********************************************************************
1976 * WIN_SetWindowLong
1978 * Helper function for SetWindowLong().
1980 * 0 is the failure code. However, in the case of failure SetLastError
1981 * must be set to distinguish between a 0 return value and a failure.
1983 * FIXME: The error values for SetLastError may not be right. Can
1984 * someone check with the real thing?
1986 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1987 WINDOWPROCTYPE type )
1989 LONG *ptr, retval;
1990 WND * wndPtr = WIN_FindWndPtr( hwnd );
1991 STYLESTRUCT style;
1993 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1995 if (!wndPtr)
1997 /* Is this the right error? */
1998 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1999 return 0;
2002 if (offset >= 0)
2004 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2006 WARN("Invalid offset %d\n", offset );
2008 /* Is this the right error? */
2009 SetLastError( ERROR_OUTOFMEMORY );
2011 retval = 0;
2012 goto end;
2014 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2015 /* Special case for dialog window procedure */
2016 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2018 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2019 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2020 type, WIN_PROC_WINDOW );
2021 goto end;
2024 else switch(offset)
2026 case GWL_ID:
2027 ptr = (DWORD*)&wndPtr->wIDmenu;
2028 break;
2029 case GWL_HINSTANCE:
2030 retval = SetWindowWord( hwnd, offset, newval );
2031 goto end;
2032 case GWL_WNDPROC:
2033 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2034 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2035 type, WIN_PROC_WINDOW );
2036 goto end;
2037 case GWL_STYLE:
2038 style.styleOld = wndPtr->dwStyle;
2039 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2040 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2042 if (wndPtr->flags & WIN_ISWIN32)
2043 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2044 wndPtr->dwStyle = style.styleNew;
2045 if (wndPtr->flags & WIN_ISWIN32)
2046 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2047 retval = style.styleOld;
2048 goto end;
2050 case GWL_USERDATA:
2051 ptr = &wndPtr->userdata;
2052 break;
2053 case GWL_EXSTYLE:
2054 style.styleOld = wndPtr->dwExStyle;
2055 style.styleNew = newval;
2056 if (wndPtr->flags & WIN_ISWIN32)
2057 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2058 wndPtr->dwExStyle = newval;
2059 if (wndPtr->flags & WIN_ISWIN32)
2060 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2061 retval = style.styleOld;
2062 goto end;
2064 default:
2065 WARN("Invalid offset %d\n", offset );
2067 /* Don't think this is right error but it should do */
2068 SetLastError( ERROR_OUTOFMEMORY );
2070 retval = 0;
2071 goto end;
2073 retval = *ptr;
2074 *ptr = newval;
2075 end:
2076 WIN_ReleaseWndPtr(wndPtr);
2077 return retval;
2081 /**********************************************************************
2082 * GetWindowLong16 (USER.135)
2084 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2086 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2090 /**********************************************************************
2091 * GetWindowLongA (USER32.305)
2093 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2095 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2099 /**********************************************************************
2100 * GetWindowLongW (USER32.306)
2102 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2104 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2108 /**********************************************************************
2109 * SetWindowLong16 (USER.136)
2111 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2113 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2117 /**********************************************************************
2118 * SetWindowLongA (USER32.517)
2120 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2122 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2126 /**********************************************************************
2127 * SetWindowLongW (USER32.518) Set window attribute
2129 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2130 * value in a window's extra memory.
2132 * The _hwnd_ parameter specifies the window. is the handle to a
2133 * window that has extra memory. The _newval_ parameter contains the
2134 * new attribute or extra memory value. If positive, the _offset_
2135 * parameter is the byte-addressed location in the window's extra
2136 * memory to set. If negative, _offset_ specifies the window
2137 * attribute to set, and should be one of the following values:
2139 * GWL_EXSTYLE The window's extended window style
2141 * GWL_STYLE The window's window style.
2143 * GWL_WNDPROC Pointer to the window's window procedure.
2145 * GWL_HINSTANCE The window's pplication instance handle.
2147 * GWL_ID The window's identifier.
2149 * GWL_USERDATA The window's user-specified data.
2151 * If the window is a dialog box, the _offset_ parameter can be one of
2152 * the following values:
2154 * DWL_DLGPROC The address of the window's dialog box procedure.
2156 * DWL_MSGRESULT The return value of a message
2157 * that the dialog box procedure processed.
2159 * DWL_USER Application specific information.
2161 * RETURNS
2163 * If successful, returns the previous value located at _offset_. Otherwise,
2164 * returns 0.
2166 * NOTES
2168 * Extra memory for a window class is specified by a nonzero cbWndExtra
2169 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2170 * time of class creation.
2172 * Using GWL_WNDPROC to set a new window procedure effectively creates
2173 * a window subclass. Use CallWindowProc() in the new windows procedure
2174 * to pass messages to the superclass's window procedure.
2176 * The user data is reserved for use by the application which created
2177 * the window.
2179 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2180 * instead, call the EnableWindow() function to change the window's
2181 * disabled state.
2183 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2184 * SetParent() instead.
2186 * Win95:
2187 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2188 * it sends WM_STYLECHANGING before changing the settings
2189 * and WM_STYLECHANGED afterwards.
2190 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2192 * BUGS
2194 * GWL_STYLE does not dispatch WM_STYLE... messages.
2196 * CONFORMANCE
2198 * ECMA-234, Win32
2201 LONG WINAPI SetWindowLongW(
2202 HWND hwnd, /* window to alter */
2203 INT offset, /* offset, in bytes, of location to alter */
2204 LONG newval /* new value of location */
2206 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2210 /*******************************************************************
2211 * GetWindowText16 (USER.36)
2213 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2215 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2219 /*******************************************************************
2220 * GetWindowTextA (USER32.309)
2222 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2224 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2225 (LPARAM)lpString );
2228 /*******************************************************************
2229 * InternalGetWindowText (USER32.326)
2231 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2233 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2234 return GetWindowTextW(hwnd,lpString,nMaxCount);
2238 /*******************************************************************
2239 * GetWindowTextW (USER32.312)
2241 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2243 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2244 (LPARAM)lpString );
2248 /*******************************************************************
2249 * SetWindowText16 (USER.37)
2251 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2253 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2257 /*******************************************************************
2258 * SetWindowTextA (USER32.521)
2260 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2262 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2266 /*******************************************************************
2267 * SetWindowTextW (USER32.523)
2269 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2271 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2275 /*******************************************************************
2276 * GetWindowTextLength16 (USER.38)
2278 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2280 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2284 /*******************************************************************
2285 * GetWindowTextLengthA (USER32.310)
2287 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2289 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2292 /*******************************************************************
2293 * GetWindowTextLengthW (USER32.311)
2295 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2297 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2301 /*******************************************************************
2302 * IsWindow16 (USER.47)
2304 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2306 CURRENT_STACK16->es = USER_HeapSel;
2307 return IsWindow( hwnd );
2311 /*******************************************************************
2312 * IsWindow (USER32.348)
2314 BOOL WINAPI IsWindow( HWND hwnd )
2316 WND * wndPtr;
2317 BOOL retvalue;
2319 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2320 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2321 WIN_ReleaseWndPtr(wndPtr);
2322 return retvalue;
2327 /*****************************************************************
2328 * GetParent16 (USER.46)
2330 HWND16 WINAPI GetParent16( HWND16 hwnd )
2332 return (HWND16)GetParent( hwnd );
2336 /*****************************************************************
2337 * GetParent (USER32.278)
2339 HWND WINAPI GetParent( HWND hwnd )
2341 WND *wndPtr;
2342 HWND retvalue = 0;
2344 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2345 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2346 goto end;
2348 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2349 if (wndPtr)
2350 retvalue = wndPtr->hwndSelf;
2352 end:
2353 WIN_ReleaseWndPtr(wndPtr);
2354 return retvalue;
2358 /*****************************************************************
2359 * WIN_GetTopParent
2361 * Get the top-level parent for a child window.
2362 * returns a locked pointer
2364 WND* WIN_GetTopParentPtr( WND* pWnd )
2366 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2368 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2370 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2372 return tmpWnd;
2375 /*****************************************************************
2376 * WIN_GetTopParent
2378 * Get the top-level parent for a child window.
2380 HWND WIN_GetTopParent( HWND hwnd )
2382 HWND retvalue;
2383 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2384 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2386 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2387 WIN_ReleaseWndPtr(tmpPtr);
2388 WIN_ReleaseWndPtr(wndPtr);
2389 return retvalue;
2393 /*****************************************************************
2394 * SetParent16 (USER.233)
2396 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2398 return SetParent( hwndChild, hwndNewParent );
2402 /*****************************************************************
2403 * SetParent (USER32.495)
2405 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2407 WND *wndPtr;
2408 DWORD dwStyle;
2409 WND *pWndNewParent;
2410 WND *pWndOldParent;
2411 HWND retvalue;
2414 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2416 dwStyle = wndPtr->dwStyle;
2418 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2419 : WIN_LockWndPtr(pWndDesktop);
2421 /* Windows hides the window first, then shows it again
2422 * including the WM_SHOWWINDOW messages and all */
2423 if (dwStyle & WS_VISIBLE)
2424 ShowWindow( hwndChild, SW_HIDE );
2426 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2428 /* SetParent additionally needs to make hwndChild the topmost window
2429 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2430 WM_WINDOWPOSCHANGED notification messages.
2432 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2433 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2434 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2435 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2437 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2439 WIN_ReleaseWndPtr(pWndOldParent);
2440 WIN_ReleaseWndPtr(pWndNewParent);
2441 WIN_ReleaseWndPtr(wndPtr);
2443 return retvalue;
2447 /*******************************************************************
2448 * IsChild16 (USER.48)
2450 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2452 return IsChild(parent,child);
2456 /*******************************************************************
2457 * IsChild (USER32.339)
2459 BOOL WINAPI IsChild( HWND parent, HWND child )
2461 WND * wndPtr = WIN_FindWndPtr( child );
2462 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2464 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2465 if (wndPtr->hwndSelf == parent)
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return TRUE;
2471 WIN_ReleaseWndPtr(wndPtr);
2472 return FALSE;
2476 /***********************************************************************
2477 * IsWindowVisible16 (USER.49)
2479 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2481 return IsWindowVisible(hwnd);
2485 /***********************************************************************
2486 * IsWindowVisible (USER32.351)
2488 BOOL WINAPI IsWindowVisible( HWND hwnd )
2490 BOOL retval;
2491 WND *wndPtr = WIN_FindWndPtr( hwnd );
2492 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2494 if (!(wndPtr->dwStyle & WS_VISIBLE))
2496 WIN_ReleaseWndPtr(wndPtr);
2497 return FALSE;
2499 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2501 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2502 WIN_ReleaseWndPtr(wndPtr);
2503 return retval;
2508 /***********************************************************************
2509 * WIN_IsWindowDrawable
2511 * hwnd is drawable when it is visible, all parents are not
2512 * minimized, and it is itself not minimized unless we are
2513 * trying to draw its default class icon.
2515 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2517 if( (wnd->dwStyle & WS_MINIMIZE &&
2518 icon && wnd->class->hIcon) ||
2519 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2520 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2521 if( wnd->dwStyle & WS_MINIMIZE ||
2522 !(wnd->dwStyle & WS_VISIBLE) ) break;
2523 return (wnd == NULL);
2527 /*******************************************************************
2528 * GetTopWindow16 (USER.229)
2530 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2532 return GetTopWindow(hwnd);
2536 /*******************************************************************
2537 * GetTopWindow (USER.229)
2539 HWND WINAPI GetTopWindow( HWND hwnd )
2541 HWND retval = 0;
2542 WND * wndPtr = (hwnd) ?
2543 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2545 if (wndPtr && wndPtr->child)
2546 retval = wndPtr->child->hwndSelf;
2548 WIN_ReleaseWndPtr(wndPtr);
2549 return retval;
2553 /*******************************************************************
2554 * GetWindow16 (USER.262)
2556 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2558 return GetWindow( hwnd,rel );
2562 /*******************************************************************
2563 * GetWindow (USER32.302)
2565 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2567 HWND retval;
2569 WND * wndPtr = WIN_FindWndPtr( hwnd );
2570 if (!wndPtr) return 0;
2571 switch(rel)
2573 case GW_HWNDFIRST:
2574 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2575 goto end;
2577 case GW_HWNDLAST:
2578 if (!wndPtr->parent)
2580 retval = 0; /* Desktop window */
2581 goto end;
2583 while (wndPtr->next)
2585 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2587 retval = wndPtr->hwndSelf;
2588 goto end;
2590 case GW_HWNDNEXT:
2591 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2592 goto end;
2594 case GW_HWNDPREV:
2595 if (!wndPtr->parent)
2597 retval = 0; /* Desktop window */
2598 goto end;
2600 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2601 if (wndPtr->hwndSelf == hwnd)
2603 retval = 0; /* First in list */
2604 goto end;
2606 while (wndPtr->next)
2608 if (wndPtr->next->hwndSelf == hwnd)
2610 retval = wndPtr->hwndSelf;
2611 goto end;
2613 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2615 retval = 0;
2616 goto end;
2618 case GW_OWNER:
2619 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2620 goto end;
2622 case GW_CHILD:
2623 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2624 goto end;
2626 retval = 0;
2627 end:
2628 WIN_ReleaseWndPtr(wndPtr);
2629 return retval;
2633 /*******************************************************************
2634 * GetNextWindow16 (USER.230)
2636 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2638 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2639 return GetWindow16( hwnd, flag );
2642 /*******************************************************************
2643 * ShowOwnedPopups16 (USER.265)
2645 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2647 ShowOwnedPopups( owner, fShow );
2651 /*******************************************************************
2652 * ShowOwnedPopups (USER32.531)
2654 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2656 UINT totalChild=0, count=0;
2658 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2660 if (!pWnd) return TRUE;
2662 for (; count < totalChild; count++)
2664 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2666 if (fShow)
2668 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2670 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2671 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2674 else
2676 if (IsWindowVisible(pWnd[count]->hwndSelf))
2678 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2679 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2685 WIN_ReleaseDesktop();
2686 WIN_ReleaseWinArray(pWnd);
2687 return TRUE;
2691 /*******************************************************************
2692 * GetLastActivePopup16 (USER.287)
2694 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2696 return GetLastActivePopup( hwnd );
2699 /*******************************************************************
2700 * GetLastActivePopup (USER32.256)
2702 HWND WINAPI GetLastActivePopup( HWND hwnd )
2704 HWND retval;
2705 WND *wndPtr =WIN_FindWndPtr(hwnd);
2706 if (!wndPtr) return hwnd;
2707 retval = wndPtr->hwndLastActive;
2708 WIN_ReleaseWndPtr(wndPtr);
2709 return retval;
2713 /*******************************************************************
2714 * WIN_BuildWinArray
2716 * Build an array of pointers to the children of a given window.
2717 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2718 * when no windows are found.
2720 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2722 /* Future: this function will lock all windows associated with this array */
2724 WND **list, **ppWnd;
2725 WND *pWnd;
2726 UINT count = 0, skipOwned, skipHidden;
2727 DWORD skipFlags;
2729 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2730 skipOwned = bwaFlags & BWA_SKIPOWNED;
2731 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2732 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2734 /* First count the windows */
2736 if (!wndPtr)
2737 wndPtr = WIN_GetDesktop();
2739 pWnd = WIN_LockWndPtr(wndPtr->child);
2740 while (pWnd)
2742 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2743 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2744 count++;
2745 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2748 if( count )
2750 /* Now build the list of all windows */
2752 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2754 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2756 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2757 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2759 *ppWnd++ = pWnd;
2760 count++;
2763 WIN_ReleaseWndPtr(pWnd);
2764 *ppWnd = NULL;
2766 else count = 0;
2767 } else list = NULL;
2769 if( pTotal ) *pTotal = count;
2770 return list;
2772 /*******************************************************************
2773 * WIN_ReleaseWinArray
2775 void WIN_ReleaseWinArray(WND **wndArray)
2777 /* Future: this function will also unlock all windows associated with wndArray */
2778 HeapFree( GetProcessHeap(), 0, wndArray );
2782 /*******************************************************************
2783 * EnumWindows (USER32.193)
2785 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2787 WND **list, **ppWnd;
2789 /* We have to build a list of all windows first, to avoid */
2790 /* unpleasant side-effects, for instance if the callback */
2791 /* function changes the Z-order of the windows. */
2793 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2795 WIN_ReleaseDesktop();
2796 return FALSE;
2799 /* Now call the callback function for every window */
2801 for (ppWnd = list; *ppWnd; ppWnd++)
2803 LRESULT lpEnumFuncRetval;
2804 int iWndsLocks = 0;
2805 /* Make sure that the window still exists */
2806 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2808 /* To avoid any deadlocks, all the locks on the windows
2809 structures must be suspended before the control
2810 is passed to the application */
2811 iWndsLocks = WIN_SuspendWndsLock();
2812 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2813 WIN_RestoreWndsLock(iWndsLocks);
2815 if (!lpEnumFuncRetval) break;
2817 WIN_ReleaseWinArray(list);
2818 WIN_ReleaseDesktop();
2819 return TRUE;
2823 /**********************************************************************
2824 * EnumTaskWindows16 (USER.225)
2826 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2827 LPARAM lParam )
2829 WND **list, **ppWnd;
2831 /* This function is the same as EnumWindows(), */
2832 /* except for an added check on the window's task. */
2834 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2836 WIN_ReleaseDesktop();
2837 return FALSE;
2840 /* Now call the callback function for every window */
2842 for (ppWnd = list; *ppWnd; ppWnd++)
2844 LRESULT funcRetval;
2845 int iWndsLocks = 0;
2846 /* Make sure that the window still exists */
2847 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2848 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2850 /* To avoid any deadlocks, all the locks on the windows
2851 structures must be suspended before the control
2852 is passed to the application */
2853 iWndsLocks = WIN_SuspendWndsLock();
2854 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2855 WIN_RestoreWndsLock(iWndsLocks);
2857 if (!funcRetval) break;
2859 WIN_ReleaseWinArray(list);
2860 WIN_ReleaseDesktop();
2861 return TRUE;
2865 /**********************************************************************
2866 * EnumThreadWindows (USER32.190)
2868 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2870 TEB *teb = THREAD_IdToTEB(id);
2872 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2876 /**********************************************************************
2877 * WIN_EnumChildWindows
2879 * Helper function for EnumChildWindows().
2881 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2883 WND **childList;
2884 BOOL16 ret = FALSE;
2886 for ( ; *ppWnd; ppWnd++)
2888 int iWndsLocks = 0;
2890 /* Make sure that the window still exists */
2891 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2892 /* Build children list first */
2893 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2895 /* To avoid any deadlocks, all the locks on the windows
2896 structures must be suspended before the control
2897 is passed to the application */
2898 iWndsLocks = WIN_SuspendWndsLock();
2899 ret = func( (*ppWnd)->hwndSelf, lParam );
2900 WIN_RestoreWndsLock(iWndsLocks);
2902 if (childList)
2904 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2905 WIN_ReleaseWinArray(childList);
2907 if (!ret) return FALSE;
2909 return TRUE;
2913 /**********************************************************************
2914 * EnumChildWindows (USER32.178)
2916 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2917 LPARAM lParam )
2919 WND **list, *pParent;
2921 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2922 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2924 WIN_ReleaseWndPtr(pParent);
2925 return FALSE;
2927 WIN_EnumChildWindows( list, func, lParam );
2928 WIN_ReleaseWinArray(list);
2929 WIN_ReleaseWndPtr(pParent);
2930 return TRUE;
2934 /*******************************************************************
2935 * AnyPopup16 (USER.52)
2937 BOOL16 WINAPI AnyPopup16(void)
2939 return AnyPopup();
2943 /*******************************************************************
2944 * AnyPopup (USER32.4)
2946 BOOL WINAPI AnyPopup(void)
2948 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2949 BOOL retvalue;
2951 while (wndPtr)
2953 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2955 retvalue = TRUE;
2956 goto end;
2958 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2960 retvalue = FALSE;
2961 end:
2962 WIN_ReleaseWndPtr(wndPtr);
2963 return retvalue;
2967 /*******************************************************************
2968 * FlashWindow16 (USER.105)
2970 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2972 return FlashWindow( hWnd, bInvert );
2976 /*******************************************************************
2977 * FlashWindow (USER32.202)
2979 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2981 WND *wndPtr = WIN_FindWndPtr(hWnd);
2983 TRACE("%04x\n", hWnd);
2985 if (!wndPtr) return FALSE;
2987 if (wndPtr->dwStyle & WS_MINIMIZE)
2989 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2991 HDC hDC = GetDC(hWnd);
2993 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2994 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2996 ReleaseDC( hWnd, hDC );
2997 wndPtr->flags |= WIN_NCACTIVATED;
2999 else
3001 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3002 RDW_UPDATENOW | RDW_FRAME, 0 );
3003 wndPtr->flags &= ~WIN_NCACTIVATED;
3005 WIN_ReleaseWndPtr(wndPtr);
3006 return TRUE;
3008 else
3010 WPARAM16 wparam;
3011 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3012 else wparam = (hWnd == GetActiveWindow());
3014 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3015 WIN_ReleaseWndPtr(wndPtr);
3016 return wparam;
3021 /*******************************************************************
3022 * SetSysModalWindow16 (USER.188)
3024 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3026 HWND hWndOldModal = hwndSysModal;
3027 hwndSysModal = hWnd;
3028 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3029 return hWndOldModal;
3033 /*******************************************************************
3034 * GetSysModalWindow16 (USER.52)
3036 HWND16 WINAPI GetSysModalWindow16(void)
3038 return hwndSysModal;
3042 /*******************************************************************
3043 * GetWindowContextHelpId (USER32.303)
3045 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3047 DWORD retval;
3048 WND *wnd = WIN_FindWndPtr( hwnd );
3049 if (!wnd) return 0;
3050 retval = wnd->helpContext;
3051 WIN_ReleaseWndPtr(wnd);
3052 return retval;
3056 /*******************************************************************
3057 * SetWindowContextHelpId (USER32.515)
3059 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3061 WND *wnd = WIN_FindWndPtr( hwnd );
3062 if (!wnd) return FALSE;
3063 wnd->helpContext = id;
3064 WIN_ReleaseWndPtr(wnd);
3065 return TRUE;
3069 /*******************************************************************
3070 * DRAG_QueryUpdate
3072 * recursively find a child that contains spDragInfo->pt point
3073 * and send WM_QUERYDROPOBJECT
3075 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3077 BOOL16 wParam, bResult = 0;
3078 POINT pt;
3079 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3080 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3081 RECT tempRect;
3083 if( !ptrQueryWnd || !ptrDragInfo )
3084 goto end;
3086 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3088 GetWindowRect(hQueryWnd,&tempRect);
3090 if( !PtInRect(&tempRect,pt) ||
3091 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3092 goto end;
3094 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3096 tempRect = ptrQueryWnd->rectClient;
3097 if(ptrQueryWnd->dwStyle & WS_CHILD)
3098 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3099 (LPPOINT)&tempRect, 2 );
3101 if (PtInRect( &tempRect, pt))
3103 wParam = 0;
3105 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3107 if( ptrWnd->dwStyle & WS_VISIBLE )
3109 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3110 if (PtInRect( &tempRect, pt )) break;
3114 if(ptrWnd)
3116 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3117 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3118 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3119 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3120 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3122 WIN_ReleaseWndPtr(ptrWnd);
3125 if(bResult)
3126 goto end;
3128 else wParam = 1;
3130 else wParam = 1;
3132 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3134 ptrDragInfo->hScope = hQueryWnd;
3136 bResult = ( bNoSend )
3137 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3138 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3139 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3140 if( !bResult )
3141 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3143 end:
3144 WIN_ReleaseWndPtr(ptrQueryWnd);
3145 return bResult;
3149 /*******************************************************************
3150 * DragDetect (USER.465)
3152 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3154 POINT pt32;
3155 CONV_POINT16TO32( &pt, &pt32 );
3156 return DragDetect( hWnd, pt32 );
3159 /*******************************************************************
3160 * DragDetect (USER32.151)
3162 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3164 MSG16 msg;
3165 RECT16 rect;
3167 rect.left = pt.x - wDragWidth;
3168 rect.right = pt.x + wDragWidth;
3170 rect.top = pt.y - wDragHeight;
3171 rect.bottom = pt.y + wDragHeight;
3173 SetCapture(hWnd);
3175 while(1)
3177 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3179 if( msg.message == WM_LBUTTONUP )
3181 ReleaseCapture();
3182 return 0;
3184 if( msg.message == WM_MOUSEMOVE )
3186 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3188 ReleaseCapture();
3189 return 1;
3193 WaitMessage();
3195 return 0;
3198 /******************************************************************************
3199 * DragObject16 (USER.464)
3201 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3202 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3204 MSG16 msg;
3205 LPDRAGINFO lpDragInfo;
3206 SEGPTR spDragInfo;
3207 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3208 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3209 WND *wndPtr = WIN_FindWndPtr(hWnd);
3210 HCURSOR16 hCurrentCursor = 0;
3211 HWND16 hCurrentWnd = 0;
3213 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3214 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3216 if( !lpDragInfo || !spDragInfo )
3218 WIN_ReleaseWndPtr(wndPtr);
3219 return 0L;
3222 hBummer = LoadCursor16(0, IDC_BUMMER16);
3224 if( !hBummer || !wndPtr )
3226 GlobalFree16(hDragInfo);
3227 WIN_ReleaseWndPtr(wndPtr);
3228 return 0L;
3231 if(hCursor)
3233 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3235 GlobalFree16(hDragInfo);
3236 WIN_ReleaseWndPtr(wndPtr);
3237 return 0L;
3240 if( hDragCursor == hCursor ) hDragCursor = 0;
3241 else hCursor = hDragCursor;
3243 hOldCursor = SetCursor(hDragCursor);
3246 lpDragInfo->hWnd = hWnd;
3247 lpDragInfo->hScope = 0;
3248 lpDragInfo->wFlags = wObj;
3249 lpDragInfo->hList = szList; /* near pointer! */
3250 lpDragInfo->hOfStruct = hOfStruct;
3251 lpDragInfo->l = 0L;
3253 SetCapture(hWnd);
3254 ShowCursor( TRUE );
3258 do{ WaitMessage(); }
3259 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3261 *(lpDragInfo+1) = *lpDragInfo;
3263 lpDragInfo->pt = msg.pt;
3265 /* update DRAGINFO struct */
3266 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3268 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3269 hCurrentCursor = hCursor;
3270 else
3272 hCurrentCursor = hBummer;
3273 lpDragInfo->hScope = 0;
3275 if( hCurrentCursor )
3276 SetCursor(hCurrentCursor);
3278 /* send WM_DRAGLOOP */
3279 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3280 (LPARAM) spDragInfo );
3281 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3282 if( hCurrentWnd != lpDragInfo->hScope )
3284 if( hCurrentWnd )
3285 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3286 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3287 HIWORD(spDragInfo)) );
3288 hCurrentWnd = lpDragInfo->hScope;
3289 if( hCurrentWnd )
3290 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3292 else
3293 if( hCurrentWnd )
3294 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3296 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3298 ReleaseCapture();
3299 ShowCursor( FALSE );
3301 if( hCursor )
3303 SetCursor( hOldCursor );
3304 if (hDragCursor) DestroyCursor( hDragCursor );
3307 if( hCurrentCursor != hBummer )
3308 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3309 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3310 else
3311 msg.lParam = 0;
3312 GlobalFree16(hDragInfo);
3313 WIN_ReleaseWndPtr(wndPtr);
3315 return (DWORD)(msg.lParam);