Release 960616
[wine/multimedia.git] / windows / win.c
blobc6e5188cffb040a69c522b4e78ce587bbc4ac457
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "sysmetrics.h"
18 #include "cursoricon.h"
19 #include "heap.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "string32.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "color.h"
28 #include "shm_main_blk.h"
29 #include "dde_proc.h"
30 #include "callback.h"
31 #include "clipboard.h"
32 #include "winproc.h"
33 #include "stddebug.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
36 #include "debug.h"
38 /* Desktop window */
39 static WND *pWndDesktop = NULL;
41 static HWND hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR CURSORICON_IconToCursor(HICON);
47 extern HQUEUE QUEUE_GetDoomedQueue();
49 /***********************************************************************
50 * WIN_FindWndPtr
52 * Return a pointer to the WND structure corresponding to a HWND.
54 WND * WIN_FindWndPtr( HWND hwnd )
56 WND * ptr;
58 if (!hwnd) return NULL;
59 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
60 if (ptr->dwMagic != WND_MAGIC) return NULL;
61 if (ptr->hwndSelf != hwnd)
63 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
64 hwnd, ptr->hwndSelf );
65 return NULL;
67 return ptr;
71 /***********************************************************************
72 * WIN_DumpWindow
74 * Dump the content of a window structure to stderr.
76 void WIN_DumpWindow( HWND hwnd )
78 WND *ptr;
79 char className[80];
80 int i;
82 if (!(ptr = WIN_FindWndPtr( hwnd )))
84 fprintf( stderr, "%04x is not a window handle\n", hwnd );
85 return;
88 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
89 strcpy( className, "#NULL#" );
91 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
92 fprintf( stderr,
93 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
94 "inst=%04x taskQ=%04x updRgn=%04x active=%04x hdce=%04x idmenu=%04x\n"
95 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
96 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
97 "sysmenu=%04x flags=%04x props=%04x vscroll=%04x hscroll=%04x\n",
98 ptr->next, ptr->child, ptr->parent, ptr->owner,
99 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
100 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
101 ptr->dwStyle, ptr->dwExStyle, ptr->winproc,
102 ptr->text ? ptr->text : "",
103 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
104 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
105 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
106 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
107 ptr->flags, ptr->hProp, ptr->hVScroll, ptr->hHScroll );
109 if (ptr->class->cbWndExtra)
111 fprintf( stderr, "extra bytes:" );
112 for (i = 0; i < ptr->class->cbWndExtra; i++)
113 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
114 fprintf( stderr, "\n" );
116 fprintf( stderr, "\n" );
120 /***********************************************************************
121 * WIN_WalkWindows
123 * Walk the windows tree and print each window on stderr.
125 void WIN_WalkWindows( HWND hwnd, int indent )
127 WND *ptr;
128 char className[80];
130 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
131 if (!ptr)
133 fprintf( stderr, "*** Invalid window handle\n" );
134 return;
137 if (!indent) /* first time around */
138 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
139 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
141 while (ptr)
143 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
145 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
147 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
148 (DWORD)ptr, ptr->hmemTaskQ, className,
149 (unsigned) ptr->dwStyle, ptr->winproc );
151 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
152 ptr = ptr->next;
157 /***********************************************************************
158 * WIN_GetXWindow
160 * Return the X window associated to a window.
162 Window WIN_GetXWindow( HWND hwnd )
164 WND *wndPtr = WIN_FindWndPtr( hwnd );
165 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
166 return wndPtr ? wndPtr->window : 0;
170 /***********************************************************************
171 * WIN_UnlinkWindow
173 * Remove a window from the siblings linked list.
175 BOOL WIN_UnlinkWindow( HWND hwnd )
177 WND *wndPtr, **ppWnd;
179 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
180 ppWnd = &wndPtr->parent->child;
181 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
182 *ppWnd = wndPtr->next;
183 return TRUE;
187 /***********************************************************************
188 * WIN_LinkWindow
190 * Insert a window into the siblings linked list.
191 * The window is inserted after the specified window, which can also
192 * be specified as HWND_TOP or HWND_BOTTOM.
194 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
196 WND *wndPtr, **ppWnd;
198 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
200 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
202 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
203 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
204 while (*ppWnd) ppWnd = &(*ppWnd)->next;
206 else /* Normal case */
208 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
209 if (!afterPtr) return FALSE;
210 ppWnd = &afterPtr->next;
212 wndPtr->next = *ppWnd;
213 *ppWnd = wndPtr;
214 return TRUE;
218 /***********************************************************************
219 * WIN_FindWinToRepaint
221 * Find a window that needs repaint.
223 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE hQueue )
225 HWND hwndRet;
226 WND *pWnd = pWndDesktop;
228 /* Note: the desktop window never gets WM_PAINT messages */
229 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
231 for ( ; pWnd ; pWnd = pWnd->next )
233 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
235 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
236 pWnd->hwndSelf );
237 continue;
239 if ((pWnd->hmemTaskQ == hQueue) &&
240 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
242 if (pWnd->child )
243 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
244 return hwndRet;
247 if (!pWnd) return 0;
249 hwndRet = pWnd->hwndSelf;
251 /* look among siblings if we got a transparent window */
252 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
253 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
255 pWnd = pWnd->next;
257 if (pWnd) hwndRet = pWnd->hwndSelf;
258 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
259 return hwndRet;
263 /***********************************************************************
264 * WIN_SendParentNotify
266 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
267 * the window has the WS_EX_NOPARENTNOTIFY style.
269 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
271 LPPOINT16 lppt = (LPPOINT16)&lValue;
272 WND *wndPtr = WIN_FindWndPtr( hwnd );
273 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
275 /* if lValue contains cursor coordinates they have to be
276 * mapped to the client area of parent window */
278 if (bMouse) MapWindowPoints16(0, hwnd, lppt, 1);
279 #ifndef WINELIB32
280 else lValue = MAKELONG( LOWORD(lValue), idChild );
281 #endif
283 while (wndPtr)
285 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
286 !(wndPtr->dwStyle & WS_CHILD)) break;
288 if (bMouse)
290 lppt->x += wndPtr->rectClient.left;
291 lppt->y += wndPtr->rectClient.top;
294 wndPtr = wndPtr->parent;
295 #ifdef WINELIB32
296 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
297 MAKEWPARAM( event, idChild ), lValue );
298 #else
299 SendMessage16( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
300 #endif
305 /***********************************************************************
306 * WIN_SetWndProc
308 * Set the window procedure and return the old one.
310 static HANDLE32 WIN_SetWndProc( WND *pWnd, HANDLE32 proc, WINDOWPROCTYPE type)
312 HANDLE32 oldProc = pWnd->winproc;
313 pWnd->winproc = WINPROC_AllocWinProc( proc, type );
314 if (oldProc) WINPROC_FreeWinProc( oldProc );
315 return oldProc;
319 /***********************************************************************
320 * WIN_DestroyWindow
322 * Destroy storage associated to a window
324 static void WIN_DestroyWindow( HWND hwnd )
326 WND *wndPtr = WIN_FindWndPtr( hwnd );
328 #ifdef CONFIG_IPC
329 if (main_block)
330 DDE_DestroyWindow(hwnd);
331 #endif /* CONFIG_IPC */
333 if (!wndPtr) return;
334 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
335 TIMER_RemoveWindowTimers( hwnd );
336 wndPtr->dwMagic = 0; /* Mark it as invalid */
337 wndPtr->hwndSelf = 0;
338 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
340 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
341 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
343 if (!(wndPtr->dwStyle & WS_CHILD))
345 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
347 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
348 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
349 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
350 WIN_SetWndProc( wndPtr, (HANDLE32)0, WIN_PROC_16 );
351 wndPtr->class->cWindows--;
352 USER_HEAP_FREE( hwnd );
356 /***********************************************************************
357 * WIN_DestroyQueueWindows
359 void WIN_DestroyQueueWindows( WND* wnd, HQUEUE hQueue )
361 WND* next;
363 while (wnd)
365 next = wnd->next;
366 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
367 else WIN_DestroyQueueWindows( wnd->child, hQueue );
368 wnd = next;
373 /***********************************************************************
374 * WIN_CreateDesktopWindow
376 * Create the desktop window.
378 BOOL WIN_CreateDesktopWindow(void)
380 CLASS *class;
381 HDC hdc;
382 HWND hwndDesktop;
384 dprintf_win(stddeb,"Creating desktop window\n");
386 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
387 return FALSE;
389 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
390 if (!hwndDesktop) return FALSE;
391 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
393 pWndDesktop->next = NULL;
394 pWndDesktop->child = NULL;
395 pWndDesktop->parent = NULL;
396 pWndDesktop->owner = NULL;
397 pWndDesktop->class = class;
398 pWndDesktop->winproc = WINPROC_CopyWinProc( class->winproc );
399 pWndDesktop->dwMagic = WND_MAGIC;
400 pWndDesktop->hwndSelf = hwndDesktop;
401 pWndDesktop->hInstance = 0;
402 pWndDesktop->rectWindow.left = 0;
403 pWndDesktop->rectWindow.top = 0;
404 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
405 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
406 pWndDesktop->rectClient = pWndDesktop->rectWindow;
407 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
408 pWndDesktop->ptIconPos.x = -1;
409 pWndDesktop->ptIconPos.y = -1;
410 pWndDesktop->ptMaxPos.x = -1;
411 pWndDesktop->ptMaxPos.y = -1;
412 pWndDesktop->text = NULL;
413 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
414 pWndDesktop->hrgnUpdate = 0;
415 pWndDesktop->hwndLastActive = hwndDesktop;
416 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
417 WS_CLIPSIBLINGS;
418 pWndDesktop->dwExStyle = 0;
419 pWndDesktop->hdce = 0;
420 pWndDesktop->hVScroll = 0;
421 pWndDesktop->hHScroll = 0;
422 pWndDesktop->wIDmenu = 0;
423 pWndDesktop->flags = 0;
424 pWndDesktop->window = rootWindow;
425 pWndDesktop->hSysMenu = 0;
426 pWndDesktop->hProp = 0;
427 pWndDesktop->userdata = 0;
429 EVENT_RegisterWindow( pWndDesktop );
430 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
431 if ((hdc = GetDC( hwndDesktop )) != 0)
433 SendMessage32A( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
434 ReleaseDC( hwndDesktop, hdc );
436 return TRUE;
440 /***********************************************************************
441 * WIN_CreateWindowEx
443 * Implementation of CreateWindowEx().
445 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
446 BOOL unicode )
448 CLASS *classPtr;
449 WND *wndPtr;
450 HWND16 hwnd;
451 POINT16 maxSize, maxPos, minTrack, maxTrack;
452 LRESULT wmcreate;
454 dprintf_win( stddeb, "CreateWindowEx: " );
455 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
456 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
457 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
458 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
460 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
461 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
462 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
464 /* Find the parent window */
466 if (cs->hwndParent)
468 /* Make sure parent is valid */
469 if (!IsWindow( cs->hwndParent ))
471 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
472 return 0;
475 else if (cs->style & WS_CHILD)
477 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
478 return 0; /* WS_CHILD needs a parent */
481 /* Find the window class */
483 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
484 GetExePtr(cs->hInstance) )))
486 char buffer[256];
487 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
488 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
489 return 0;
492 /* Fix the coordinates */
494 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
495 if (cs->cx == CW_USEDEFAULT32)
497 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
498 else */
500 cs->cx = 600;
501 cs->cy = 400;
505 /* Create the window structure */
507 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
508 - sizeof(wndPtr->wExtra) )))
510 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
511 return 0;
514 /* Fill the window structure */
516 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
517 wndPtr->next = NULL;
518 wndPtr->child = NULL;
519 wndPtr->parent = (cs->style & WS_CHILD) ?
520 WIN_FindWndPtr( cs->hwndParent ) : pWndDesktop;
521 wndPtr->owner = (cs->style & WS_CHILD) ? NULL :
522 WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
523 wndPtr->window = 0;
524 wndPtr->class = classPtr;
525 wndPtr->winproc = WINPROC_CopyWinProc( classPtr->winproc );
526 wndPtr->dwMagic = WND_MAGIC;
527 wndPtr->hwndSelf = hwnd;
528 wndPtr->hInstance = cs->hInstance;
529 wndPtr->ptIconPos.x = -1;
530 wndPtr->ptIconPos.y = -1;
531 wndPtr->ptMaxPos.x = -1;
532 wndPtr->ptMaxPos.y = -1;
533 wndPtr->text = NULL;
534 wndPtr->hmemTaskQ = GetTaskQueue(0);
535 wndPtr->hrgnUpdate = 0;
536 wndPtr->hwndLastActive = hwnd;
537 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
538 wndPtr->dwExStyle = cs->dwExStyle;
539 wndPtr->wIDmenu = 0;
540 wndPtr->flags = 0;
541 wndPtr->hVScroll = 0;
542 wndPtr->hHScroll = 0;
543 wndPtr->hSysMenu = MENU_GetDefSysMenu();
544 wndPtr->hProp = 0;
545 wndPtr->userdata = 0;
547 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
548 classPtr->cWindows++;
550 /* Correct the window style */
552 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
554 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
555 wndPtr->flags |= WIN_NEED_SIZE;
557 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
559 /* Get class or window DC if needed */
561 if (classPtr->style & CS_OWNDC) wndPtr->hdce = DCE_AllocDCE(hwnd, DCE_WINDOW_DC);
562 else if (classPtr->style & CS_CLASSDC) wndPtr->hdce = classPtr->hdce;
563 else wndPtr->hdce = 0;
565 /* Insert the window in the linked list */
567 WIN_LinkWindow( hwnd, HWND_TOP );
569 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
571 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
573 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
574 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
575 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
577 if (cs->cx <= 0) cs->cx = 1;
578 if (cs->cy <= 0) cs->cy = 1;
580 wndPtr->rectWindow.left = cs->x;
581 wndPtr->rectWindow.top = cs->y;
582 wndPtr->rectWindow.right = cs->x + cs->cx;
583 wndPtr->rectWindow.bottom = cs->y + cs->cy;
584 wndPtr->rectClient = wndPtr->rectWindow;
585 wndPtr->rectNormal = wndPtr->rectWindow;
587 /* Create the X window (only for top-level windows, and then only */
588 /* when there's no desktop window) */
590 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
592 XSetWindowAttributes win_attr;
593 Atom XA_WM_DELETE_WINDOW;
595 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
596 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
598 win_attr.event_mask = ExposureMask | KeyPressMask |
599 KeyReleaseMask | PointerMotionMask |
600 ButtonPressMask | ButtonReleaseMask |
601 FocusChangeMask | StructureNotifyMask;
602 win_attr.override_redirect = FALSE;
603 wndPtr->flags |= WIN_MANAGED;
605 else
607 win_attr.event_mask = ExposureMask | KeyPressMask |
608 KeyReleaseMask | PointerMotionMask |
609 ButtonPressMask | ButtonReleaseMask |
610 FocusChangeMask;
611 win_attr.override_redirect = TRUE;
613 win_attr.colormap = COLOR_WinColormap;
614 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
615 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
616 win_attr.cursor = CURSORICON_XCursor;
617 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
618 cs->cx, cs->cy, 0, CopyFromParent,
619 InputOutput, CopyFromParent,
620 CWEventMask | CWOverrideRedirect |
621 CWColormap | CWCursor | CWSaveUnder |
622 CWBackingStore, &win_attr );
623 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
624 False );
625 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
626 if (cs->hwndParent) /* Get window owner */
628 Window win = WIN_GetXWindow( cs->hwndParent );
629 if (win) XSetTransientForHint( display, wndPtr->window, win );
631 EVENT_RegisterWindow( wndPtr );
634 /* Set the window menu */
636 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
638 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
639 else
641 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
642 if (classPtr->menuNameA)
643 cs->hMenu = HIWORD(classPtr->menuNameA) ?
644 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
645 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
646 #else
647 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
648 if (menuName) cs->hMenu = LoadMenu( cs->hInstance, menuName );
649 #endif
651 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
653 else wndPtr->wIDmenu = (UINT)cs->hMenu;
655 /* Send the WM_CREATE message */
657 if (unicode)
659 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
660 else
662 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
663 NULL, NULL, 0, &wndPtr->rectClient );
664 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
667 else
669 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
670 else
672 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
673 NULL, NULL, 0, &wndPtr->rectClient );
674 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
678 if (wmcreate == -1)
680 /* Abort window creation */
681 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
682 WIN_DestroyWindow( hwnd );
683 return 0;
686 /* Send the size messages */
688 if (!(wndPtr->flags & WIN_NEED_SIZE))
690 /* send it anyway */
691 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
692 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
693 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
694 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
695 wndPtr->rectClient.top ));
698 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
699 if (!IsWindow(hwnd)) return 0;
701 /* Show the window, maximizing or minimizing if needed */
703 if (wndPtr->dwStyle & WS_MINIMIZE)
705 wndPtr->dwStyle &= ~WS_MAXIMIZE;
706 WINPOS_FindIconPos( hwnd );
707 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
708 SYSMETRICS_CXICON, SYSMETRICS_CYICON, SWP_FRAMECHANGED |
709 (cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
711 else if (wndPtr->dwStyle & WS_MAXIMIZE)
713 POINT16 maxSize, maxPos, minTrack, maxTrack;
714 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
715 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
716 SWP_FRAMECHANGED | (cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
718 else if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
720 /* Call WH_SHELL hook */
722 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
723 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
725 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
726 return hwnd;
730 /***********************************************************************
731 * CreateWindow16 (USER.41)
733 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
734 DWORD style, INT16 x, INT16 y, INT16 width,
735 INT16 height, HWND16 parent, HMENU16 menu,
736 HINSTANCE16 instance, LPVOID data )
738 return CreateWindowEx16( 0, className, windowName, style,
739 x, y, width, height, parent, menu, instance, data );
743 /***********************************************************************
744 * CreateWindowEx16 (USER.452)
746 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
747 DWORD style, INT16 x, INT16 y, INT16 width,
748 INT16 height, HWND16 parent, HMENU16 menu,
749 HINSTANCE16 instance, LPVOID data )
751 ATOM classAtom;
752 CREATESTRUCT32A cs;
754 /* Find the class atom */
756 if (!(classAtom = GlobalFindAtom32A( className )))
758 fprintf( stderr, "CreateWindowEx16: bad class name " );
759 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
760 else fprintf( stderr, "'%s'\n", className );
761 return 0;
764 /* Fix the coordinates */
766 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
767 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
768 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
769 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
771 /* Create the window */
773 cs.lpCreateParams = data;
774 cs.hInstance = (HINSTANCE32)instance;
775 cs.hMenu = (HMENU32)menu;
776 cs.hwndParent = (HWND32)parent;
777 cs.style = style;
778 cs.lpszName = windowName;
779 cs.lpszClass = className;
780 cs.dwExStyle = exStyle;
781 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
785 /***********************************************************************
786 * CreateWindowEx32A (USER32.82)
788 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
789 DWORD style, INT32 x, INT32 y, INT32 width,
790 INT32 height, HWND32 parent, HMENU32 menu,
791 HINSTANCE32 instance, LPVOID data )
793 ATOM classAtom;
794 CREATESTRUCT32A cs;
796 /* Find the class atom */
798 if (!(classAtom = GlobalFindAtom32A( className )))
800 fprintf( stderr, "CreateWindowEx32A: bad class name " );
801 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
802 else fprintf( stderr, "'%s'\n", className );
803 return 0;
806 /* Create the window */
808 cs.lpCreateParams = data;
809 cs.hInstance = instance;
810 cs.hMenu = menu;
811 cs.hwndParent = parent;
812 cs.x = x;
813 cs.y = y;
814 cs.cx = width;
815 cs.cy = height;
816 cs.style = style;
817 cs.lpszName = windowName;
818 cs.lpszClass = className;
819 cs.dwExStyle = exStyle;
820 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
824 /***********************************************************************
825 * CreateWindowEx32W (USER32.83)
827 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
828 DWORD style, INT32 x, INT32 y, INT32 width,
829 INT32 height, HWND32 parent, HMENU32 menu,
830 HINSTANCE32 instance, LPVOID data )
832 ATOM classAtom;
833 CREATESTRUCT32W cs;
835 /* Find the class atom */
837 if (!(classAtom = GlobalFindAtom32W( className )))
839 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
840 return 0;
843 /* Create the window */
845 cs.lpCreateParams = data;
846 cs.hInstance = instance;
847 cs.hMenu = menu;
848 cs.hwndParent = parent;
849 cs.x = x;
850 cs.y = y;
851 cs.cx = width;
852 cs.cy = height;
853 cs.style = style;
854 cs.lpszName = windowName;
855 cs.lpszClass = className;
856 cs.dwExStyle = exStyle;
857 /* Note: we rely on the fact that CREATESTRUCT32A and */
858 /* CREATESTRUCT32W have the same layout. */
859 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
863 /***********************************************************************
864 * DestroyWindow (USER.53)
866 BOOL DestroyWindow( HWND hwnd )
868 WND * wndPtr;
870 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
872 /* Initialization */
874 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
875 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
877 /* Top-level window */
879 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
881 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
882 /* FIXME: clean up palette - see "Internals" p.352 */
885 /* Hide the window */
887 if (wndPtr->dwStyle & WS_VISIBLE)
888 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
889 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
890 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
891 ReleaseCapture();
892 if (!QUEUE_GetDoomedQueue())
893 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
895 /* Recursively destroy owned windows */
897 for (;;)
899 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
900 while (siblingPtr)
902 if (siblingPtr->owner == wndPtr) break;
903 siblingPtr = siblingPtr->next;
905 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
906 else break;
909 CLIPBOARD_DisOwn( hwnd );
911 /* Send destroy messages and destroy children */
913 SendMessage16( hwnd, WM_DESTROY, 0, 0 );
914 while (wndPtr->child) /* The child removes itself from the list */
915 DestroyWindow( wndPtr->child->hwndSelf );
916 SendMessage16( hwnd, WM_NCDESTROY, 0, 0 );
918 /* Destroy the window */
920 WIN_DestroyWindow( hwnd );
921 return TRUE;
925 /***********************************************************************
926 * CloseWindow (USER.43)
928 BOOL CloseWindow(HWND hWnd)
930 WND * wndPtr = WIN_FindWndPtr(hWnd);
931 if (wndPtr->dwStyle & WS_CHILD) return TRUE;
932 ShowWindow(hWnd, SW_MINIMIZE);
933 return TRUE;
937 /***********************************************************************
938 * OpenIcon (USER.44)
940 BOOL OpenIcon(HWND hWnd)
942 if (!IsIconic(hWnd)) return FALSE;
943 ShowWindow(hWnd, SW_SHOWNORMAL);
944 return(TRUE);
948 /***********************************************************************
949 * WIN_FindWindow
951 * Implementation of FindWindow() and FindWindowEx().
953 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
954 LPCSTR title )
956 WND *pWnd;
957 CLASS *pClass = NULL;
959 if (child)
961 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
962 if (parent)
964 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
966 else if (pWnd->parent != pWndDesktop) return 0;
967 pWnd = pWnd->next;
969 else
971 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
972 pWnd = pWnd->child;
974 if (!pWnd) return 0;
976 /* For a child window, all siblings will have the same hInstance, */
977 /* so we can look for the class once and for all. */
979 if (className && (pWnd->dwStyle & WS_CHILD))
981 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
982 return 0;
985 for ( ; pWnd; pWnd = pWnd->next)
987 if (className && !(pWnd->dwStyle & WS_CHILD))
989 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
990 continue; /* Skip this window */
992 if (pClass && (pWnd->class != pClass))
993 continue; /* Not the right class */
995 /* Now check the title */
997 if (!title) return pWnd->hwndSelf;
998 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1000 return 0;
1005 /***********************************************************************
1006 * FindWindow16 (USER.50)
1008 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1010 return FindWindowEx16( 0, 0, className, title );
1014 /***********************************************************************
1015 * FindWindowEx16 (USER.427)
1017 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1018 SEGPTR className, LPCSTR title )
1020 ATOM atom;
1022 atom = className ? GlobalFindAtom16( className ) : 0;
1023 return WIN_FindWindow( parent, child, atom, title );
1027 /***********************************************************************
1028 * FindWindow32A (USER32.197)
1030 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1032 return FindWindowEx32A( 0, 0, className, title );
1036 /***********************************************************************
1037 * FindWindowEx32A (USER32.198)
1039 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1040 LPCSTR className, LPCSTR title )
1042 ATOM atom;
1044 atom = className ? GlobalFindAtom32A( className ) : 0;
1045 return WIN_FindWindow( 0, 0, atom, title );
1049 /***********************************************************************
1050 * FindWindowEx32W (USER32.199)
1052 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1053 LPCWSTR className, LPCWSTR title )
1055 ATOM atom;
1056 char *buffer;
1057 HWND hwnd;
1059 atom = className ? GlobalFindAtom32W( className ) : 0;
1060 buffer = STRING32_DupUniToAnsi( title );
1061 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1062 free( buffer );
1063 return hwnd;
1067 /***********************************************************************
1068 * FindWindow32W (USER32.200)
1070 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1072 return FindWindowEx32W( 0, 0, className, title );
1076 /**********************************************************************
1077 * WIN_GetDesktop
1079 WND *WIN_GetDesktop(void)
1081 return pWndDesktop;
1085 /**********************************************************************
1086 * GetDesktopWindow (USER.286)
1088 HWND GetDesktopWindow(void)
1090 return pWndDesktop->hwndSelf;
1094 /**********************************************************************
1095 * GetDesktopHwnd (USER.278)
1097 * Exactly the same thing as GetDesktopWindow(), but not documented.
1098 * Don't ask me why...
1100 HWND GetDesktopHwnd(void)
1102 return pWndDesktop->hwndSelf;
1106 /*******************************************************************
1107 * EnableWindow (USER.34)
1109 BOOL EnableWindow( HWND hwnd, BOOL enable )
1111 WND *wndPtr;
1113 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1114 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1116 /* Enable window */
1117 wndPtr->dwStyle &= ~WS_DISABLED;
1118 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1119 return TRUE;
1121 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1123 /* Disable window */
1124 wndPtr->dwStyle |= WS_DISABLED;
1125 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1126 SetFocus( 0 ); /* A disabled window can't have the focus */
1127 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1128 ReleaseCapture(); /* A disabled window can't capture the mouse */
1129 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1130 return FALSE;
1132 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1136 /***********************************************************************
1137 * IsWindowEnabled (USER.35) (USER32.348)
1139 BOOL IsWindowEnabled(HWND hWnd)
1141 WND * wndPtr;
1143 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1144 return !(wndPtr->dwStyle & WS_DISABLED);
1148 /***********************************************************************
1149 * IsWindowUnicode (USER32.349)
1151 BOOL IsWindowUnicode( HWND hwnd )
1153 WND * wndPtr;
1155 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1156 return (WINPROC_GetWinProcType( wndPtr->winproc ) == WIN_PROC_32W);
1160 /**********************************************************************
1161 * GetWindowWord (USER.133) (USER32.313)
1163 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1165 WND * wndPtr = WIN_FindWndPtr( hwnd );
1166 if (!wndPtr) return 0;
1167 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1168 switch(offset)
1170 case GWW_ID: return wndPtr->wIDmenu;
1171 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1172 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1173 default:
1174 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1175 return 0;
1180 /**********************************************************************
1181 * WIN_GetWindowInstance
1183 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
1185 WND * wndPtr = WIN_FindWndPtr( hwnd );
1186 if (!wndPtr) return (HINSTANCE)0;
1187 return wndPtr->hInstance;
1191 /**********************************************************************
1192 * SetWindowWord (USER.134) (USER32.523)
1194 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1196 WORD *ptr, retval;
1197 WND * wndPtr = WIN_FindWndPtr( hwnd );
1198 if (!wndPtr) return 0;
1199 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1200 else switch(offset)
1202 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1203 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1204 default:
1205 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1206 return 0;
1208 retval = *ptr;
1209 *ptr = newval;
1210 return retval;
1214 /**********************************************************************
1215 * GetWindowLong16 (USER.135)
1217 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1219 LONG ret = GetWindowLong32A( (HWND32)hwnd, offset );
1220 if (offset == GWL_WNDPROC) return (LONG)WINPROC_GetFunc16( (HANDLE32)ret );
1221 return ret;
1225 /**********************************************************************
1226 * GetWindowLong32A (USER32.304)
1228 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1230 WND * wndPtr = WIN_FindWndPtr( hwnd );
1231 if (!wndPtr) return 0;
1232 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
1233 switch(offset)
1235 case GWL_USERDATA: return wndPtr->userdata;
1236 case GWL_STYLE: return wndPtr->dwStyle;
1237 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1238 case GWL_ID: return wndPtr->wIDmenu;
1239 case GWL_WNDPROC: return (LONG)WINPROC_GetFunc32( wndPtr->winproc );
1240 case GWL_HWNDPARENT: return wndPtr->parent ?
1241 (HWND32)wndPtr->parent->hwndSelf : 0;
1242 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1243 default:
1244 fprintf( stderr, "GetWindowLong32A: unknown offset %d\n", offset );
1246 return 0;
1250 /**********************************************************************
1251 * GetWindowLong32W (USER32.305)
1253 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1255 return GetWindowLong32A( hwnd, offset );
1259 /**********************************************************************
1260 * SetWindowLong16 (USER.136)
1262 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1264 if (offset == GWL_WNDPROC)
1266 HANDLE32 ret;
1267 WND *wndPtr = WIN_FindWndPtr( hwnd );
1268 if (!wndPtr) return 0;
1269 ret = WIN_SetWndProc( wndPtr, (HANDLE32)newval, WIN_PROC_16 );
1270 return (LONG)WINPROC_GetFunc16( ret );
1272 return SetWindowLong32A( hwnd, offset, newval );
1276 /**********************************************************************
1277 * SetWindowLong32A (USER32.516)
1279 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1281 LONG *ptr, retval;
1282 WND * wndPtr = WIN_FindWndPtr( hwnd );
1283 if (!wndPtr) return 0;
1284 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1285 else switch(offset)
1287 case GWL_ID:
1288 case GWL_HINSTANCE:
1289 return SetWindowWord( hwnd, offset, (WORD)newval );
1290 case GWL_WNDPROC:
1291 return (LONG)WINPROC_GetFunc32( WIN_SetWndProc( wndPtr,
1292 (HANDLE32)newval,
1293 WIN_PROC_32A ));
1294 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1295 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
1296 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1297 default:
1298 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1299 return 0;
1301 retval = *ptr;
1302 *ptr = newval;
1303 return retval;
1307 /**********************************************************************
1308 * SetWindowLong32W (USER32.517)
1310 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1312 if (offset == GCL_WNDPROC)
1314 WND *wndPtr = WIN_FindWndPtr( hwnd );
1315 if (!wndPtr) return 0;
1316 return (LONG)WINPROC_GetFunc32( WIN_SetWndProc( wndPtr,
1317 (HANDLE32)newval,
1318 WIN_PROC_32W ));
1320 return SetWindowLong32A( hwnd, offset, newval );
1324 /*******************************************************************
1325 * GetWindowText16 (USER.36)
1327 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1329 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1333 /*******************************************************************
1334 * GetWindowText32A (USER32.308)
1336 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1338 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1339 (LPARAM)lpString );
1343 /*******************************************************************
1344 * GetWindowText32W (USER32.311)
1346 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1348 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1349 (LPARAM)lpString );
1353 /*******************************************************************
1354 * SetWindowText16 (USER.37)
1356 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1358 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1362 /*******************************************************************
1363 * SetWindowText32A (USER32.)
1365 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1367 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1371 /*******************************************************************
1372 * SetWindowText32W (USER32.)
1374 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1376 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1380 /*******************************************************************
1381 * GetWindowTextLength (USER.38)
1383 int GetWindowTextLength(HWND hwnd)
1385 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1389 /*******************************************************************
1390 * IsWindow (USER.47)
1392 BOOL IsWindow( HWND hwnd )
1394 WND * wndPtr = WIN_FindWndPtr( hwnd );
1395 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1399 /*****************************************************************
1400 * GetParent (USER.46)
1402 HWND GetParent(HWND hwnd)
1404 WND *wndPtr = WIN_FindWndPtr(hwnd);
1405 if (!wndPtr) return 0;
1406 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1407 return wndPtr ? wndPtr->hwndSelf : 0;
1411 /*****************************************************************
1412 * WIN_GetTopParent
1414 * Get the top-level parent for a child window.
1416 HWND WIN_GetTopParent( HWND hwnd )
1418 WND *wndPtr = WIN_FindWndPtr( hwnd );
1419 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1420 return wndPtr ? wndPtr->hwndSelf : 0;
1424 /*****************************************************************
1425 * SetParent (USER.233)
1427 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1429 HWND oldParent;
1431 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1432 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1433 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1435 oldParent = wndPtr->parent->hwndSelf;
1437 WIN_UnlinkWindow(hwndChild);
1438 if (hwndNewParent) wndPtr->parent = pWndParent;
1439 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1441 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1443 return oldParent;
1448 /*******************************************************************
1449 * IsChild (USER.48)
1451 BOOL IsChild( HWND parent, HWND child )
1453 WND * wndPtr = WIN_FindWndPtr( child );
1454 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1456 wndPtr = wndPtr->parent;
1457 if (wndPtr->hwndSelf == parent) return TRUE;
1459 return FALSE;
1463 /***********************************************************************
1464 * IsWindowVisible (USER.49) (USER32.350)
1466 BOOL IsWindowVisible( HWND hwnd )
1468 WND *wndPtr = WIN_FindWndPtr( hwnd );
1469 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1471 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1472 wndPtr = wndPtr->parent;
1474 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1479 /*******************************************************************
1480 * GetTopWindow (USER.229)
1482 HWND GetTopWindow( HWND hwnd )
1484 WND * wndPtr = WIN_FindWndPtr( hwnd );
1485 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1486 else return 0;
1490 /*******************************************************************
1491 * GetWindow (USER.262)
1493 HWND GetWindow( HWND hwnd, WORD rel )
1495 WND * wndPtr = WIN_FindWndPtr( hwnd );
1496 if (!wndPtr) return 0;
1497 switch(rel)
1499 case GW_HWNDFIRST:
1500 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1501 else return 0;
1503 case GW_HWNDLAST:
1504 if (!wndPtr->parent) return 0; /* Desktop window */
1505 while (wndPtr->next) wndPtr = wndPtr->next;
1506 return wndPtr->hwndSelf;
1508 case GW_HWNDNEXT:
1509 if (!wndPtr->next) return 0;
1510 return wndPtr->next->hwndSelf;
1512 case GW_HWNDPREV:
1513 if (!wndPtr->parent) return 0; /* Desktop window */
1514 wndPtr = wndPtr->parent->child; /* First sibling */
1515 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1516 while (wndPtr->next)
1518 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1519 wndPtr = wndPtr->next;
1521 return 0;
1523 case GW_OWNER:
1524 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1526 case GW_CHILD:
1527 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1529 return 0;
1533 /*******************************************************************
1534 * GetNextWindow (USER.230)
1536 HWND GetNextWindow( HWND hwnd, WORD flag )
1538 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1539 return GetWindow( hwnd, flag );
1542 /*******************************************************************
1543 * ShowOwnedPopups (USER.265)
1545 void ShowOwnedPopups( HWND owner, BOOL fShow )
1547 WND *pWnd = pWndDesktop->child;
1548 while (pWnd)
1550 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1551 (pWnd->dwStyle & WS_POPUP))
1552 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1553 pWnd = pWnd->next;
1558 /*******************************************************************
1559 * GetLastActivePopup (USER.287)
1561 HWND GetLastActivePopup(HWND hwnd)
1563 WND *wndPtr;
1564 wndPtr = WIN_FindWndPtr(hwnd);
1565 if (wndPtr == NULL) return hwnd;
1566 return wndPtr->hwndLastActive;
1570 /*******************************************************************
1571 * EnumWindows (USER.54)
1573 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
1575 WND *wndPtr;
1576 HWND *list, *pWnd;
1577 int count;
1579 /* We have to build a list of all windows first, to avoid */
1580 /* unpleasant side-effects, for instance if the callback */
1581 /* function changes the Z-order of the windows. */
1583 /* First count the windows */
1585 count = 0;
1586 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next) count++;
1587 if (!count) return TRUE;
1589 /* Now build the list of all windows */
1591 if (!(pWnd = list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1592 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1593 *pWnd++ = wndPtr->hwndSelf;
1595 /* Now call the callback function for every window */
1597 for (pWnd = list; count > 0; count--, pWnd++)
1599 /* Make sure that window still exists */
1600 if (!IsWindow(*pWnd)) continue;
1601 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1603 free( list );
1604 return TRUE;
1608 /**********************************************************************
1609 * EnumTaskWindows (USER.225)
1611 BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
1613 WND *wndPtr;
1614 HWND *list, *pWnd;
1615 HANDLE hQueue = GetTaskQueue( hTask );
1616 int count;
1618 /* This function is the same as EnumWindows(), */
1619 /* except for an added check on the window queue. */
1621 /* First count the windows */
1623 count = 0;
1624 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1625 if (wndPtr->hmemTaskQ == hQueue) count++;
1626 if (!count) return TRUE;
1628 /* Now build the list of all windows */
1630 if (!(pWnd = list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1631 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1632 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = wndPtr->hwndSelf;
1634 /* Now call the callback function for every window */
1636 for (pWnd = list; count > 0; count--, pWnd++)
1638 /* Make sure that window still exists */
1639 if (!IsWindow(*pWnd)) continue;
1640 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1642 free( list );
1643 return TRUE;
1647 /*******************************************************************
1648 * WIN_EnumChildWin
1650 * o hwnd is the first child to use, loop until all next windows
1651 * are processed
1653 * o call wdnenumprc
1655 * o call ourselves with the next child window
1658 static BOOL WIN_EnumChildWin( WND *wndPtr, FARPROC wndenumprc, LPARAM lParam )
1660 WND *pWndNext, *pWndChild;
1661 while (wndPtr)
1663 pWndNext = wndPtr->next; /* storing hwnd is a way to avoid.. */
1664 pWndChild = wndPtr->child; /* ..side effects after wndenumprc */
1665 if (!CallEnumWindowsProc( wndenumprc, wndPtr->hwndSelf, lParam ))
1666 return 0;
1667 if (pWndChild && IsWindow(pWndChild->hwndSelf))
1668 if (!WIN_EnumChildWin(pWndChild, wndenumprc, lParam)) return 0;
1669 wndPtr = pWndNext;
1671 return 1;
1675 /*******************************************************************
1676 * EnumChildWindows (USER.55)
1678 * o gets the first child of hwnd
1680 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1682 BOOL EnumChildWindows(HWND hwnd, WNDENUMPROC wndenumprc, LPARAM lParam)
1684 WND *wndPtr;
1686 dprintf_enum(stddeb,"EnumChildWindows\n");
1688 if (hwnd == 0) return 0;
1689 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1690 return WIN_EnumChildWin(wndPtr->child, wndenumprc, lParam);
1694 /*******************************************************************
1695 * AnyPopup (USER.52)
1697 BOOL AnyPopup(void)
1699 WND *wndPtr;
1700 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1701 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1702 return FALSE;
1705 /*******************************************************************
1706 * FlashWindow [USER.105]
1708 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1710 WND *wndPtr = WIN_FindWndPtr(hWnd);
1712 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
1714 if (!wndPtr) return FALSE;
1716 if (wndPtr->dwStyle & WS_MINIMIZE)
1718 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1720 HDC hDC = GetDC(hWnd);
1722 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1723 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1725 ReleaseDC( hWnd, hDC );
1726 wndPtr->flags |= WIN_NCACTIVATED;
1728 else
1730 RedrawWindow32( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1731 RDW_UPDATENOW | RDW_FRAME );
1732 wndPtr->flags &= ~WIN_NCACTIVATED;
1734 return TRUE;
1736 else
1738 WPARAM wparam;
1739 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1740 else wparam = (hWnd == GetActiveWindow());
1742 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1743 return wparam;
1748 /*******************************************************************
1749 * SetSysModalWindow [USER.188]
1751 HWND SetSysModalWindow(HWND hWnd)
1753 HWND hWndOldModal = hwndSysModal;
1754 hwndSysModal = hWnd;
1755 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
1756 return hWndOldModal;
1760 /*******************************************************************
1761 * GetSysModalWindow [USER.189]
1763 HWND GetSysModalWindow(void)
1765 return hwndSysModal;
1768 /*******************************************************************
1769 * DRAG_QueryUpdate
1771 * recursively find a child that contains spDragInfo->pt point
1772 * and send WM_QUERYDROPOBJECT
1774 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1776 BOOL wParam,bResult = 0;
1777 POINT16 pt;
1778 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1779 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1780 RECT16 tempRect; /* this sucks */
1782 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1784 pt = ptrDragInfo->pt;
1786 GetWindowRect16(hQueryWnd,&tempRect);
1788 if( !PtInRect16(&tempRect,pt) ||
1789 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1790 return 0;
1792 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1794 tempRect = ptrQueryWnd->rectClient;
1795 if(ptrQueryWnd->dwStyle & WS_CHILD)
1796 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
1798 if( PtInRect16(&tempRect,pt) )
1800 wParam = 0;
1802 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
1803 if( ptrWnd->dwStyle & WS_VISIBLE )
1805 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
1807 if( PtInRect16(&tempRect,pt) )
1808 break;
1811 if(ptrWnd)
1813 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
1814 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
1815 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
1816 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1817 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo);
1820 if(bResult) return bResult;
1822 else wParam = 1;
1824 else wParam = 1;
1826 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
1828 ptrDragInfo->hScope = hQueryWnd;
1830 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
1831 (WPARAM)wParam ,(LPARAM) spDragInfo );
1832 if( !bResult )
1833 ptrDragInfo->pt = pt;
1835 return bResult;
1838 /*******************************************************************
1839 * DragDetect ( USER.465 )
1842 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
1844 MSG16 msg;
1845 RECT16 rect;
1847 rect.left = pt.x - wDragWidth;
1848 rect.right = pt.x + wDragWidth;
1850 rect.top = pt.y - wDragHeight;
1851 rect.bottom = pt.y + wDragHeight;
1853 SetCapture(hWnd);
1855 while(1)
1857 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1859 if( msg.message == WM_LBUTTONUP )
1861 ReleaseCapture();
1862 return 0;
1864 if( msg.message == WM_MOUSEMOVE )
1866 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
1868 ReleaseCapture();
1869 return 1;
1873 WaitMessage();
1876 return 0;
1879 /******************************************************************************
1880 * DragObject ( USER.464 )
1883 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1884 WORD szList , HCURSOR hCursor)
1886 MSG16 msg;
1887 LPDRAGINFO lpDragInfo;
1888 SEGPTR spDragInfo;
1889 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1890 HANDLE hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1891 WND *wndPtr = WIN_FindWndPtr(hWnd);
1892 DWORD dwRet = 0;
1893 short dragDone = 0;
1894 HCURSOR hCurrentCursor = 0;
1895 HWND hCurrentWnd = 0;
1896 WORD btemp;
1898 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1899 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
1901 if( !lpDragInfo || !spDragInfo ) return 0L;
1903 hBummer = LoadCursor(0,IDC_BUMMER);
1905 if( !hBummer || !wndPtr )
1907 GlobalFree16(hDragInfo);
1908 return 0L;
1911 if(hCursor)
1913 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1915 GlobalFree16(hDragInfo);
1916 return 0L;
1919 if( hDragCursor == hCursor ) hDragCursor = 0;
1920 else hCursor = hDragCursor;
1922 hOldCursor = SetCursor(hDragCursor);
1925 lpDragInfo->hWnd = hWnd;
1926 lpDragInfo->hScope = 0;
1927 lpDragInfo->wFlags = wObj;
1928 lpDragInfo->hList = szList; /* near pointer! */
1929 lpDragInfo->hOfStruct = hOfStruct;
1930 lpDragInfo->l = 0L;
1932 SetCapture(hWnd);
1933 ShowCursor(1);
1935 while( !dragDone )
1937 WaitMessage();
1939 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1940 continue;
1942 *(lpDragInfo+1) = *lpDragInfo;
1944 lpDragInfo->pt = msg.pt;
1946 /* update DRAGINFO struct */
1947 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
1949 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1950 hCurrentCursor = hCursor;
1951 else
1953 hCurrentCursor = hBummer;
1954 lpDragInfo->hScope = 0;
1956 if( hCurrentCursor )
1957 SetCursor(hCurrentCursor);
1959 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1961 /* send WM_DRAGLOOP */
1962 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1963 (LPARAM) spDragInfo );
1964 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1965 if( hCurrentWnd != lpDragInfo->hScope )
1967 if( hCurrentWnd )
1968 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
1969 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1970 HIWORD(spDragInfo)) );
1971 hCurrentWnd = lpDragInfo->hScope;
1972 if( hCurrentWnd )
1973 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1975 else
1976 if( hCurrentWnd )
1977 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1980 /* check if we're done */
1981 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1982 dragDone = TRUE;
1985 ReleaseCapture();
1986 ShowCursor(0);
1988 if( hCursor )
1990 SetCursor(hOldCursor);
1991 if( hDragCursor )
1992 DestroyCursor(hDragCursor);
1995 if( hCurrentCursor != hBummer )
1996 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
1997 (WPARAM)hWnd, (LPARAM)spDragInfo );
1998 GlobalFree16(hDragInfo);
2000 return dwRet;