Speedup enhancement for the 8->16 and 8->32 copy loop hotspots,
[wine.git] / windows / win.c
blob4922297207715e53fa8c350e8131ccf2d104137e
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.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 "cursoricon.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "debugtools.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.h"
35 #include "desktop.h"
36 #include "syslevel.h"
38 DECLARE_DEBUG_CHANNEL(msg)
39 DECLARE_DEBUG_CHANNEL(win)
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_(win)("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_(win)("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_(win)("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE_(win)("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_(win)("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 GlobalGetAtomName16(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_(win)("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_(win)("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_(win)("%04x\n", wndPtr->hwndSelf );
443 #ifdef CONFIG_IPC
444 if (main_block)
445 DDE_DestroyWindow(wndPtr->hwndSelf);
446 #endif /* CONFIG_IPC */
448 /* free child windows */
449 WIN_LockWndPtr(wndPtr->child);
450 while ((pWnd = wndPtr->child))
452 wndPtr->child = WIN_DestroyWindow( pWnd );
453 WIN_ReleaseWndPtr(pWnd);
457 * Clear the update region to make sure no WM_PAINT messages will be
458 * generated for this window while processing the WM_NCDESTROY.
460 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
462 if (wndPtr->hrgnUpdate > 1)
463 DeleteObject( wndPtr->hrgnUpdate );
465 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
467 wndPtr->hrgnUpdate = 0;
471 * Send the WM_NCDESTROY to the window being destroyed.
473 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
475 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
477 WINPOS_CheckInternalPos( wndPtr );
478 if( hwnd == GetCapture()) ReleaseCapture();
480 /* free resources associated with the window */
482 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
483 PROPERTY_RemoveWindowProps( wndPtr );
485 wndPtr->dwMagic = 0; /* Mark it as invalid */
487 /* toss stale messages from the queue */
489 if( wndPtr->hmemTaskQ )
491 BOOL bPostQuit = FALSE;
492 WPARAM wQuitParam = 0;
493 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
494 QMSG *qmsg;
496 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
498 if( qmsg->msg.message == WM_QUIT )
500 bPostQuit = TRUE;
501 wQuitParam = qmsg->msg.wParam;
503 QUEUE_RemoveMsg(msgQ, qmsg);
506 QUEUE_Unlock(msgQ);
508 /* repost WM_QUIT to make sure this app exits its message loop */
509 if( bPostQuit ) PostQuitMessage(wQuitParam);
510 wndPtr->hmemTaskQ = 0;
513 if (!(wndPtr->dwStyle & WS_CHILD))
514 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
515 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
516 wndPtr->pDriver->pDestroyWindow( wndPtr );
517 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
518 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
519 wndPtr->class->cWindows--;
520 wndPtr->class = NULL;
522 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
524 wndPtr->pDriver->pFinalize(wndPtr);
526 return pWnd;
529 /***********************************************************************
530 * WIN_ResetQueueWindows
532 * Reset the queue of all the children of a given window.
533 * Return TRUE if something was done.
535 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
537 BOOL ret = FALSE;
539 if (hNew) /* Set a new queue */
541 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
543 if (wnd->hmemTaskQ == hQueue)
545 wnd->hmemTaskQ = hNew;
546 ret = TRUE;
548 if (wnd->child)
550 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
554 else /* Queue is being destroyed */
556 while (wnd->child)
558 WND *tmp = WIN_LockWndPtr(wnd->child);
559 WND *tmp2;
560 ret = FALSE;
561 while (tmp)
563 if (tmp->hmemTaskQ == hQueue)
565 DestroyWindow( tmp->hwndSelf );
566 ret = TRUE;
567 break;
569 tmp2 = WIN_LockWndPtr(tmp->child);
570 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
571 ret = TRUE;
572 else
574 WIN_UpdateWndPtr(&tmp,tmp->next);
576 WIN_ReleaseWndPtr(tmp2);
578 WIN_ReleaseWndPtr(tmp);
579 if (!ret) break;
582 return ret;
585 /***********************************************************************
586 * WIN_CreateDesktopWindow
588 * Create the desktop window.
590 BOOL WIN_CreateDesktopWindow(void)
592 CLASS *class;
593 HWND hwndDesktop;
594 DESKTOP *pDesktop;
596 TRACE_(win)("Creating desktop window\n");
599 if (!ICONTITLE_Init() ||
600 !WINPOS_CreateInternalPosAtom() ||
601 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
602 return FALSE;
604 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
605 if (!hwndDesktop) return FALSE;
606 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
608 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
609 pDesktop->pDriver = DESKTOP_Driver;
610 pWndDesktop->pDriver = WND_Driver;
612 pDesktop->pDriver->pInitialize(pDesktop);
613 pWndDesktop->pDriver->pInitialize(pWndDesktop);
615 pWndDesktop->next = NULL;
616 pWndDesktop->child = NULL;
617 pWndDesktop->parent = NULL;
618 pWndDesktop->owner = NULL;
619 pWndDesktop->class = class;
620 pWndDesktop->dwMagic = WND_MAGIC;
621 pWndDesktop->hwndSelf = hwndDesktop;
622 pWndDesktop->hInstance = 0;
623 pWndDesktop->rectWindow.left = 0;
624 pWndDesktop->rectWindow.top = 0;
625 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
626 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
627 pWndDesktop->rectClient = pWndDesktop->rectWindow;
628 pWndDesktop->text = NULL;
629 pWndDesktop->hmemTaskQ = GetFastQueue16();
630 pWndDesktop->hrgnUpdate = 0;
631 pWndDesktop->hwndLastActive = hwndDesktop;
632 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
633 WS_CLIPSIBLINGS;
634 pWndDesktop->dwExStyle = 0;
635 pWndDesktop->dce = NULL;
636 pWndDesktop->pVScroll = NULL;
637 pWndDesktop->pHScroll = NULL;
638 pWndDesktop->pProp = NULL;
639 pWndDesktop->wIDmenu = 0;
640 pWndDesktop->helpContext = 0;
641 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
642 pWndDesktop->hSysMenu = 0;
643 pWndDesktop->userdata = 0;
644 pWndDesktop->winproc = (WNDPROC16)class->winproc;
645 pWndDesktop->irefCount = 0;
647 /* FIXME: How do we know if it should be Unicode or not */
648 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
649 return FALSE;
651 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
652 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
653 return TRUE;
657 /***********************************************************************
658 * WIN_CreateWindowEx
660 * Implementation of CreateWindowEx().
662 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
663 BOOL win32, BOOL unicode )
665 CLASS *classPtr;
666 WND *wndPtr;
667 HWND retvalue;
668 HWND16 hwnd, hwndLinkAfter;
669 POINT maxSize, maxPos, minTrack, maxTrack;
670 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
671 char buffer[256];
673 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
674 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
675 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
676 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
677 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
679 /* Find the parent window */
681 if (cs->hwndParent)
683 /* Make sure parent is valid */
684 if (!IsWindow( cs->hwndParent ))
686 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
687 return 0;
689 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
690 WARN_(win)("No parent for child window\n" );
691 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
694 /* Find the window class */
695 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
697 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
698 WARN_(win)("Bad class '%s'\n", buffer );
699 return 0;
702 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
703 * with an atom as the class name, put some programs expect to have a *REAL* string in
704 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
706 if ( !HIWORD(cs->lpszClass) ) {
707 if (unicode) {
708 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
709 } else {
710 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
712 cs->lpszClass = buffer;
715 /* Fix the coordinates */
717 if (cs->x == CW_USEDEFAULT)
719 PDB *pdb = PROCESS_Current();
720 if ( !(cs->style & (WS_CHILD | WS_POPUP))
721 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
723 cs->x = pdb->env_db->startup_info->dwX;
724 cs->y = pdb->env_db->startup_info->dwY;
726 else
728 cs->x = 0;
729 cs->y = 0;
732 if (cs->cx == CW_USEDEFAULT)
734 PDB *pdb = PROCESS_Current();
735 if ( !(cs->style & (WS_CHILD | WS_POPUP))
736 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
738 cs->cx = pdb->env_db->startup_info->dwXSize;
739 cs->cy = pdb->env_db->startup_info->dwYSize;
741 else
743 cs->cx = 600; /* FIXME */
744 cs->cy = 400;
748 /* Create the window structure */
750 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
751 - sizeof(wndPtr->wExtra) )))
753 TRACE_(win)("out of memory\n" );
754 return 0;
757 /* Fill the window structure */
759 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
760 wndPtr->next = NULL;
761 wndPtr->child = NULL;
763 if ((cs->style & WS_CHILD) && cs->hwndParent)
765 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
766 wndPtr->owner = NULL;
767 WIN_ReleaseWndPtr(wndPtr->parent);
769 else
771 wndPtr->parent = pWndDesktop;
772 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
773 wndPtr->owner = NULL;
774 else
776 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
777 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
778 WIN_ReleaseWndPtr(wndPtr->owner);
779 WIN_ReleaseWndPtr(tmpWnd);
783 wndPtr->pDriver = wndPtr->parent->pDriver;
784 wndPtr->pDriver->pInitialize(wndPtr);
786 wndPtr->class = classPtr;
787 wndPtr->winproc = classPtr->winproc;
788 wndPtr->dwMagic = WND_MAGIC;
789 wndPtr->hwndSelf = hwnd;
790 wndPtr->hInstance = cs->hInstance;
791 wndPtr->text = NULL;
792 wndPtr->hmemTaskQ = GetFastQueue16();
793 wndPtr->hrgnUpdate = 0;
794 wndPtr->hwndLastActive = hwnd;
795 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
796 wndPtr->dwExStyle = cs->dwExStyle;
797 wndPtr->wIDmenu = 0;
798 wndPtr->helpContext = 0;
799 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
800 wndPtr->pVScroll = NULL;
801 wndPtr->pHScroll = NULL;
802 wndPtr->pProp = NULL;
803 wndPtr->userdata = 0;
804 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
805 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
806 wndPtr->irefCount = 1;
808 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
810 /* Call the WH_CBT hook */
812 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
813 ? HWND_BOTTOM : HWND_TOP;
815 if (HOOK_IsHooked( WH_CBT ))
817 CBT_CREATEWNDA cbtc;
818 LRESULT ret;
820 cbtc.lpcs = cs;
821 cbtc.hwndInsertAfter = hwndLinkAfter;
822 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
823 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
824 if (ret)
826 TRACE_(win)("CBT-hook returned 0\n");
827 wndPtr->pDriver->pFinalize(wndPtr);
828 USER_HEAP_FREE( hwnd );
829 retvalue = 0;
830 goto end;
834 /* Increment class window counter */
836 classPtr->cWindows++;
838 /* Correct the window style */
840 if (!(cs->style & WS_CHILD))
842 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
843 if (!(cs->style & WS_POPUP))
845 wndPtr->dwStyle |= WS_CAPTION;
846 wndPtr->flags |= WIN_NEED_SIZE;
849 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
851 /* Get class or window DC if needed */
853 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
854 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
855 else wndPtr->dce = NULL;
857 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
859 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
861 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
862 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
863 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
864 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
865 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
868 if(cs->style & WS_CHILD)
870 if(cs->cx < 0) cs->cx = 0;
871 if(cs->cy < 0) cs->cy = 0;
873 else
875 if (cs->cx <= 0) cs->cx = 1;
876 if (cs->cy <= 0) cs->cy = 1;
879 wndPtr->rectWindow.left = cs->x;
880 wndPtr->rectWindow.top = cs->y;
881 wndPtr->rectWindow.right = cs->x + cs->cx;
882 wndPtr->rectWindow.bottom = cs->y + cs->cy;
883 wndPtr->rectClient = wndPtr->rectWindow;
885 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
887 retvalue = FALSE;
888 goto end;
891 /* Set the window menu */
893 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
895 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
896 else
898 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
899 if (classPtr->menuNameA)
900 cs->hMenu = HIWORD(classPtr->menuNameA) ?
901 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
902 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
903 #else
904 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
905 if (menuName)
907 if (HIWORD(cs->hInstance))
908 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
909 else
910 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
912 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
914 #endif
917 else wndPtr->wIDmenu = (UINT)cs->hMenu;
919 /* Send the WM_CREATE message
920 * Perhaps we shouldn't allow width/height changes as well.
921 * See p327 in "Internals".
924 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
926 localSend32 = unicode ? SendMessageW : SendMessageA;
927 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
929 /* Insert the window in the linked list */
931 WIN_LinkWindow( hwnd, hwndLinkAfter );
933 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
934 NULL, NULL, 0, &wndPtr->rectClient );
935 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
936 maxPos.y - wndPtr->rectWindow.top);
937 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
939 /* Send the size messages */
941 if (!(wndPtr->flags & WIN_NEED_SIZE))
943 /* send it anyway */
944 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
945 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
946 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
947 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
948 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
949 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
950 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
951 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
952 SendMessageA( hwnd, WM_MOVE, 0,
953 MAKELONG( wndPtr->rectClient.left,
954 wndPtr->rectClient.top ) );
957 /* Show the window, maximizing or minimizing if needed */
959 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
961 RECT16 newPos;
962 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
963 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
964 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
965 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
966 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
967 : SWP_NOZORDER | SWP_FRAMECHANGED;
968 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
969 newPos.right, newPos.bottom, swFlag );
972 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
974 /* Notify the parent window only */
976 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
977 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
978 if( !IsWindow(hwnd) )
980 retvalue = 0;
981 goto end;
985 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
987 /* Call WH_SHELL hook */
989 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
990 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
992 TRACE_(win)("created window %04x\n", hwnd);
993 retvalue = hwnd;
994 goto end;
996 WIN_UnlinkWindow( hwnd );
999 /* Abort window creation */
1001 WARN_(win)("aborted by WM_xxCREATE!\n");
1002 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1003 retvalue = 0;
1004 end:
1005 WIN_ReleaseWndPtr(wndPtr);
1007 return retvalue;
1011 /***********************************************************************
1012 * CreateWindow16 (USER.41)
1014 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1015 DWORD style, INT16 x, INT16 y, INT16 width,
1016 INT16 height, HWND16 parent, HMENU16 menu,
1017 HINSTANCE16 instance, LPVOID data )
1019 return CreateWindowEx16( 0, className, windowName, style,
1020 x, y, width, height, parent, menu, instance, data );
1024 /***********************************************************************
1025 * CreateWindowEx16 (USER.452)
1027 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1028 LPCSTR windowName, DWORD style, INT16 x,
1029 INT16 y, INT16 width, INT16 height,
1030 HWND16 parent, HMENU16 menu,
1031 HINSTANCE16 instance, LPVOID data )
1033 ATOM classAtom;
1034 CREATESTRUCTA cs;
1036 /* Find the class atom */
1038 if (!(classAtom = GlobalFindAtomA( className )))
1040 fprintf( stderr, "CreateWindowEx16: bad class name " );
1041 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1042 else fprintf( stderr, "'%s'\n", className );
1043 return 0;
1046 /* Fix the coordinates */
1048 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1049 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1050 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1051 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1053 /* Create the window */
1055 cs.lpCreateParams = data;
1056 cs.hInstance = (HINSTANCE)instance;
1057 cs.hMenu = (HMENU)menu;
1058 cs.hwndParent = (HWND)parent;
1059 cs.style = style;
1060 cs.lpszName = windowName;
1061 cs.lpszClass = className;
1062 cs.dwExStyle = exStyle;
1063 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1067 /***********************************************************************
1068 * CreateWindowEx32A (USER32.83)
1070 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1071 LPCSTR windowName, DWORD style, INT x,
1072 INT y, INT width, INT height,
1073 HWND parent, HMENU menu,
1074 HINSTANCE instance, LPVOID data )
1076 ATOM classAtom;
1077 CREATESTRUCTA cs;
1079 if(exStyle & WS_EX_MDICHILD)
1080 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1081 /* Find the class atom */
1083 if (!(classAtom = GlobalFindAtomA( className )))
1085 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1086 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1087 else fprintf( stderr, "'%s'\n", className );
1088 return 0;
1091 /* Create the window */
1093 cs.lpCreateParams = data;
1094 cs.hInstance = instance;
1095 cs.hMenu = menu;
1096 cs.hwndParent = parent;
1097 cs.x = x;
1098 cs.y = y;
1099 cs.cx = width;
1100 cs.cy = height;
1101 cs.style = style;
1102 cs.lpszName = windowName;
1103 cs.lpszClass = className;
1104 cs.dwExStyle = exStyle;
1105 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1109 /***********************************************************************
1110 * CreateWindowEx32W (USER32.84)
1112 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1113 LPCWSTR windowName, DWORD style, INT x,
1114 INT y, INT width, INT height,
1115 HWND parent, HMENU menu,
1116 HINSTANCE instance, LPVOID data )
1118 ATOM classAtom;
1119 CREATESTRUCTW cs;
1121 if(exStyle & WS_EX_MDICHILD)
1122 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1124 /* Find the class atom */
1126 if (!(classAtom = GlobalFindAtomW( className )))
1128 if (HIWORD(className))
1130 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1131 WARN_(win)("Bad class name '%s'\n",cn);
1132 HeapFree( GetProcessHeap(), 0, cn );
1134 else
1135 WARN_(win)("Bad class name %p\n", className );
1136 return 0;
1139 /* Create the window */
1141 cs.lpCreateParams = data;
1142 cs.hInstance = instance;
1143 cs.hMenu = menu;
1144 cs.hwndParent = parent;
1145 cs.x = x;
1146 cs.y = y;
1147 cs.cx = width;
1148 cs.cy = height;
1149 cs.style = style;
1150 cs.lpszName = windowName;
1151 cs.lpszClass = className;
1152 cs.dwExStyle = exStyle;
1153 /* Note: we rely on the fact that CREATESTRUCT32A and */
1154 /* CREATESTRUCT32W have the same layout. */
1155 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1159 /***********************************************************************
1160 * WIN_CheckFocus
1162 static void WIN_CheckFocus( WND* pWnd )
1164 if( GetFocus16() == pWnd->hwndSelf )
1165 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1168 /***********************************************************************
1169 * WIN_SendDestroyMsg
1171 static void WIN_SendDestroyMsg( WND* pWnd )
1173 WIN_CheckFocus(pWnd);
1175 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1176 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1179 * Send the WM_DESTROY to the window.
1181 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1184 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1185 * make sure that the window still exists when we come back.
1187 if (IsWindow(pWnd->hwndSelf))
1189 HWND* pWndArray = NULL;
1190 WND* pChild = NULL;
1191 int nKidCount = 0;
1194 * Now, if the window has kids, we have to send WM_DESTROY messages
1195 * recursively to it's kids. It seems that those calls can also
1196 * trigger re-entrant calls to DestroyWindow for the kids so we must
1197 * protect against corruption of the list of siblings. We first build
1198 * a list of HWNDs representing all the kids.
1200 pChild = WIN_LockWndPtr(pWnd->child);
1201 while( pChild )
1203 nKidCount++;
1204 WIN_UpdateWndPtr(&pChild,pChild->next);
1208 * If there are no kids, we're done.
1210 if (nKidCount==0)
1211 return;
1213 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1216 * Sanity check
1218 if (pWndArray==NULL)
1219 return;
1222 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1223 * call, our linked list of siblings should be safe.
1225 nKidCount = 0;
1226 pChild = WIN_LockWndPtr(pWnd->child);
1227 while( pChild )
1229 pWndArray[nKidCount] = pChild->hwndSelf;
1230 nKidCount++;
1231 WIN_UpdateWndPtr(&pChild,pChild->next);
1235 * Now that we have a list, go through that list again and send the destroy
1236 * message to those windows. We are using the HWND to retrieve the
1237 * WND pointer so we are effectively checking that all the kid windows are
1238 * still valid before sending the message.
1240 while (nKidCount>0)
1242 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1244 if (pChild!=NULL)
1246 WIN_SendDestroyMsg( pChild );
1247 WIN_ReleaseWndPtr(pChild);
1252 * Cleanup
1254 HeapFree(GetProcessHeap(), 0, pWndArray);
1255 WIN_CheckFocus(pWnd);
1257 else
1258 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1262 /***********************************************************************
1263 * DestroyWindow16 (USER.53)
1265 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1267 return DestroyWindow(hwnd);
1271 /***********************************************************************
1272 * DestroyWindow32 (USER32.135)
1274 BOOL WINAPI DestroyWindow( HWND hwnd )
1276 WND * wndPtr;
1277 BOOL retvalue;
1279 TRACE_(win)("(%04x)\n", hwnd);
1281 /* Initialization */
1283 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1284 if (wndPtr == pWndDesktop)
1286 WIN_ReleaseWndPtr(wndPtr);
1287 return FALSE; /* Can't destroy desktop */
1290 /* Call hooks */
1292 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1294 retvalue = FALSE;
1295 goto end;
1298 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1300 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1301 /* FIXME: clean up palette - see "Internals" p.352 */
1304 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1305 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1307 /* Notify the parent window only */
1308 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1309 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1310 if( !IsWindow(hwnd) )
1312 retvalue = TRUE;
1313 goto end;
1317 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1319 /* Hide the window */
1321 if (wndPtr->dwStyle & WS_VISIBLE)
1323 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1324 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1325 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1326 if (!IsWindow(hwnd))
1328 retvalue = TRUE;
1329 goto end;
1333 /* Recursively destroy owned windows */
1335 if( !(wndPtr->dwStyle & WS_CHILD) )
1337 /* make sure top menu popup doesn't get destroyed */
1338 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1340 for (;;)
1342 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1343 while (siblingPtr)
1345 if (siblingPtr->owner == wndPtr)
1347 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1348 break;
1349 else
1350 siblingPtr->owner = NULL;
1352 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1354 if (siblingPtr)
1356 DestroyWindow( siblingPtr->hwndSelf );
1357 WIN_ReleaseWndPtr(siblingPtr);
1359 else break;
1362 if( !Options.managed || EVENT_CheckFocus() )
1363 WINPOS_ActivateOtherWindow(wndPtr);
1365 if( wndPtr->owner &&
1366 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1367 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1370 /* Send destroy messages */
1372 WIN_SendDestroyMsg( wndPtr );
1373 if (!IsWindow(hwnd))
1375 retvalue = TRUE;
1376 goto end;
1379 /* Unlink now so we won't bother with the children later on */
1381 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1383 /* Destroy the window storage */
1385 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1386 retvalue = TRUE;
1387 end:
1388 WIN_ReleaseWndPtr(wndPtr);
1389 return retvalue;
1393 /***********************************************************************
1394 * CloseWindow16 (USER.43)
1396 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1398 return CloseWindow( hwnd );
1402 /***********************************************************************
1403 * CloseWindow32 (USER32.56)
1405 BOOL WINAPI CloseWindow( HWND hwnd )
1407 WND * wndPtr = WIN_FindWndPtr( hwnd );
1408 BOOL retvalue;
1410 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1412 retvalue = FALSE;
1413 goto end;
1415 ShowWindow( hwnd, SW_MINIMIZE );
1416 retvalue = TRUE;
1417 end:
1418 WIN_ReleaseWndPtr(wndPtr);
1419 return retvalue;
1424 /***********************************************************************
1425 * OpenIcon16 (USER.44)
1427 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1429 return OpenIcon( hwnd );
1433 /***********************************************************************
1434 * OpenIcon32 (USER32.410)
1436 BOOL WINAPI OpenIcon( HWND hwnd )
1438 if (!IsIconic( hwnd )) return FALSE;
1439 ShowWindow( hwnd, SW_SHOWNORMAL );
1440 return TRUE;
1444 /***********************************************************************
1445 * WIN_FindWindow
1447 * Implementation of FindWindow() and FindWindowEx().
1449 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1450 LPCSTR title )
1452 WND *pWnd;
1453 HWND retvalue;
1454 CLASS *pClass = NULL;
1456 if (child)
1458 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1459 if (parent)
1461 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1463 retvalue = 0;
1464 goto end;
1467 else if (pWnd->parent != pWndDesktop)
1469 retvalue = 0;
1470 goto end;
1472 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1474 else
1476 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1478 retvalue = 0;
1479 goto end;
1481 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1483 if (!pWnd)
1485 retvalue = 0;
1486 goto end;
1489 /* For a child window, all siblings will have the same hInstance, */
1490 /* so we can look for the class once and for all. */
1492 if (className && (pWnd->dwStyle & WS_CHILD))
1494 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1496 retvalue = 0;
1497 goto end;
1502 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1504 if (className && !(pWnd->dwStyle & WS_CHILD))
1506 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1507 continue; /* Skip this window */
1510 if (pClass && (pWnd->class != pClass))
1511 continue; /* Not the right class */
1513 /* Now check the title */
1515 if (!title)
1517 retvalue = pWnd->hwndSelf;
1518 goto end;
1520 if (pWnd->text && !strcmp( pWnd->text, title ))
1522 retvalue = pWnd->hwndSelf;
1523 goto end;
1526 retvalue = 0;
1527 end:
1528 WIN_ReleaseWndPtr(pWnd);
1529 return retvalue;
1534 /***********************************************************************
1535 * FindWindow16 (USER.50)
1537 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1539 return FindWindowEx16( 0, 0, className, title );
1543 /***********************************************************************
1544 * FindWindowEx16 (USER.427)
1546 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1547 SEGPTR className, LPCSTR title )
1549 ATOM atom = 0;
1551 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1552 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1553 title ? title : "");
1555 if (className)
1557 /* If the atom doesn't exist, then no class */
1558 /* with this name exists either. */
1559 if (!(atom = GlobalFindAtom16( className ))) return 0;
1561 return WIN_FindWindow( parent, child, atom, title );
1565 /***********************************************************************
1566 * FindWindow32A (USER32.198)
1568 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1570 HWND ret = FindWindowExA( 0, 0, className, title );
1571 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1572 return ret;
1576 /***********************************************************************
1577 * FindWindowEx32A (USER32.199)
1579 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1580 LPCSTR className, LPCSTR title )
1582 ATOM atom = 0;
1584 if (className)
1586 /* If the atom doesn't exist, then no class */
1587 /* with this name exists either. */
1588 if (!(atom = GlobalFindAtomA( className )))
1590 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1591 return 0;
1594 return WIN_FindWindow( parent, child, atom, title );
1598 /***********************************************************************
1599 * FindWindowEx32W (USER32.200)
1601 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1602 LPCWSTR className, LPCWSTR title )
1604 ATOM atom = 0;
1605 char *buffer;
1606 HWND hwnd;
1608 if (className)
1610 /* If the atom doesn't exist, then no class */
1611 /* with this name exists either. */
1612 if (!(atom = GlobalFindAtomW( className )))
1614 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1615 return 0;
1618 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1619 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1620 HeapFree( GetProcessHeap(), 0, buffer );
1621 return hwnd;
1625 /***********************************************************************
1626 * FindWindow32W (USER32.201)
1628 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1630 return FindWindowExW( 0, 0, className, title );
1634 /**********************************************************************
1635 * WIN_GetDesktop
1636 * returns a locked pointer
1638 WND *WIN_GetDesktop(void)
1640 return WIN_LockWndPtr(pWndDesktop);
1642 /**********************************************************************
1643 * WIN_ReleaseDesktop
1644 * unlock the desktop pointer
1646 void WIN_ReleaseDesktop(void)
1648 WIN_ReleaseWndPtr(pWndDesktop);
1652 /**********************************************************************
1653 * GetDesktopWindow16 (USER.286)
1655 HWND16 WINAPI GetDesktopWindow16(void)
1657 return (HWND16)pWndDesktop->hwndSelf;
1661 /**********************************************************************
1662 * GetDesktopWindow32 (USER32.232)
1664 HWND WINAPI GetDesktopWindow(void)
1666 return pWndDesktop->hwndSelf;
1670 /**********************************************************************
1671 * GetDesktopHwnd (USER.278)
1673 * Exactly the same thing as GetDesktopWindow(), but not documented.
1674 * Don't ask me why...
1676 HWND16 WINAPI GetDesktopHwnd16(void)
1678 return (HWND16)pWndDesktop->hwndSelf;
1682 /*******************************************************************
1683 * EnableWindow16 (USER.34)
1685 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1687 return EnableWindow( hwnd, enable );
1691 /*******************************************************************
1692 * EnableWindow32 (USER32.172)
1694 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1696 WND *wndPtr;
1697 BOOL retvalue;
1699 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1702 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1704 /* Enable window */
1705 wndPtr->dwStyle &= ~WS_DISABLED;
1707 if( wndPtr->flags & WIN_NATIVE )
1708 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1710 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1711 retvalue = TRUE;
1712 goto end;
1714 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1716 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1718 /* Disable window */
1719 wndPtr->dwStyle |= WS_DISABLED;
1721 if( wndPtr->flags & WIN_NATIVE )
1722 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1724 if (hwnd == GetFocus())
1726 SetFocus( 0 ); /* A disabled window can't have the focus */
1728 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1730 ReleaseCapture(); /* A disabled window can't capture the mouse */
1732 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1733 retvalue = FALSE;
1734 goto end;
1736 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1737 end:
1738 WIN_ReleaseWndPtr(wndPtr);
1739 return retvalue;
1743 /***********************************************************************
1744 * IsWindowEnabled16 (USER.35)
1746 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1748 return IsWindowEnabled(hWnd);
1752 /***********************************************************************
1753 * IsWindowEnabled32 (USER32.349)
1755 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1757 WND * wndPtr;
1758 BOOL retvalue;
1760 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1761 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1762 WIN_ReleaseWndPtr(wndPtr);
1763 return retvalue;
1768 /***********************************************************************
1769 * IsWindowUnicode (USER32.350)
1771 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1773 WND * wndPtr;
1774 BOOL retvalue;
1776 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1777 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1778 WIN_ReleaseWndPtr(wndPtr);
1779 return retvalue;
1783 /**********************************************************************
1784 * GetWindowWord16 (USER.133)
1786 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1788 return GetWindowWord( hwnd, offset );
1792 /**********************************************************************
1793 * GetWindowWord32 (USER32.314)
1795 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1797 WORD retvalue;
1798 WND * wndPtr = WIN_FindWndPtr( hwnd );
1799 if (!wndPtr) return 0;
1800 if (offset >= 0)
1802 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1804 WARN_(win)("Invalid offset %d\n", offset );
1805 retvalue = 0;
1806 goto end;
1808 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1809 goto end;
1811 switch(offset)
1813 case GWW_ID:
1814 if (HIWORD(wndPtr->wIDmenu))
1815 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1816 wndPtr->wIDmenu);
1817 retvalue = (WORD)wndPtr->wIDmenu;
1818 goto end;
1819 case GWW_HWNDPARENT:
1820 retvalue = GetParent(hwnd);
1821 goto end;
1822 case GWW_HINSTANCE:
1823 if (HIWORD(wndPtr->hInstance))
1824 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1825 wndPtr->hInstance);
1826 retvalue = (WORD)wndPtr->hInstance;
1827 goto end;
1828 default:
1829 WARN_(win)("Invalid offset %d\n", offset );
1830 retvalue = 0;
1831 goto end;
1833 end:
1834 WIN_ReleaseWndPtr(wndPtr);
1835 return retvalue;
1838 /**********************************************************************
1839 * SetWindowWord16 (USER.134)
1841 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1843 return SetWindowWord( hwnd, offset, newval );
1847 /**********************************************************************
1848 * SetWindowWord32 (USER32.524)
1850 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1852 WORD *ptr, retval;
1853 WND * wndPtr = WIN_FindWndPtr( hwnd );
1854 if (!wndPtr) return 0;
1855 if (offset >= 0)
1857 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1859 WARN_(win)("Invalid offset %d\n", offset );
1860 retval = 0;
1861 goto end;
1863 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1865 else switch(offset)
1867 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1868 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1869 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1870 goto end;
1871 default:
1872 WARN_(win)("Invalid offset %d\n", offset );
1873 retval = 0;
1874 goto end;
1876 retval = *ptr;
1877 *ptr = newval;
1878 end:
1879 WIN_ReleaseWndPtr(wndPtr);
1880 return retval;
1884 /**********************************************************************
1885 * WIN_GetWindowLong
1887 * Helper function for GetWindowLong().
1889 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1891 LONG retvalue;
1892 WND * wndPtr = WIN_FindWndPtr( hwnd );
1893 if (!wndPtr) return 0;
1894 if (offset >= 0)
1896 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1898 WARN_(win)("Invalid offset %d\n", offset );
1899 retvalue = 0;
1900 goto end;
1902 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1903 /* Special case for dialog window procedure */
1904 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1906 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1907 goto end;
1909 goto end;
1911 switch(offset)
1913 case GWL_USERDATA: retvalue = wndPtr->userdata;
1914 goto end;
1915 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1916 goto end;
1917 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1918 goto end;
1919 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1920 goto end;
1921 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1922 type );
1923 goto end;
1924 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1925 goto end;
1926 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1927 goto end;
1928 default:
1929 WARN_(win)("Unknown offset %d\n", offset );
1931 retvalue = 0;
1932 end:
1933 WIN_ReleaseWndPtr(wndPtr);
1934 return retvalue;
1938 /**********************************************************************
1939 * WIN_SetWindowLong
1941 * Helper function for SetWindowLong().
1943 * 0 is the failure code. However, in the case of failure SetLastError
1944 * must be set to distinguish between a 0 return value and a failure.
1946 * FIXME: The error values for SetLastError may not be right. Can
1947 * someone check with the real thing?
1949 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1950 WINDOWPROCTYPE type )
1952 LONG *ptr, retval;
1953 WND * wndPtr = WIN_FindWndPtr( hwnd );
1954 STYLESTRUCT style;
1956 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1958 if (!wndPtr)
1960 /* Is this the right error? */
1961 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1962 return 0;
1965 if (offset >= 0)
1967 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1969 WARN_(win)("Invalid offset %d\n", offset );
1971 /* Is this the right error? */
1972 SetLastError( ERROR_OUTOFMEMORY );
1974 retval = 0;
1975 goto end;
1977 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1978 /* Special case for dialog window procedure */
1979 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1981 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1982 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1983 type, WIN_PROC_WINDOW );
1984 goto end;
1987 else switch(offset)
1989 case GWL_ID:
1990 ptr = (DWORD*)&wndPtr->wIDmenu;
1991 break;
1992 case GWL_HINSTANCE:
1993 retval = SetWindowWord( hwnd, offset, newval );
1994 goto end;
1995 case GWL_WNDPROC:
1996 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1997 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1998 type, WIN_PROC_WINDOW );
1999 goto end;;
2000 case GWL_STYLE:
2001 style.styleOld = wndPtr->dwStyle;
2002 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2003 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2005 if (wndPtr->flags & WIN_ISWIN32)
2006 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2007 wndPtr->dwStyle = style.styleNew;
2008 if (wndPtr->flags & WIN_ISWIN32)
2009 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2010 retval = style.styleOld;
2011 goto end;
2013 case GWL_USERDATA:
2014 ptr = &wndPtr->userdata;
2015 break;
2016 case GWL_EXSTYLE:
2017 style.styleOld = wndPtr->dwExStyle;
2018 style.styleNew = newval;
2019 if (wndPtr->flags & WIN_ISWIN32)
2020 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2021 wndPtr->dwExStyle = newval;
2022 if (wndPtr->flags & WIN_ISWIN32)
2023 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2024 retval = style.styleOld;
2025 goto end;
2027 default:
2028 WARN_(win)("Invalid offset %d\n", offset );
2030 /* Don't think this is right error but it should do */
2031 SetLastError( ERROR_OUTOFMEMORY );
2033 retval = 0;
2034 goto end;
2036 retval = *ptr;
2037 *ptr = newval;
2038 end:
2039 WIN_ReleaseWndPtr(wndPtr);
2040 return retval;
2044 /**********************************************************************
2045 * GetWindowLong16 (USER.135)
2047 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2049 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2053 /**********************************************************************
2054 * GetWindowLong32A (USER32.305)
2056 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2058 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2062 /**********************************************************************
2063 * GetWindowLong32W (USER32.306)
2065 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2067 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2071 /**********************************************************************
2072 * SetWindowLong16 (USER.136)
2074 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2076 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2080 /**********************************************************************
2081 * SetWindowLong32A (USER32.517)
2083 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2085 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2089 /**********************************************************************
2090 * SetWindowLong32W (USER32.518) Set window attribute
2092 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2093 * value in a window's extra memory.
2095 * The _hwnd_ parameter specifies the window. is the handle to a
2096 * window that has extra memory. The _newval_ parameter contains the
2097 * new attribute or extra memory value. If positive, the _offset_
2098 * parameter is the byte-addressed location in the window's extra
2099 * memory to set. If negative, _offset_ specifies the window
2100 * attribute to set, and should be one of the following values:
2102 * GWL_EXSTYLE The window's extended window style
2104 * GWL_STYLE The window's window style.
2106 * GWL_WNDPROC Pointer to the window's window procedure.
2108 * GWL_HINSTANCE The window's pplication instance handle.
2110 * GWL_ID The window's identifier.
2112 * GWL_USERDATA The window's user-specified data.
2114 * If the window is a dialog box, the _offset_ parameter can be one of
2115 * the following values:
2117 * DWL_DLGPROC The address of the window's dialog box procedure.
2119 * DWL_MSGRESULT The return value of a message
2120 * that the dialog box procedure processed.
2122 * DWL_USER Application specific information.
2124 * RETURNS
2126 * If successful, returns the previous value located at _offset_. Otherwise,
2127 * returns 0.
2129 * NOTES
2131 * Extra memory for a window class is specified by a nonzero cbWndExtra
2132 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2133 * time of class creation.
2135 * Using GWL_WNDPROC to set a new window procedure effectively creates
2136 * a window subclass. Use CallWindowProc() in the new windows procedure
2137 * to pass messages to the superclass's window procedure.
2139 * The user data is reserved for use by the application which created
2140 * the window.
2142 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2143 * instead, call the EnableWindow() function to change the window's
2144 * disabled state.
2146 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2147 * SetParent() instead.
2149 * Win95:
2150 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2151 * it sends WM_STYLECHANGING before changing the settings
2152 * and WM_STYLECHANGED afterwards.
2153 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2155 * BUGS
2157 * GWL_STYLE does not dispatch WM_STYLE... messages.
2159 * CONFORMANCE
2161 * ECMA-234, Win32
2164 LONG WINAPI SetWindowLongW(
2165 HWND hwnd, /* window to alter */
2166 INT offset, /* offset, in bytes, of location to alter */
2167 LONG newval /* new value of location */
2169 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2173 /*******************************************************************
2174 * GetWindowText16 (USER.36)
2176 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2178 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2182 /*******************************************************************
2183 * GetWindowText32A (USER32.309)
2185 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2187 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2188 (LPARAM)lpString );
2191 /*******************************************************************
2192 * InternalGetWindowText (USER32.326)
2194 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2196 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2197 return GetWindowTextW(hwnd,lpString,nMaxCount);
2201 /*******************************************************************
2202 * GetWindowText32W (USER32.312)
2204 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2206 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2207 (LPARAM)lpString );
2211 /*******************************************************************
2212 * SetWindowText16 (USER.37)
2214 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2216 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2220 /*******************************************************************
2221 * SetWindowText32A (USER32.521)
2223 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2225 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2229 /*******************************************************************
2230 * SetWindowText32W (USER32.523)
2232 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2234 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2238 /*******************************************************************
2239 * GetWindowTextLength16 (USER.38)
2241 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2243 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2247 /*******************************************************************
2248 * GetWindowTextLength32A (USER32.310)
2250 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2252 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2255 /*******************************************************************
2256 * GetWindowTextLength32W (USER32.311)
2258 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2260 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2264 /*******************************************************************
2265 * IsWindow16 (USER.47)
2267 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2269 return IsWindow( hwnd );
2272 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2274 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2275 HWND16 hwnd = (HWND16)stack[2];
2277 AX_reg(context) = IsWindow( hwnd );
2278 ES_reg(context) = USER_HeapSel;
2282 /*******************************************************************
2283 * IsWindow32 (USER32.348)
2285 BOOL WINAPI IsWindow( HWND hwnd )
2287 WND * wndPtr;
2288 BOOL retvalue;
2290 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2291 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2292 WIN_ReleaseWndPtr(wndPtr);
2293 return retvalue;
2298 /*****************************************************************
2299 * GetParent16 (USER.46)
2301 HWND16 WINAPI GetParent16( HWND16 hwnd )
2303 return (HWND16)GetParent( hwnd );
2307 /*****************************************************************
2308 * GetParent32 (USER32.278)
2310 HWND WINAPI GetParent( HWND hwnd )
2312 WND *wndPtr;
2313 HWND retvalue;
2315 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2316 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2318 WIN_ReleaseWndPtr(wndPtr);
2319 return 0;
2321 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2322 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2324 WIN_ReleaseWndPtr(wndPtr);
2325 return retvalue;
2329 /*****************************************************************
2330 * WIN_GetTopParent
2332 * Get the top-level parent for a child window.
2333 * returns a locked pointer
2335 WND* WIN_GetTopParentPtr( WND* pWnd )
2337 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2339 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2341 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2343 return tmpWnd;
2346 /*****************************************************************
2347 * WIN_GetTopParent
2349 * Get the top-level parent for a child window.
2351 HWND WIN_GetTopParent( HWND hwnd )
2353 HWND retvalue;
2354 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2355 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2357 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2358 WIN_ReleaseWndPtr(tmpPtr);
2359 WIN_ReleaseWndPtr(wndPtr);
2360 return retvalue;
2364 /*****************************************************************
2365 * SetParent16 (USER.233)
2367 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2369 return SetParent( hwndChild, hwndNewParent );
2373 /*****************************************************************
2374 * SetParent32 (USER32.495)
2376 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2378 WND *wndPtr;
2379 DWORD dwStyle;
2380 WND *pWndNewParent;
2381 WND *pWndOldParent;
2382 HWND retvalue;
2385 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2387 dwStyle = wndPtr->dwStyle;
2389 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2390 : WIN_LockWndPtr(pWndDesktop);
2392 /* Windows hides the window first, then shows it again
2393 * including the WM_SHOWWINDOW messages and all */
2394 if (dwStyle & WS_VISIBLE)
2395 ShowWindow( hwndChild, SW_HIDE );
2397 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2399 /* SetParent32 additionally needs to make hwndChild the topmost window
2400 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2401 WM_WINDOWPOSCHANGED notification messages.
2403 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2404 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2405 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2406 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2408 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2410 WIN_ReleaseWndPtr(pWndOldParent);
2411 WIN_ReleaseWndPtr(pWndNewParent);
2412 WIN_ReleaseWndPtr(wndPtr);
2414 return retvalue;
2418 /*******************************************************************
2419 * IsChild16 (USER.48)
2421 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2423 return IsChild(parent,child);
2427 /*******************************************************************
2428 * IsChild32 (USER32.339)
2430 BOOL WINAPI IsChild( HWND parent, HWND child )
2432 WND * wndPtr = WIN_FindWndPtr( child );
2433 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2435 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2436 if (wndPtr->hwndSelf == parent)
2438 WIN_ReleaseWndPtr(wndPtr);
2439 return TRUE;
2442 WIN_ReleaseWndPtr(wndPtr);
2443 return FALSE;
2447 /***********************************************************************
2448 * IsWindowVisible16 (USER.49)
2450 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2452 return IsWindowVisible(hwnd);
2456 /***********************************************************************
2457 * IsWindowVisible32 (USER32.351)
2459 BOOL WINAPI IsWindowVisible( HWND hwnd )
2461 BOOL retval;
2462 WND *wndPtr = WIN_FindWndPtr( hwnd );
2463 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2465 if (!(wndPtr->dwStyle & WS_VISIBLE))
2467 WIN_ReleaseWndPtr(wndPtr);
2468 return FALSE;
2470 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2472 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2473 WIN_ReleaseWndPtr(wndPtr);
2474 return retval;
2479 /***********************************************************************
2480 * WIN_IsWindowDrawable
2482 * hwnd is drawable when it is visible, all parents are not
2483 * minimized, and it is itself not minimized unless we are
2484 * trying to draw its default class icon.
2486 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2488 if( (wnd->dwStyle & WS_MINIMIZE &&
2489 icon && wnd->class->hIcon) ||
2490 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2491 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2492 if( wnd->dwStyle & WS_MINIMIZE ||
2493 !(wnd->dwStyle & WS_VISIBLE) ) break;
2494 return (wnd == NULL);
2498 /*******************************************************************
2499 * GetTopWindow16 (USER.229)
2501 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2503 return GetTopWindow(hwnd);
2507 /*******************************************************************
2508 * GetTopWindow32 (USER.229)
2510 HWND WINAPI GetTopWindow( HWND hwnd )
2512 HWND retval;
2513 WND * wndPtr = NULL;
2515 if (hwnd!=0)
2516 wndPtr = WIN_FindWndPtr( hwnd );
2517 else
2518 wndPtr = WIN_GetDesktop();
2520 if (wndPtr && wndPtr->child)
2522 retval = wndPtr->child->hwndSelf;
2524 else retval = 0;
2525 WIN_ReleaseWndPtr(wndPtr);
2526 return retval;
2530 /*******************************************************************
2531 * GetWindow16 (USER.262)
2533 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2535 return GetWindow( hwnd,rel );
2539 /*******************************************************************
2540 * GetWindow32 (USER32.302)
2542 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2544 HWND retval;
2546 WND * wndPtr = WIN_FindWndPtr( hwnd );
2547 if (!wndPtr) return 0;
2548 switch(rel)
2550 case GW_HWNDFIRST:
2551 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2552 else retval = 0;
2553 goto end;
2555 case GW_HWNDLAST:
2556 if (!wndPtr->parent)
2558 retval = 0; /* Desktop window */
2559 goto end;
2561 while (wndPtr->next)
2563 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2565 retval = wndPtr->hwndSelf;
2566 goto end;
2568 case GW_HWNDNEXT:
2569 if (!wndPtr->next) retval = 0;
2570 else retval = wndPtr->next->hwndSelf;
2571 goto end;
2573 case GW_HWNDPREV:
2574 if (!wndPtr->parent)
2576 retval = 0; /* Desktop window */
2577 goto end;
2579 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2580 if (wndPtr->hwndSelf == hwnd)
2582 retval = 0; /* First in list */
2583 goto end;
2585 while (wndPtr->next)
2587 if (wndPtr->next->hwndSelf == hwnd)
2589 retval = wndPtr->hwndSelf;
2590 goto end;
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2594 retval = 0;
2595 goto end;
2597 case GW_OWNER:
2598 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2599 goto end;
2601 case GW_CHILD:
2602 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2603 goto end;
2605 retval = 0;
2606 end:
2607 WIN_ReleaseWndPtr(wndPtr);
2608 return retval;
2612 /*******************************************************************
2613 * GetNextWindow16 (USER.230)
2615 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2617 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2618 return GetWindow16( hwnd, flag );
2621 /*******************************************************************
2622 * ShowOwnedPopups16 (USER.265)
2624 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2626 ShowOwnedPopups( owner, fShow );
2630 /*******************************************************************
2631 * ShowOwnedPopups32 (USER32.531)
2633 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2635 WND *pWnd;
2636 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2637 while (pWnd)
2639 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2640 (pWnd->dwStyle & WS_POPUP))
2641 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2642 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2644 return TRUE;
2648 /*******************************************************************
2649 * GetLastActivePopup16 (USER.287)
2651 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2653 return GetLastActivePopup( hwnd );
2656 /*******************************************************************
2657 * GetLastActivePopup32 (USER32.256)
2659 HWND WINAPI GetLastActivePopup( HWND hwnd )
2661 WND *wndPtr;
2662 HWND retval;
2663 wndPtr = WIN_FindWndPtr(hwnd);
2664 if (!wndPtr) return hwnd;
2665 retval = wndPtr->hwndLastActive;
2666 WIN_ReleaseWndPtr(wndPtr);
2667 return retval;
2671 /*******************************************************************
2672 * WIN_BuildWinArray
2674 * Build an array of pointers to the children of a given window.
2675 * The array must be freed with HeapFree(SystemHeap). Return NULL
2676 * when no windows are found.
2678 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2680 /* Future : this function will lock all windows associated with this array */
2682 WND **list, **ppWnd;
2683 WND *pWnd;
2684 UINT count = 0, skipOwned, skipHidden;
2685 DWORD skipFlags;
2687 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2688 skipOwned = bwaFlags & BWA_SKIPOWNED;
2689 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2690 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2692 /* First count the windows */
2694 if (!wndPtr)
2695 wndPtr = WIN_GetDesktop();
2697 pWnd = WIN_LockWndPtr(wndPtr->child);
2698 while (pWnd)
2700 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2701 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2702 count++;
2703 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2706 if( count )
2708 /* Now build the list of all windows */
2710 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2712 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2714 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2715 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2717 *ppWnd++ = pWnd;
2718 count++;
2721 WIN_ReleaseWndPtr(pWnd);
2722 *ppWnd = NULL;
2724 else count = 0;
2725 } else list = NULL;
2727 if( pTotal ) *pTotal = count;
2728 return list;
2730 /*******************************************************************
2731 * WIN_ReleaseWinArray
2733 void WIN_ReleaseWinArray(WND **wndArray)
2735 /* Future : this function will also unlock all windows associated with wndArray */
2736 HeapFree( SystemHeap, 0, wndArray );
2740 /*******************************************************************
2741 * EnumWindows16 (USER.54)
2743 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2745 WND **list, **ppWnd;
2747 /* We have to build a list of all windows first, to avoid */
2748 /* unpleasant side-effects, for instance if the callback */
2749 /* function changes the Z-order of the windows. */
2751 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2753 WIN_ReleaseDesktop();
2754 return FALSE;
2757 /* Now call the callback function for every window */
2759 for (ppWnd = list; *ppWnd; ppWnd++)
2761 LRESULT lpEnumFuncRetval;
2762 int iWndsLocks = 0;
2763 /* Make sure that the window still exists */
2764 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2766 /* To avoid any deadlocks, all the locks on the windows
2767 structures must be suspended before the control
2768 is passed to the application */
2769 iWndsLocks = WIN_SuspendWndsLock();
2770 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2771 WIN_RestoreWndsLock(iWndsLocks);
2773 if (!lpEnumFuncRetval) break;
2775 WIN_ReleaseWinArray(list);
2776 WIN_ReleaseDesktop();
2777 return TRUE;
2781 /*******************************************************************
2782 * EnumWindows32 (USER32.193)
2784 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2786 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2790 /**********************************************************************
2791 * EnumTaskWindows16 (USER.225)
2793 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2794 LPARAM lParam )
2796 WND **list, **ppWnd;
2798 /* This function is the same as EnumWindows(), */
2799 /* except for an added check on the window's task. */
2801 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2803 WIN_ReleaseDesktop();
2804 return FALSE;
2807 /* Now call the callback function for every window */
2809 for (ppWnd = list; *ppWnd; ppWnd++)
2811 LRESULT funcRetval;
2812 int iWndsLocks = 0;
2813 /* Make sure that the window still exists */
2814 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2815 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2817 /* To avoid any deadlocks, all the locks on the windows
2818 structures must be suspended before the control
2819 is passed to the application */
2820 iWndsLocks = WIN_SuspendWndsLock();
2821 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2822 WIN_RestoreWndsLock(iWndsLocks);
2824 if (!funcRetval) break;
2826 WIN_ReleaseWinArray(list);
2827 WIN_ReleaseDesktop();
2828 return TRUE;
2832 /**********************************************************************
2833 * EnumThreadWindows (USER32.190)
2835 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2837 THDB *tdb = THREAD_IdToTHDB(id);
2839 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2843 /**********************************************************************
2844 * WIN_EnumChildWindows
2846 * Helper function for EnumChildWindows().
2848 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2849 LPARAM lParam )
2851 WND **childList;
2852 BOOL16 ret = FALSE;
2854 for ( ; *ppWnd; ppWnd++)
2856 int iWndsLocks = 0;
2858 /* Make sure that the window still exists */
2859 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2860 /* Build children list first */
2861 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2863 /* To avoid any deadlocks, all the locks on the windows
2864 structures must be suspended before the control
2865 is passed to the application */
2866 iWndsLocks = WIN_SuspendWndsLock();
2867 ret = func( (*ppWnd)->hwndSelf, lParam );
2868 WIN_RestoreWndsLock(iWndsLocks);
2870 if (childList)
2872 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2873 WIN_ReleaseWinArray(childList);
2875 if (!ret) return FALSE;
2877 return TRUE;
2881 /**********************************************************************
2882 * EnumChildWindows16 (USER.55)
2884 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2885 LPARAM lParam )
2887 WND **list, *pParent;
2889 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2890 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2892 WIN_ReleaseWndPtr(pParent);
2893 return FALSE;
2895 WIN_EnumChildWindows( list, func, lParam );
2896 WIN_ReleaseWinArray(list);
2897 WIN_ReleaseWndPtr(pParent);
2898 return TRUE;
2902 /**********************************************************************
2903 * EnumChildWindows32 (USER32.178)
2905 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2906 LPARAM lParam )
2908 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2909 lParam );
2913 /*******************************************************************
2914 * AnyPopup16 (USER.52)
2916 BOOL16 WINAPI AnyPopup16(void)
2918 return AnyPopup();
2922 /*******************************************************************
2923 * AnyPopup32 (USER32.4)
2925 BOOL WINAPI AnyPopup(void)
2927 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2928 BOOL retvalue;
2930 while (wndPtr)
2932 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2934 retvalue = TRUE;
2935 goto end;
2937 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2939 retvalue = FALSE;
2940 end:
2941 WIN_ReleaseWndPtr(wndPtr);
2942 return retvalue;
2946 /*******************************************************************
2947 * FlashWindow16 (USER.105)
2949 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2951 return FlashWindow( hWnd, bInvert );
2955 /*******************************************************************
2956 * FlashWindow32 (USER32.202)
2958 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2960 WND *wndPtr = WIN_FindWndPtr(hWnd);
2962 TRACE_(win)("%04x\n", hWnd);
2964 if (!wndPtr) return FALSE;
2966 if (wndPtr->dwStyle & WS_MINIMIZE)
2968 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2970 HDC hDC = GetDC(hWnd);
2972 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2973 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2975 ReleaseDC( hWnd, hDC );
2976 wndPtr->flags |= WIN_NCACTIVATED;
2978 else
2980 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2981 RDW_UPDATENOW | RDW_FRAME, 0 );
2982 wndPtr->flags &= ~WIN_NCACTIVATED;
2984 WIN_ReleaseWndPtr(wndPtr);
2985 return TRUE;
2987 else
2989 WPARAM16 wparam;
2990 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2991 else wparam = (hWnd == GetActiveWindow());
2993 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2994 WIN_ReleaseWndPtr(wndPtr);
2995 return wparam;
3000 /*******************************************************************
3001 * SetSysModalWindow16 (USER.188)
3003 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3005 HWND hWndOldModal = hwndSysModal;
3006 hwndSysModal = hWnd;
3007 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3008 return hWndOldModal;
3012 /*******************************************************************
3013 * GetSysModalWindow16 (USER.52)
3015 HWND16 WINAPI GetSysModalWindow16(void)
3017 return hwndSysModal;
3021 /*******************************************************************
3022 * GetWindowContextHelpId (USER32.303)
3024 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3026 DWORD retval;
3027 WND *wnd = WIN_FindWndPtr( hwnd );
3028 if (!wnd) return 0;
3029 retval = wnd->helpContext;
3030 WIN_ReleaseWndPtr(wnd);
3031 return retval;
3035 /*******************************************************************
3036 * SetWindowContextHelpId (USER32.515)
3038 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3040 WND *wnd = WIN_FindWndPtr( hwnd );
3041 if (!wnd) return FALSE;
3042 wnd->helpContext = id;
3043 WIN_ReleaseWndPtr(wnd);
3044 return TRUE;
3048 /*******************************************************************
3049 * DRAG_QueryUpdate
3051 * recursively find a child that contains spDragInfo->pt point
3052 * and send WM_QUERYDROPOBJECT
3054 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3056 BOOL16 wParam,bResult = 0;
3057 POINT pt;
3058 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3059 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3060 RECT tempRect;
3062 if( !ptrQueryWnd || !ptrDragInfo )
3064 WIN_ReleaseWndPtr(ptrQueryWnd);
3065 return 0;
3068 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3070 GetWindowRect(hQueryWnd,&tempRect);
3072 if( !PtInRect(&tempRect,pt) ||
3073 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3075 WIN_ReleaseWndPtr(ptrQueryWnd);
3076 return 0;
3079 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3081 tempRect = ptrQueryWnd->rectClient;
3082 if(ptrQueryWnd->dwStyle & WS_CHILD)
3083 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3084 (LPPOINT)&tempRect, 2 );
3086 if (PtInRect( &tempRect, pt))
3088 wParam = 0;
3090 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3092 if( ptrWnd->dwStyle & WS_VISIBLE )
3094 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3095 if (PtInRect( &tempRect, pt )) break;
3099 if(ptrWnd)
3101 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3102 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3103 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3104 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3105 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3107 WIN_ReleaseWndPtr(ptrWnd);
3110 if(bResult)
3112 WIN_ReleaseWndPtr(ptrQueryWnd);
3113 return bResult;
3116 else wParam = 1;
3118 else wParam = 1;
3120 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3122 ptrDragInfo->hScope = hQueryWnd;
3124 bResult = ( bNoSend )
3125 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3126 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3127 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3128 if( !bResult )
3129 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3131 WIN_ReleaseWndPtr(ptrQueryWnd);
3132 return bResult;
3136 /*******************************************************************
3137 * DragDetect (USER.465)
3139 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3141 POINT pt32;
3142 CONV_POINT16TO32( &pt, &pt32 );
3143 return DragDetect( hWnd, pt32 );
3146 /*******************************************************************
3147 * DragDetect32 (USER32.151)
3149 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3151 MSG16 msg;
3152 RECT16 rect;
3154 rect.left = pt.x - wDragWidth;
3155 rect.right = pt.x + wDragWidth;
3157 rect.top = pt.y - wDragHeight;
3158 rect.bottom = pt.y + wDragHeight;
3160 SetCapture(hWnd);
3162 while(1)
3164 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3166 if( msg.message == WM_LBUTTONUP )
3168 ReleaseCapture();
3169 return 0;
3171 if( msg.message == WM_MOUSEMOVE )
3173 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3175 ReleaseCapture();
3176 return 1;
3180 WaitMessage();
3182 return 0;
3185 /******************************************************************************
3186 * DragObject16 (USER.464)
3188 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3189 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3191 MSG16 msg;
3192 LPDRAGINFO lpDragInfo;
3193 SEGPTR spDragInfo;
3194 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3195 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3196 WND *wndPtr = WIN_FindWndPtr(hWnd);
3197 HCURSOR16 hCurrentCursor = 0;
3198 HWND16 hCurrentWnd = 0;
3200 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3201 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3203 if( !lpDragInfo || !spDragInfo )
3205 WIN_ReleaseWndPtr(wndPtr);
3206 return 0L;
3209 hBummer = LoadCursor16(0, IDC_BUMMER16);
3211 if( !hBummer || !wndPtr )
3213 GlobalFree16(hDragInfo);
3214 WIN_ReleaseWndPtr(wndPtr);
3215 return 0L;
3218 if(hCursor)
3220 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3222 GlobalFree16(hDragInfo);
3223 WIN_ReleaseWndPtr(wndPtr);
3224 return 0L;
3227 if( hDragCursor == hCursor ) hDragCursor = 0;
3228 else hCursor = hDragCursor;
3230 hOldCursor = SetCursor(hDragCursor);
3233 lpDragInfo->hWnd = hWnd;
3234 lpDragInfo->hScope = 0;
3235 lpDragInfo->wFlags = wObj;
3236 lpDragInfo->hList = szList; /* near pointer! */
3237 lpDragInfo->hOfStruct = hOfStruct;
3238 lpDragInfo->l = 0L;
3240 SetCapture(hWnd);
3241 ShowCursor( TRUE );
3245 do{ WaitMessage(); }
3246 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3248 *(lpDragInfo+1) = *lpDragInfo;
3250 lpDragInfo->pt = msg.pt;
3252 /* update DRAGINFO struct */
3253 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3255 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3256 hCurrentCursor = hCursor;
3257 else
3259 hCurrentCursor = hBummer;
3260 lpDragInfo->hScope = 0;
3262 if( hCurrentCursor )
3263 SetCursor(hCurrentCursor);
3265 /* send WM_DRAGLOOP */
3266 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3267 (LPARAM) spDragInfo );
3268 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3269 if( hCurrentWnd != lpDragInfo->hScope )
3271 if( hCurrentWnd )
3272 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3273 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3274 HIWORD(spDragInfo)) );
3275 hCurrentWnd = lpDragInfo->hScope;
3276 if( hCurrentWnd )
3277 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3279 else
3280 if( hCurrentWnd )
3281 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3283 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3285 ReleaseCapture();
3286 ShowCursor( FALSE );
3288 if( hCursor )
3290 SetCursor( hOldCursor );
3291 if (hDragCursor) DestroyCursor( hDragCursor );
3294 if( hCurrentCursor != hBummer )
3295 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3296 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3297 else
3298 msg.lParam = 0;
3299 GlobalFree16(hDragInfo);
3300 WIN_ReleaseWndPtr(wndPtr);
3302 return (DWORD)(msg.lParam);