2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xatom.h>
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
24 #include "nonclient.h"
28 #include "shm_main_blk.h"
30 #include "clipboard.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
39 static WND *pWndDesktop = NULL;
41 static HWND32 hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
47 extern HWND32 CARET_GetHwnd(void);
48 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
49 extern void WINPOS_CheckActive(HWND32);
50 extern BOOL32 EVENT_CheckFocus(void);
52 /***********************************************************************
55 * Return a pointer to the WND structure corresponding to a HWND.
57 WND * WIN_FindWndPtr( HWND32 hwnd )
61 if (!hwnd || HIWORD(hwnd)) return NULL;
62 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
63 if (ptr->dwMagic != WND_MAGIC) return NULL;
64 if (ptr->hwndSelf != hwnd)
66 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
67 hwnd, ptr->hwndSelf );
74 /***********************************************************************
77 * Dump the content of a window structure to stderr.
79 void WIN_DumpWindow( HWND32 hwnd )
85 if (!(ptr = WIN_FindWndPtr( hwnd )))
87 fprintf( stderr, "%04x is not a window handle\n", hwnd );
91 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
92 strcpy( className, "#NULL#" );
94 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
96 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
97 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
98 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
99 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
100 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
101 ptr->next, ptr->child, ptr->parent, ptr->owner,
102 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
103 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
104 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
105 ptr->text ? ptr->text : "",
106 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
107 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
108 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
109 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
110 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
112 if (ptr->class->cbWndExtra)
114 fprintf( stderr, "extra bytes:" );
115 for (i = 0; i < ptr->class->cbWndExtra; i++)
116 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
117 fprintf( stderr, "\n" );
119 fprintf( stderr, "\n" );
123 /***********************************************************************
126 * Walk the windows tree and print each window on stderr.
128 void WIN_WalkWindows( HWND32 hwnd, int indent )
133 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
136 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
140 if (!indent) /* first time around */
141 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
142 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
146 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
148 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
150 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
151 (DWORD)ptr, ptr->hmemTaskQ, className,
152 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
154 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
160 /***********************************************************************
163 * Return the X window associated to a window.
165 Window WIN_GetXWindow( HWND32 hwnd )
167 WND *wndPtr = WIN_FindWndPtr( hwnd );
168 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
169 return wndPtr ? wndPtr->window : 0;
173 /***********************************************************************
176 * Remove a window from the siblings linked list.
178 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
180 WND *wndPtr, **ppWnd;
182 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
183 ppWnd = &wndPtr->parent->child;
184 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
185 *ppWnd = wndPtr->next;
190 /***********************************************************************
193 * Insert a window into the siblings linked list.
194 * The window is inserted after the specified window, which can also
195 * be specified as HWND_TOP or HWND_BOTTOM.
197 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
199 WND *wndPtr, **ppWnd;
201 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
203 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
205 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
206 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
207 while (*ppWnd) ppWnd = &(*ppWnd)->next;
209 else /* Normal case */
211 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
212 if (!afterPtr) return FALSE;
213 ppWnd = &afterPtr->next;
215 wndPtr->next = *ppWnd;
221 /***********************************************************************
222 * WIN_FindWinToRepaint
224 * Find a window that needs repaint.
226 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
229 WND *pWnd = pWndDesktop;
231 /* Note: the desktop window never gets WM_PAINT messages
232 * The real reason why is because Windows DesktopWndProc
233 * does ValidateRgn inside WM_ERASEBKGND handler.
236 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
238 for ( ; pWnd ; pWnd = pWnd->next )
240 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
242 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
246 if ((pWnd->hmemTaskQ == hQueue) &&
247 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
250 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
256 hwndRet = pWnd->hwndSelf;
258 /* look among siblings if we got a transparent window */
259 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
260 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
264 if (pWnd) hwndRet = pWnd->hwndSelf;
265 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
270 /***********************************************************************
271 * WIN_SendParentNotify
273 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
274 * the window has the WS_EX_NOPARENTNOTIFY style.
276 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
278 LPPOINT16 lppt = (LPPOINT16)&lValue;
279 WND *wndPtr = WIN_FindWndPtr( hwnd );
280 BOOL32 bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
282 /* if lValue contains cursor coordinates they have to be
283 * mapped to the client area of parent window */
285 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
289 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
290 !(wndPtr->dwStyle & WS_CHILD)) break;
294 lppt->x += wndPtr->rectClient.left;
295 lppt->y += wndPtr->rectClient.top;
298 wndPtr = wndPtr->parent;
299 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
300 MAKEWPARAM( event, idChild ), lValue );
305 /***********************************************************************
308 * Destroy storage associated to a window. "Internals" p.358
310 static WND* WIN_DestroyWindow( WND* wndPtr )
312 HWND32 hwnd = wndPtr->hwndSelf;
315 dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
319 DDE_DestroyWindow(wndPtr->hwndSelf);
320 #endif /* CONFIG_IPC */
322 /* free child windows */
324 while ((pWnd = wndPtr->child))
325 wndPtr->child = WIN_DestroyWindow( pWnd );
327 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
329 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
331 WINPOS_CheckActive( hwnd );
332 if( hwnd == GetCapture32()) ReleaseCapture();
334 /* free resources associated with the window */
336 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
337 PROPERTY_RemoveWindowProps( wndPtr );
339 wndPtr->dwMagic = 0; /* Mark it as invalid */
340 wndPtr->hwndSelf = 0;
342 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
344 if (wndPtr->hrgnUpdate) DeleteObject32( wndPtr->hrgnUpdate );
345 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
348 /* toss stale messages from the queue */
350 if( wndPtr->hmemTaskQ )
353 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
355 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
356 QUEUE_RemoveMsg(msgQ, pos);
357 wndPtr->hmemTaskQ = 0;
360 if (!(wndPtr->dwStyle & WS_CHILD))
361 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
362 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
363 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
364 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
366 WINPROC_FreeProc( wndPtr->winproc );
368 wndPtr->class->cWindows--;
369 wndPtr->class = NULL;
372 USER_HEAP_FREE( hwnd );
376 /***********************************************************************
377 * WIN_ResetQueueWindows
379 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
386 if (wnd->hmemTaskQ == hQueue)
387 if( hNew ) wnd->hmemTaskQ = hNew;
388 else DestroyWindow32( wnd->hwndSelf );
389 else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
394 /***********************************************************************
395 * WIN_CreateDesktopWindow
397 * Create the desktop window.
399 BOOL32 WIN_CreateDesktopWindow(void)
404 dprintf_win(stddeb,"Creating desktop window\n");
406 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
409 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
410 if (!hwndDesktop) return FALSE;
411 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
413 pWndDesktop->next = NULL;
414 pWndDesktop->child = NULL;
415 pWndDesktop->parent = NULL;
416 pWndDesktop->owner = NULL;
417 pWndDesktop->class = class;
418 pWndDesktop->winproc = NULL;
419 pWndDesktop->dwMagic = WND_MAGIC;
420 pWndDesktop->hwndSelf = hwndDesktop;
421 pWndDesktop->hInstance = 0;
422 pWndDesktop->rectWindow.left = 0;
423 pWndDesktop->rectWindow.top = 0;
424 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
425 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
426 pWndDesktop->rectClient = pWndDesktop->rectWindow;
427 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
428 pWndDesktop->ptIconPos.x = -1;
429 pWndDesktop->ptIconPos.y = -1;
430 pWndDesktop->ptMaxPos.x = -1;
431 pWndDesktop->ptMaxPos.y = -1;
432 pWndDesktop->text = NULL;
433 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
434 pWndDesktop->hrgnUpdate = 0;
435 pWndDesktop->hwndLastActive = hwndDesktop;
436 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
438 pWndDesktop->dwExStyle = 0;
439 pWndDesktop->dce = NULL;
440 pWndDesktop->pVScroll = NULL;
441 pWndDesktop->pHScroll = NULL;
442 pWndDesktop->pProp = NULL;
443 pWndDesktop->wIDmenu = 0;
444 pWndDesktop->flags = 0;
445 pWndDesktop->window = rootWindow;
446 pWndDesktop->hSysMenu = 0;
447 pWndDesktop->userdata = 0;
449 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
450 EVENT_RegisterWindow( pWndDesktop );
451 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
452 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
457 /***********************************************************************
460 * Implementation of CreateWindowEx().
462 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
463 BOOL32 win32, BOOL32 unicode )
467 HWND16 hwnd, hwndLinkAfter;
468 POINT16 maxSize, maxPos, minTrack, maxTrack;
469 LRESULT (*localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
471 dprintf_win( stddeb, "CreateWindowEx: " );
472 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
473 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
474 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
475 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
477 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
478 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
479 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
481 /* Find the parent window */
485 /* Make sure parent is valid */
486 if (!IsWindow32( cs->hwndParent ))
488 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
492 else if (cs->style & WS_CHILD)
494 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
495 return 0; /* WS_CHILD needs a parent */
498 /* Find the window class */
500 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
501 GetExePtr(cs->hInstance) )))
504 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
505 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
509 /* Fix the coordinates */
511 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
512 if (cs->cx == CW_USEDEFAULT32)
514 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
522 /* Create the window structure */
524 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
525 - sizeof(wndPtr->wExtra) )))
527 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
531 /* Fill the window structure */
533 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
535 wndPtr->child = NULL;
537 if (cs->style & WS_CHILD)
539 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
540 wndPtr->owner = NULL;
544 wndPtr->parent = pWndDesktop;
545 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
546 wndPtr->owner = NULL;
548 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
552 wndPtr->class = classPtr;
553 wndPtr->winproc = NULL;
554 wndPtr->dwMagic = WND_MAGIC;
555 wndPtr->hwndSelf = hwnd;
556 wndPtr->hInstance = cs->hInstance;
557 wndPtr->ptIconPos.x = -1;
558 wndPtr->ptIconPos.y = -1;
559 wndPtr->ptMaxPos.x = -1;
560 wndPtr->ptMaxPos.y = -1;
562 wndPtr->hmemTaskQ = GetTaskQueue(0);
563 wndPtr->hrgnUpdate = 0;
564 wndPtr->hwndLastActive = hwnd;
565 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
566 wndPtr->dwExStyle = cs->dwExStyle;
568 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
569 wndPtr->pVScroll = NULL;
570 wndPtr->pHScroll = NULL;
571 wndPtr->pProp = NULL;
572 wndPtr->hSysMenu = MENU_GetDefSysMenu();
573 wndPtr->userdata = 0;
575 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
577 /* Call the WH_CBT hook */
579 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
581 if (HOOK_IsHooked( WH_CBT ))
583 CBT_CREATEWND32A cbtc;
586 cbtc.hwndInsertAfter = hwndLinkAfter;
587 if ( HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc) )
589 dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
590 USER_HEAP_FREE( hwnd );
595 /* Set the window procedure */
597 classPtr->cWindows++;
598 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
600 /* Correct the window style */
602 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
604 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
605 wndPtr->flags |= WIN_NEED_SIZE;
607 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
609 /* Get class or window DC if needed */
611 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
612 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
613 else wndPtr->dce = NULL;
615 /* Insert the window in the linked list */
617 WIN_LinkWindow( hwnd, hwndLinkAfter );
619 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
621 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
623 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
624 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
625 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
626 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
627 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
629 if (cs->cx <= 0) cs->cx = 1;
630 if (cs->cy <= 0) cs->cy = 1;
632 wndPtr->rectWindow.left = cs->x;
633 wndPtr->rectWindow.top = cs->y;
634 wndPtr->rectWindow.right = cs->x + cs->cx;
635 wndPtr->rectWindow.bottom = cs->y + cs->cy;
636 wndPtr->rectClient = wndPtr->rectWindow;
637 wndPtr->rectNormal = wndPtr->rectWindow;
639 /* Create the X window (only for top-level windows, and then only */
640 /* when there's no desktop window) */
642 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
644 XSetWindowAttributes win_attr;
646 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
647 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
649 win_attr.event_mask = ExposureMask | KeyPressMask |
650 KeyReleaseMask | PointerMotionMask |
651 ButtonPressMask | ButtonReleaseMask |
652 FocusChangeMask | StructureNotifyMask;
653 win_attr.override_redirect = FALSE;
654 wndPtr->flags |= WIN_MANAGED;
658 win_attr.event_mask = ExposureMask | KeyPressMask |
659 KeyReleaseMask | PointerMotionMask |
660 ButtonPressMask | ButtonReleaseMask |
661 FocusChangeMask | StructureNotifyMask;
662 win_attr.override_redirect = TRUE;
664 win_attr.colormap = COLOR_GetColormap();
665 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
666 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
667 win_attr.cursor = CURSORICON_XCursor;
668 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
669 cs->cx, cs->cy, 0, CopyFromParent,
670 InputOutput, CopyFromParent,
671 CWEventMask | CWOverrideRedirect |
672 CWColormap | CWCursor | CWSaveUnder |
673 CWBackingStore, &win_attr );
675 if ((wndPtr->flags & WIN_MANAGED) &&
676 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
678 XSizeHints* size_hints = XAllocSizeHints();
682 size_hints->min_width = size_hints->max_width = cs->cx;
683 size_hints->min_height = size_hints->max_height = cs->cy;
684 size_hints->flags = (PSize | PMinSize | PMaxSize);
685 XSetWMSizeHints( display, wndPtr->window, size_hints,
686 XA_WM_NORMAL_HINTS );
691 if (cs->hwndParent) /* Get window owner */
693 Window win = WIN_GetXWindow( cs->hwndParent );
694 if (win) XSetTransientForHint( display, wndPtr->window, win );
696 EVENT_RegisterWindow( wndPtr );
699 /* Set the window menu */
701 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
703 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
706 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
707 if (classPtr->menuNameA)
708 cs->hMenu = HIWORD(classPtr->menuNameA) ?
709 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
710 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
712 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
713 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
716 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
718 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
720 /* Send the WM_CREATE message
721 * Perhaps we shouldn't allow width/height changes as well.
722 * See p327 in "Internals".
725 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
727 localSend32 = unicode ? SendMessage32W : SendMessage32A;
728 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
730 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
731 NULL, NULL, 0, &wndPtr->rectClient );
732 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
733 maxPos.y - wndPtr->rectWindow.top);
734 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
736 /* Send the size messages */
738 if (!(wndPtr->flags & WIN_NEED_SIZE))
741 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
742 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
743 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
744 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
745 wndPtr->rectClient.top ));
748 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
749 if (!IsWindow32(hwnd)) return 0;
751 /* Show the window, maximizing or minimizing if needed */
753 if (wndPtr->dwStyle & WS_MINIMIZE)
755 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
757 wndPtr->dwStyle &= ~WS_MAXIMIZE;
758 WINPOS_FindIconPos( hwnd );
759 SetWindowPos32( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
760 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
761 SWP_FRAMECHANGED | ((GetActiveWindow32())? SWP_NOACTIVATE : 0) );
763 else if (wndPtr->dwStyle & WS_MAXIMIZE)
765 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
767 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
768 SetWindowPos32( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
769 ((GetActiveWindow32())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
772 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
774 /* Call WH_SHELL hook */
776 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
777 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
779 dprintf_win(stddeb, "CreateWindowEx: created window %04x\n", hwnd);
784 /* Abort window creation */
786 dprintf_win(stddeb,"CreateWindowEx: aborted by WM_xxCREATE!\n");
787 WIN_UnlinkWindow( hwnd );
788 WIN_DestroyWindow( wndPtr );
793 /***********************************************************************
794 * CreateWindow16 (USER.41)
796 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
797 DWORD style, INT16 x, INT16 y, INT16 width,
798 INT16 height, HWND16 parent, HMENU16 menu,
799 HINSTANCE16 instance, LPVOID data )
801 return CreateWindowEx16( 0, className, windowName, style,
802 x, y, width, height, parent, menu, instance, data );
806 /***********************************************************************
807 * CreateWindowEx16 (USER.452)
809 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
810 DWORD style, INT16 x, INT16 y, INT16 width,
811 INT16 height, HWND16 parent, HMENU16 menu,
812 HINSTANCE16 instance, LPVOID data )
817 /* Find the class atom */
819 if (!(classAtom = GlobalFindAtom32A( className )))
821 fprintf( stderr, "CreateWindowEx16: bad class name " );
822 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
823 else fprintf( stderr, "'%s'\n", className );
827 /* Fix the coordinates */
829 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
830 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
831 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
832 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
834 /* Create the window */
836 cs.lpCreateParams = data;
837 cs.hInstance = (HINSTANCE32)instance;
838 cs.hMenu = (HMENU32)menu;
839 cs.hwndParent = (HWND32)parent;
841 cs.lpszName = windowName;
842 cs.lpszClass = className;
843 cs.dwExStyle = exStyle;
844 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
848 /***********************************************************************
849 * CreateWindowEx32A (USER32.82)
851 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
852 DWORD style, INT32 x, INT32 y, INT32 width,
853 INT32 height, HWND32 parent, HMENU32 menu,
854 HINSTANCE32 instance, LPVOID data )
859 /* Find the class atom */
861 if (!(classAtom = GlobalFindAtom32A( className )))
863 fprintf( stderr, "CreateWindowEx32A: bad class name " );
864 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
865 else fprintf( stderr, "'%s'\n", className );
869 /* Create the window */
871 cs.lpCreateParams = data;
872 cs.hInstance = instance;
874 cs.hwndParent = parent;
880 cs.lpszName = windowName;
881 cs.lpszClass = className;
882 cs.dwExStyle = exStyle;
883 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
887 /***********************************************************************
888 * CreateWindowEx32W (USER32.83)
890 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
891 DWORD style, INT32 x, INT32 y, INT32 width,
892 INT32 height, HWND32 parent, HMENU32 menu,
893 HINSTANCE32 instance, LPVOID data )
898 /* Find the class atom */
900 if (!(classAtom = GlobalFindAtom32W( className )))
902 if (HIWORD(className))
904 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
905 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
906 HeapFree( GetProcessHeap(), 0, cn );
909 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
913 /* Create the window */
915 cs.lpCreateParams = data;
916 cs.hInstance = instance;
918 cs.hwndParent = parent;
924 cs.lpszName = windowName;
925 cs.lpszClass = className;
926 cs.dwExStyle = exStyle;
927 /* Note: we rely on the fact that CREATESTRUCT32A and */
928 /* CREATESTRUCT32W have the same layout. */
929 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
933 /***********************************************************************
936 static void WIN_CheckFocus( WND* pWnd )
938 if( GetFocus16() == pWnd->hwndSelf )
939 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
942 /***********************************************************************
945 static void WIN_SendDestroyMsg( WND* pWnd )
949 WIN_CheckFocus(pWnd);
951 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
952 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
954 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
956 if( !IsWindow32(pWnd->hwndSelf) )
958 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
962 pChild = pWnd->child;
965 WIN_SendDestroyMsg( pChild );
966 pChild = pChild->next;
968 WIN_CheckFocus(pWnd);
972 /***********************************************************************
973 * DestroyWindow (USER.53)
975 BOOL16 DestroyWindow16( HWND16 hwnd )
977 return DestroyWindow32(hwnd);
979 /***********************************************************************
980 * DestroyWindow (USER32.134)
982 BOOL32 DestroyWindow32( HWND32 hwnd )
986 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
990 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
991 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
995 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
998 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1000 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1001 /* FIXME: clean up palette - see "Internals" p.352 */
1004 if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1005 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1006 if (!IsWindow32(hwnd)) return TRUE;
1008 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1010 /* Hide the window */
1012 if (wndPtr->dwStyle & WS_VISIBLE)
1014 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1015 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1016 ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1017 if (!IsWindow32(hwnd)) return TRUE;
1020 /* Recursively destroy owned windows */
1022 if( !(wndPtr->dwStyle & WS_CHILD) )
1026 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1029 if (siblingPtr->owner == wndPtr)
1030 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1033 siblingPtr->owner = NULL;
1034 siblingPtr = siblingPtr->next;
1036 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1040 if( !Options.managed || EVENT_CheckFocus() )
1041 WINPOS_ActivateOtherWindow(wndPtr);
1043 if( wndPtr->owner &&
1044 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1045 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1048 /* Send destroy messages */
1050 WIN_SendDestroyMsg( wndPtr );
1051 if (!IsWindow32(hwnd)) return TRUE;
1053 /* Unlink now so we won't bother with the children later on */
1055 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1057 /* Destroy the window storage */
1059 WIN_DestroyWindow( wndPtr );
1064 /***********************************************************************
1065 * CloseWindow16 (USER.43)
1067 BOOL16 CloseWindow16( HWND16 hwnd )
1069 return CloseWindow32( hwnd );
1073 /***********************************************************************
1074 * CloseWindow32 (USER32.55)
1076 BOOL32 CloseWindow32( HWND32 hwnd )
1078 WND * wndPtr = WIN_FindWndPtr( hwnd );
1079 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1080 ShowWindow32( hwnd, SW_MINIMIZE );
1085 /***********************************************************************
1086 * OpenIcon16 (USER.44)
1088 BOOL16 OpenIcon16( HWND16 hwnd )
1090 return OpenIcon32( hwnd );
1094 /***********************************************************************
1095 * OpenIcon32 (USER32.409)
1097 BOOL32 OpenIcon32( HWND32 hwnd )
1099 if (!IsIconic32( hwnd )) return FALSE;
1100 ShowWindow32( hwnd, SW_SHOWNORMAL );
1105 /***********************************************************************
1108 * Implementation of FindWindow() and FindWindowEx().
1110 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1114 CLASS *pClass = NULL;
1118 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1121 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1123 else if (pWnd->parent != pWndDesktop) return 0;
1128 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1131 if (!pWnd) return 0;
1133 /* For a child window, all siblings will have the same hInstance, */
1134 /* so we can look for the class once and for all. */
1136 if (className && (pWnd->dwStyle & WS_CHILD))
1138 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1142 for ( ; pWnd; pWnd = pWnd->next)
1144 if (className && !(pWnd->dwStyle & WS_CHILD))
1146 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1147 continue; /* Skip this window */
1149 if (pClass && (pWnd->class != pClass))
1150 continue; /* Not the right class */
1152 /* Now check the title */
1154 if (!title) return pWnd->hwndSelf;
1155 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1162 /***********************************************************************
1163 * FindWindow16 (USER.50)
1165 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1167 return FindWindowEx16( 0, 0, className, title );
1171 /***********************************************************************
1172 * FindWindowEx16 (USER.427)
1174 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1175 SEGPTR className, LPCSTR title )
1181 /* If the atom doesn't exist, then no class */
1182 /* with this name exists either. */
1183 if (!(atom = GlobalFindAtom16( className ))) return 0;
1185 return WIN_FindWindow( parent, child, atom, title );
1189 /***********************************************************************
1190 * FindWindow32A (USER32.197)
1192 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1194 return FindWindowEx32A( 0, 0, className, title );
1198 /***********************************************************************
1199 * FindWindowEx32A (USER32.198)
1201 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1202 LPCSTR className, LPCSTR title )
1208 /* If the atom doesn't exist, then no class */
1209 /* with this name exists either. */
1210 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1212 return WIN_FindWindow( 0, 0, atom, title );
1216 /***********************************************************************
1217 * FindWindowEx32W (USER32.199)
1219 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1220 LPCWSTR className, LPCWSTR title )
1228 /* If the atom doesn't exist, then no class */
1229 /* with this name exists either. */
1230 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1232 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1233 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1234 HeapFree( GetProcessHeap(), 0, buffer );
1239 /***********************************************************************
1240 * FindWindow32W (USER32.200)
1242 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1244 return FindWindowEx32W( 0, 0, className, title );
1248 /**********************************************************************
1251 WND *WIN_GetDesktop(void)
1257 /**********************************************************************
1258 * GetDesktopWindow16 (USER.286)
1260 HWND16 GetDesktopWindow16(void)
1262 return (HWND16)pWndDesktop->hwndSelf;
1266 /**********************************************************************
1267 * GetDesktopWindow32 (USER32.231)
1269 HWND32 GetDesktopWindow32(void)
1271 return pWndDesktop->hwndSelf;
1275 /**********************************************************************
1276 * GetDesktopHwnd (USER.278)
1278 * Exactly the same thing as GetDesktopWindow(), but not documented.
1279 * Don't ask me why...
1281 HWND16 GetDesktopHwnd(void)
1283 return (HWND16)pWndDesktop->hwndSelf;
1287 /*******************************************************************
1288 * EnableWindow16 (USER.34)
1290 BOOL16 EnableWindow16( HWND16 hwnd, BOOL16 enable )
1292 return EnableWindow32( hwnd, enable );
1296 /*******************************************************************
1297 * EnableWindow32 (USER32.171)
1299 BOOL32 EnableWindow32( HWND32 hwnd, BOOL32 enable )
1303 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1304 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1307 wndPtr->dwStyle &= ~WS_DISABLED;
1308 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1311 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1313 /* Disable window */
1314 wndPtr->dwStyle |= WS_DISABLED;
1315 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1316 SetFocus32( 0 ); /* A disabled window can't have the focus */
1317 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1318 ReleaseCapture(); /* A disabled window can't capture the mouse */
1319 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1322 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1326 /***********************************************************************
1327 * IsWindowEnabled16 (USER.35)
1329 BOOL16 IsWindowEnabled16(HWND16 hWnd)
1331 return IsWindowEnabled32(hWnd);
1335 /***********************************************************************
1336 * IsWindowEnabled32 (USER32.348)
1338 BOOL32 IsWindowEnabled32(HWND32 hWnd)
1342 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1343 return !(wndPtr->dwStyle & WS_DISABLED);
1347 /***********************************************************************
1348 * IsWindowUnicode (USER32.349)
1350 BOOL32 IsWindowUnicode( HWND32 hwnd )
1354 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1355 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1359 /**********************************************************************
1360 * GetWindowWord16 (USER.133)
1362 WORD GetWindowWord16( HWND16 hwnd, INT16 offset )
1364 return GetWindowWord32( hwnd, offset );
1368 /**********************************************************************
1369 * GetWindowWord32 (USER32.313)
1371 WORD GetWindowWord32( HWND32 hwnd, INT32 offset )
1373 WND * wndPtr = WIN_FindWndPtr( hwnd );
1374 if (!wndPtr) return 0;
1377 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1379 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1382 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1386 case GWW_ID: return wndPtr->wIDmenu;
1387 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1388 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1390 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1396 /**********************************************************************
1397 * WIN_GetWindowInstance
1399 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1401 WND * wndPtr = WIN_FindWndPtr( hwnd );
1402 if (!wndPtr) return (HINSTANCE16)0;
1403 return wndPtr->hInstance;
1407 /**********************************************************************
1408 * SetWindowWord16 (USER.134)
1410 WORD SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1412 return SetWindowWord32( hwnd, offset, newval );
1416 /**********************************************************************
1417 * SetWindowWord32 (USER32.523)
1419 WORD SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1422 WND * wndPtr = WIN_FindWndPtr( hwnd );
1423 if (!wndPtr) return 0;
1426 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1428 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1431 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1435 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1436 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1437 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1439 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1448 /**********************************************************************
1451 * Helper function for GetWindowLong().
1453 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1456 WND * wndPtr = WIN_FindWndPtr( hwnd );
1457 if (!wndPtr) return 0;
1460 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1462 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1465 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1466 /* Special case for dialog window procedure */
1467 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1468 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1473 case GWL_USERDATA: return wndPtr->userdata;
1474 case GWL_STYLE: return wndPtr->dwStyle;
1475 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1476 case GWL_ID: return wndPtr->wIDmenu;
1477 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1479 case GWL_HWNDPARENT: return wndPtr->parent ?
1480 (HWND32)wndPtr->parent->hwndSelf : 0;
1481 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1483 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1489 /**********************************************************************
1492 * Helper function for SetWindowLong().
1494 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1495 WINDOWPROCTYPE type )
1498 WND * wndPtr = WIN_FindWndPtr( hwnd );
1499 if (!wndPtr) return 0;
1502 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1504 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1507 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1508 /* Special case for dialog window procedure */
1509 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1511 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1512 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1520 return SetWindowWord32( hwnd, offset, (WORD)newval );
1522 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1523 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1527 /* FIXME: WM_STYLE... messages for WIN_ISWIN32 windows */
1529 ptr = &wndPtr->dwStyle;
1530 /* Some bits can't be changed this way */
1531 newval &= ~(WS_VISIBLE | WS_CHILD);
1532 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1534 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1535 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1537 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1546 /**********************************************************************
1547 * GetWindowLong16 (USER.135)
1549 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1551 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1555 /**********************************************************************
1556 * GetWindowLong32A (USER32.304)
1558 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1560 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1564 /**********************************************************************
1565 * GetWindowLong32W (USER32.305)
1567 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1569 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1573 /**********************************************************************
1574 * SetWindowLong16 (USER.136)
1576 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1578 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1582 /**********************************************************************
1583 * SetWindowLong32A (USER32.516)
1585 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1587 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1591 /**********************************************************************
1592 * SetWindowLong32W (USER32.517)
1594 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1596 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1600 /*******************************************************************
1601 * GetWindowText16 (USER.36)
1603 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1605 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1609 /*******************************************************************
1610 * GetWindowText32A (USER32.308)
1612 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1614 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1619 /*******************************************************************
1620 * GetWindowText32W (USER32.311)
1622 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1624 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1629 /*******************************************************************
1630 * SetWindowText16 (USER.37)
1632 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1634 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1638 /*******************************************************************
1639 * SetWindowText32A (USER32.)
1641 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1643 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1647 /*******************************************************************
1648 * SetWindowText32W (USER32.)
1650 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1652 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1656 /*******************************************************************
1657 * GetWindowTextLength16 (USER.38)
1659 INT16 GetWindowTextLength16( HWND16 hwnd )
1661 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1665 /*******************************************************************
1666 * GetWindowTextLength32A (USER32.309)
1668 INT32 GetWindowTextLength32A( HWND32 hwnd )
1670 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1673 /*******************************************************************
1674 * GetWindowTextLength32W (USER32.309)
1676 INT32 GetWindowTextLength32W( HWND32 hwnd )
1678 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1682 /*******************************************************************
1683 * IsWindow16 (USER.47)
1685 BOOL16 IsWindow16( HWND16 hwnd )
1687 return IsWindow32( hwnd );
1691 /*******************************************************************
1692 * IsWindow32 (USER32.347)
1694 BOOL32 IsWindow32( HWND32 hwnd )
1696 WND * wndPtr = WIN_FindWndPtr( hwnd );
1697 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1701 /*****************************************************************
1702 * GetParent16 (USER.46)
1704 HWND16 GetParent16( HWND16 hwnd )
1706 return (HWND16)GetParent32( hwnd );
1710 /*****************************************************************
1711 * GetParent32 (USER32.277)
1713 HWND32 GetParent32( HWND32 hwnd )
1715 WND *wndPtr = WIN_FindWndPtr(hwnd);
1716 if (!wndPtr) return 0;
1717 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1718 return wndPtr ? wndPtr->hwndSelf : 0;
1722 /*****************************************************************
1725 * Get the top-level parent for a child window.
1727 HWND32 WIN_GetTopParent( HWND32 hwnd )
1729 WND *wndPtr = WIN_FindWndPtr( hwnd );
1730 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1731 return wndPtr ? wndPtr->hwndSelf : 0;
1735 /*****************************************************************
1736 * SetParent16 (USER.233)
1738 HWND16 SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1740 return SetParent32( hwndChild, hwndNewParent );
1744 /*****************************************************************
1745 * SetParent32 (USER32.494)
1747 HWND32 SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1751 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1752 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1753 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1755 oldParent = wndPtr->parent->hwndSelf;
1757 WIN_UnlinkWindow(hwndChild);
1758 if (hwndNewParent) wndPtr->parent = pWndParent;
1759 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1761 if (IsWindowVisible32(hwndChild)) UpdateWindow32(hwndChild);
1767 /*******************************************************************
1768 * IsChild16 (USER.48)
1770 BOOL16 IsChild16( HWND16 parent, HWND16 child )
1772 return IsChild32(parent,child);
1776 /*******************************************************************
1777 * IsChild32 (USER32.338)
1779 BOOL32 IsChild32( HWND32 parent, HWND32 child )
1781 WND * wndPtr = WIN_FindWndPtr( child );
1782 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1784 wndPtr = wndPtr->parent;
1785 if (wndPtr->hwndSelf == parent) return TRUE;
1791 /***********************************************************************
1792 * IsWindowVisible16 (USER.49)
1794 BOOL16 IsWindowVisible16( HWND16 hwnd )
1796 return IsWindowVisible32(hwnd);
1800 /***********************************************************************
1801 * IsWindowVisible32 (USER32.350)
1803 BOOL32 IsWindowVisible32( HWND32 hwnd )
1805 WND *wndPtr = WIN_FindWndPtr( hwnd );
1806 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1808 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1809 wndPtr = wndPtr->parent;
1811 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1815 /***********************************************************************
1816 * WIN_IsWindowDrawable
1818 * hwnd is drawable when it is visible, all parents are not
1819 * minimized, and it is itself not minimized unless we are
1820 * trying to draw icon and the default class icon is set.
1822 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1824 HWND32 hwnd = wnd->hwndSelf;
1829 if( wnd->dwStyle & WS_MINIMIZE )
1830 if( wnd->hwndSelf != hwnd ) break;
1831 else if( icon && wnd->class->hIcon ) break;
1833 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1834 wnd = wnd->parent; }
1835 return (!wnd && yes);
1838 /*******************************************************************
1839 * GetTopWindow16 (USER.229)
1841 HWND16 GetTopWindow16( HWND16 hwnd )
1843 return GetTopWindow32(hwnd);
1847 /*******************************************************************
1848 * GetTopWindow32 (USER.229)
1850 HWND32 GetTopWindow32( HWND32 hwnd )
1852 WND * wndPtr = WIN_FindWndPtr( hwnd );
1853 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1858 /*******************************************************************
1859 * GetWindow16 (USER.262)
1861 HWND16 GetWindow16( HWND16 hwnd, WORD rel )
1863 return GetWindow32( hwnd,rel );
1867 /*******************************************************************
1868 * GetWindow32 (USER32.301)
1870 HWND32 GetWindow32( HWND32 hwnd, WORD rel )
1872 WND * wndPtr = WIN_FindWndPtr( hwnd );
1873 if (!wndPtr) return 0;
1877 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1881 if (!wndPtr->parent) return 0; /* Desktop window */
1882 while (wndPtr->next) wndPtr = wndPtr->next;
1883 return wndPtr->hwndSelf;
1886 if (!wndPtr->next) return 0;
1887 return wndPtr->next->hwndSelf;
1890 if (!wndPtr->parent) return 0; /* Desktop window */
1891 wndPtr = wndPtr->parent->child; /* First sibling */
1892 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1893 while (wndPtr->next)
1895 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1896 wndPtr = wndPtr->next;
1901 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1904 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1910 /*******************************************************************
1911 * GetNextWindow16 (USER.230)
1913 HWND16 GetNextWindow16( HWND16 hwnd, WORD flag )
1915 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1916 return GetWindow16( hwnd, flag );
1919 /*******************************************************************
1920 * ShowOwnedPopups16 (USER.265)
1922 void ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
1924 ShowOwnedPopups32( owner, fShow );
1928 /*******************************************************************
1929 * ShowOwnedPopups32 (USER32.530)
1931 BOOL32 ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
1933 WND *pWnd = pWndDesktop->child;
1936 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1937 (pWnd->dwStyle & WS_POPUP))
1938 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1945 /*******************************************************************
1946 * GetLastActivePopup16 (USER.287)
1948 HWND16 GetLastActivePopup16( HWND16 hwnd )
1950 return GetLastActivePopup32( hwnd );
1953 /*******************************************************************
1954 * GetLastActivePopup32 (USER32.255)
1956 HWND32 GetLastActivePopup32( HWND32 hwnd )
1959 wndPtr = WIN_FindWndPtr(hwnd);
1960 if (wndPtr == NULL) return hwnd;
1961 return wndPtr->hwndLastActive;
1965 /*******************************************************************
1968 * Build an array of pointers to all children of a given window.
1969 * The array must be freed with HeapFree(SystemHeap).
1971 WND **WIN_BuildWinArray( WND *wndPtr )
1973 WND **list, **ppWnd;
1977 /* First count the windows */
1979 if (!wndPtr) wndPtr = pWndDesktop;
1980 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1981 count++; /* For the terminating NULL */
1983 /* Now build the list of all windows */
1985 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1987 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1994 /*******************************************************************
1995 * EnumWindows16 (USER.54)
1997 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1999 WND **list, **ppWnd;
2001 /* We have to build a list of all windows first, to avoid */
2002 /* unpleasant side-effects, for instance if the callback */
2003 /* function changes the Z-order of the windows. */
2005 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
2007 /* Now call the callback function for every window */
2009 for (ppWnd = list; *ppWnd; ppWnd++)
2011 /* Make sure that the window still exists */
2012 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2013 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2015 HeapFree( SystemHeap, 0, list );
2020 /*******************************************************************
2021 * EnumWindows32 (USER32.192)
2023 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2025 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2029 /**********************************************************************
2030 * EnumTaskWindows16 (USER.225)
2032 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
2034 WND **list, **ppWnd;
2035 HQUEUE16 hQueue = GetTaskQueue( hTask );
2037 /* This function is the same as EnumWindows(), */
2038 /* except for an added check on the window queue. */
2040 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
2042 /* Now call the callback function for every window */
2044 for (ppWnd = list; *ppWnd; ppWnd++)
2046 /* Make sure that the window still exists */
2047 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2048 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2049 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2051 HeapFree( SystemHeap, 0, list );
2056 /**********************************************************************
2057 * EnumThreadWindows (USER32.189)
2059 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2061 THDB *tdb = (THDB*)id;
2063 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2067 /**********************************************************************
2068 * WIN_EnumChildWindows
2070 * Helper function for EnumChildWindows().
2072 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2080 /* Make sure that the window still exists */
2081 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2082 /* Build children list first */
2083 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
2084 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
2085 ret = WIN_EnumChildWindows( childList, func, lParam );
2086 HeapFree( SystemHeap, 0, childList );
2087 if (!ret) return FALSE;
2094 /**********************************************************************
2095 * EnumChildWindows16 (USER.55)
2097 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
2099 WND **list, *pParent;
2101 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2102 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
2103 WIN_EnumChildWindows( list, func, lParam );
2104 HeapFree( SystemHeap, 0, list );
2109 /**********************************************************************
2110 * EnumChildWindows32 (USER32.177)
2112 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
2114 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2119 /*******************************************************************
2120 * AnyPopup16 (USER.52)
2122 BOOL16 AnyPopup16(void)
2124 return AnyPopup32();
2128 /*******************************************************************
2129 * AnyPopup32 (USER32.3)
2131 BOOL32 AnyPopup32(void)
2134 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2135 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2140 /*******************************************************************
2141 * FlashWindow16 (USER.105)
2143 BOOL16 FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2145 return FlashWindow32( hWnd, bInvert );
2149 /*******************************************************************
2150 * FlashWindow32 (USER32.201)
2152 BOOL32 FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2154 WND *wndPtr = WIN_FindWndPtr(hWnd);
2156 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2158 if (!wndPtr) return FALSE;
2160 if (wndPtr->dwStyle & WS_MINIMIZE)
2162 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2164 HDC32 hDC = GetDC32(hWnd);
2166 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2167 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2169 ReleaseDC32( hWnd, hDC );
2170 wndPtr->flags |= WIN_NCACTIVATED;
2174 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2175 RDW_UPDATENOW | RDW_FRAME, 0 );
2176 wndPtr->flags &= ~WIN_NCACTIVATED;
2183 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2184 else wparam = (hWnd == GetActiveWindow32());
2186 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2192 /*******************************************************************
2193 * SetSysModalWindow16 (USER.188)
2195 HWND16 SetSysModalWindow16( HWND16 hWnd )
2197 HWND32 hWndOldModal = hwndSysModal;
2198 hwndSysModal = hWnd;
2199 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2200 return hWndOldModal;
2204 /*******************************************************************
2205 * GetSysModalWindow16 (USER.52)
2207 HWND16 GetSysModalWindow16(void)
2209 return hwndSysModal;
2213 /*******************************************************************
2216 * recursively find a child that contains spDragInfo->pt point
2217 * and send WM_QUERYDROPOBJECT
2219 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2221 BOOL16 wParam,bResult = 0;
2223 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2224 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2227 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2229 pt = ptrDragInfo->pt;
2231 GetWindowRect16(hQueryWnd,&tempRect);
2233 if( !PtInRect16(&tempRect,pt) ||
2234 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2237 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2239 tempRect = ptrQueryWnd->rectClient;
2240 if(ptrQueryWnd->dwStyle & WS_CHILD)
2241 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2243 if( PtInRect16(&tempRect,pt) )
2247 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2248 if( ptrWnd->dwStyle & WS_VISIBLE )
2250 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2252 if( PtInRect16(&tempRect,pt) )
2258 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2259 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2260 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2261 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2262 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2265 if(bResult) return bResult;
2271 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2273 ptrDragInfo->hScope = hQueryWnd;
2275 bResult = ( bNoSend )
2276 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2277 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2278 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2280 ptrDragInfo->pt = pt;
2286 /*******************************************************************
2287 * DragDetect (USER.465)
2289 BOOL16 DragDetect16( HWND16 hWnd, POINT16 pt )
2292 CONV_POINT16TO32( &pt, &pt32 );
2293 return DragDetect32( hWnd, pt32 );
2296 /*******************************************************************
2297 * DragDetect32 (USER32.150)
2299 BOOL32 DragDetect32( HWND32 hWnd, POINT32 pt )
2304 rect.left = pt.x - wDragWidth;
2305 rect.right = pt.x + wDragWidth;
2307 rect.top = pt.y - wDragHeight;
2308 rect.bottom = pt.y + wDragHeight;
2314 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2316 if( msg.message == WM_LBUTTONUP )
2321 if( msg.message == WM_MOUSEMOVE )
2323 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2336 /******************************************************************************
2337 * DragObject16 (USER.464)
2339 DWORD DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2340 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2343 LPDRAGINFO lpDragInfo;
2345 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2346 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2347 WND *wndPtr = WIN_FindWndPtr(hWnd);
2350 HCURSOR16 hCurrentCursor = 0;
2351 HWND16 hCurrentWnd = 0;
2354 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2355 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2357 if( !lpDragInfo || !spDragInfo ) return 0L;
2359 hBummer = LoadCursor16(0,IDC_BUMMER);
2361 if( !hBummer || !wndPtr )
2363 GlobalFree16(hDragInfo);
2369 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2371 GlobalFree16(hDragInfo);
2375 if( hDragCursor == hCursor ) hDragCursor = 0;
2376 else hCursor = hDragCursor;
2378 hOldCursor = SetCursor32(hDragCursor);
2381 lpDragInfo->hWnd = hWnd;
2382 lpDragInfo->hScope = 0;
2383 lpDragInfo->wFlags = wObj;
2384 lpDragInfo->hList = szList; /* near pointer! */
2385 lpDragInfo->hOfStruct = hOfStruct;
2389 ShowCursor32( TRUE );
2395 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2398 *(lpDragInfo+1) = *lpDragInfo;
2400 lpDragInfo->pt = msg.pt;
2402 /* update DRAGINFO struct */
2403 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2405 if( (b = DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE)) > 0 )
2406 hCurrentCursor = hCursor;
2409 hCurrentCursor = hBummer;
2410 lpDragInfo->hScope = 0;
2412 if( hCurrentCursor )
2413 SetCursor32(hCurrentCursor);
2415 dprintf_msg(stddeb,"drag: got %04x\n", b);
2417 /* send WM_DRAGLOOP */
2418 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer) ,
2419 (LPARAM) spDragInfo );
2420 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2421 if( hCurrentWnd != lpDragInfo->hScope )
2424 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2425 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2426 HIWORD(spDragInfo)) );
2427 hCurrentWnd = lpDragInfo->hScope;
2429 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2433 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2436 /* check if we're done */
2437 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2442 ShowCursor32( FALSE );
2446 SetCursor32( hOldCursor );
2447 if (hDragCursor) DestroyCursor32( hDragCursor );
2450 if( hCurrentCursor != hBummer )
2451 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2452 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2453 GlobalFree16(hDragInfo);