Release 960717
[wine/multimedia.git] / windows / win.c
blob25ccc7f675942c6e66bc0fb7c7cf16562648b5b0
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <X11/Xatom.h>
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "heap.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "string32.h"
26 #include "queue.h"
27 #include "winpos.h"
28 #include "color.h"
29 #include "shm_main_blk.h"
30 #include "dde_proc.h"
31 #include "callback.h"
32 #include "clipboard.h"
33 #include "winproc.h"
34 #include "stddebug.h"
35 /* #define DEBUG_WIN */
36 /* #define DEBUG_MENU */
37 #include "debug.h"
39 /* Desktop window */
40 static WND *pWndDesktop = NULL;
42 static HWND hwndSysModal = 0;
44 static WORD wDragWidth = 4;
45 static WORD wDragHeight= 3;
47 extern HCURSOR CURSORICON_IconToCursor(HICON);
48 extern HQUEUE QUEUE_GetDoomedQueue();
50 /***********************************************************************
51 * WIN_FindWndPtr
53 * Return a pointer to the WND structure corresponding to a HWND.
55 WND * WIN_FindWndPtr( HWND hwnd )
57 WND * ptr;
59 if (!hwnd) return NULL;
60 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
61 if (ptr->dwMagic != WND_MAGIC) return NULL;
62 if (ptr->hwndSelf != hwnd)
64 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
65 hwnd, ptr->hwndSelf );
66 return NULL;
68 return ptr;
72 /***********************************************************************
73 * WIN_DumpWindow
75 * Dump the content of a window structure to stderr.
77 void WIN_DumpWindow( HWND hwnd )
79 WND *ptr;
80 char className[80];
81 int i;
83 if (!(ptr = WIN_FindWndPtr( hwnd )))
85 fprintf( stderr, "%04x is not a window handle\n", hwnd );
86 return;
89 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
90 strcpy( className, "#NULL#" );
92 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
93 fprintf( stderr,
94 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
95 "inst=%04x taskQ=%04x updRgn=%04x active=%04x hdce=%04x idmenu=%04x\n"
96 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
97 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
98 "sysmenu=%04x flags=%04x props=%04x vscroll=%p hscroll=%p\n",
99 ptr->next, ptr->child, ptr->parent, ptr->owner,
100 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
101 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
102 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
103 ptr->text ? ptr->text : "",
104 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
105 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
106 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
107 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
108 ptr->flags, ptr->hProp, ptr->pVScroll, ptr->pHScroll );
110 if (ptr->class->cbWndExtra)
112 fprintf( stderr, "extra bytes:" );
113 for (i = 0; i < ptr->class->cbWndExtra; i++)
114 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
115 fprintf( stderr, "\n" );
117 fprintf( stderr, "\n" );
121 /***********************************************************************
122 * WIN_WalkWindows
124 * Walk the windows tree and print each window on stderr.
126 void WIN_WalkWindows( HWND hwnd, int indent )
128 WND *ptr;
129 char className[80];
131 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
132 if (!ptr)
134 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
135 return;
138 if (!indent) /* first time around */
139 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
140 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
142 while (ptr)
144 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
146 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
148 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
149 (DWORD)ptr, ptr->hmemTaskQ, className,
150 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
152 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
153 ptr = ptr->next;
158 /***********************************************************************
159 * WIN_GetXWindow
161 * Return the X window associated to a window.
163 Window WIN_GetXWindow( HWND hwnd )
165 WND *wndPtr = WIN_FindWndPtr( hwnd );
166 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
167 return wndPtr ? wndPtr->window : 0;
171 /***********************************************************************
172 * WIN_UnlinkWindow
174 * Remove a window from the siblings linked list.
176 BOOL WIN_UnlinkWindow( HWND hwnd )
178 WND *wndPtr, **ppWnd;
180 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
181 ppWnd = &wndPtr->parent->child;
182 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
183 *ppWnd = wndPtr->next;
184 return TRUE;
188 /***********************************************************************
189 * WIN_LinkWindow
191 * Insert a window into the siblings linked list.
192 * The window is inserted after the specified window, which can also
193 * be specified as HWND_TOP or HWND_BOTTOM.
195 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
197 WND *wndPtr, **ppWnd;
199 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
201 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
203 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
204 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
205 while (*ppWnd) ppWnd = &(*ppWnd)->next;
207 else /* Normal case */
209 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
210 if (!afterPtr) return FALSE;
211 ppWnd = &afterPtr->next;
213 wndPtr->next = *ppWnd;
214 *ppWnd = wndPtr;
215 return TRUE;
219 /***********************************************************************
220 * WIN_FindWinToRepaint
222 * Find a window that needs repaint.
224 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE hQueue )
226 HWND hwndRet;
227 WND *pWnd = pWndDesktop;
229 /* Note: the desktop window never gets WM_PAINT messages */
230 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
232 for ( ; pWnd ; pWnd = pWnd->next )
234 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
236 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
237 pWnd->hwndSelf );
238 continue;
240 if ((pWnd->hmemTaskQ == hQueue) &&
241 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
243 if (pWnd->child )
244 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
245 return hwndRet;
248 if (!pWnd) return 0;
250 hwndRet = pWnd->hwndSelf;
252 /* look among siblings if we got a transparent window */
253 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
254 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
256 pWnd = pWnd->next;
258 if (pWnd) hwndRet = pWnd->hwndSelf;
259 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
260 return hwndRet;
264 /***********************************************************************
265 * WIN_SendParentNotify
267 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
268 * the window has the WS_EX_NOPARENTNOTIFY style.
270 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
272 LPPOINT16 lppt = (LPPOINT16)&lValue;
273 WND *wndPtr = WIN_FindWndPtr( hwnd );
274 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
276 /* if lValue contains cursor coordinates they have to be
277 * mapped to the client area of parent window */
279 if (bMouse) MapWindowPoints16(0, hwnd, lppt, 1);
280 #ifndef WINELIB32
281 else lValue = MAKELONG( LOWORD(lValue), idChild );
282 #endif
284 while (wndPtr)
286 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
287 !(wndPtr->dwStyle & WS_CHILD)) break;
289 if (bMouse)
291 lppt->x += wndPtr->rectClient.left;
292 lppt->y += wndPtr->rectClient.top;
295 wndPtr = wndPtr->parent;
296 #ifdef WINELIB32
297 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
298 MAKEWPARAM( event, idChild ), lValue );
299 #else
300 SendMessage16( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
301 #endif
306 /***********************************************************************
307 * WIN_DestroyWindow
309 * Destroy storage associated to a window
311 static void WIN_DestroyWindow( HWND hwnd )
313 WND *wndPtr = WIN_FindWndPtr( hwnd );
315 #ifdef CONFIG_IPC
316 if (main_block)
317 DDE_DestroyWindow(hwnd);
318 #endif /* CONFIG_IPC */
320 if (!wndPtr) return;
321 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
322 TIMER_RemoveWindowTimers( hwnd );
323 wndPtr->dwMagic = 0; /* Mark it as invalid */
324 wndPtr->hwndSelf = 0;
325 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
327 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
328 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
330 if (!(wndPtr->dwStyle & WS_CHILD))
332 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
334 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
335 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
336 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
337 WINPROC_FreeProc( wndPtr->winproc );
338 wndPtr->class->cWindows--;
339 USER_HEAP_FREE( hwnd );
343 /***********************************************************************
344 * WIN_DestroyQueueWindows
346 void WIN_DestroyQueueWindows( WND* wnd, HQUEUE hQueue )
348 WND* next;
350 while (wnd)
352 next = wnd->next;
353 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
354 else WIN_DestroyQueueWindows( wnd->child, hQueue );
355 wnd = next;
360 /***********************************************************************
361 * WIN_CreateDesktopWindow
363 * Create the desktop window.
365 BOOL WIN_CreateDesktopWindow(void)
367 CLASS *class;
368 HDC hdc;
369 HWND hwndDesktop;
371 dprintf_win(stddeb,"Creating desktop window\n");
373 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
374 return FALSE;
376 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
377 if (!hwndDesktop) return FALSE;
378 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
380 pWndDesktop->next = NULL;
381 pWndDesktop->child = NULL;
382 pWndDesktop->parent = NULL;
383 pWndDesktop->owner = NULL;
384 pWndDesktop->class = class;
385 pWndDesktop->winproc = NULL;
386 pWndDesktop->dwMagic = WND_MAGIC;
387 pWndDesktop->hwndSelf = hwndDesktop;
388 pWndDesktop->hInstance = 0;
389 pWndDesktop->rectWindow.left = 0;
390 pWndDesktop->rectWindow.top = 0;
391 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
392 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
393 pWndDesktop->rectClient = pWndDesktop->rectWindow;
394 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
395 pWndDesktop->ptIconPos.x = -1;
396 pWndDesktop->ptIconPos.y = -1;
397 pWndDesktop->ptMaxPos.x = -1;
398 pWndDesktop->ptMaxPos.y = -1;
399 pWndDesktop->text = NULL;
400 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
401 pWndDesktop->hrgnUpdate = 0;
402 pWndDesktop->hwndLastActive = hwndDesktop;
403 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
404 WS_CLIPSIBLINGS;
405 pWndDesktop->dwExStyle = 0;
406 pWndDesktop->hdce = 0;
407 pWndDesktop->pVScroll = NULL;
408 pWndDesktop->pHScroll = NULL;
409 pWndDesktop->wIDmenu = 0;
410 pWndDesktop->flags = 0;
411 pWndDesktop->window = rootWindow;
412 pWndDesktop->hSysMenu = 0;
413 pWndDesktop->hProp = 0;
414 pWndDesktop->userdata = 0;
416 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
417 EVENT_RegisterWindow( pWndDesktop );
418 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
419 if ((hdc = GetDC( hwndDesktop )) != 0)
421 SendMessage32A( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
422 ReleaseDC( hwndDesktop, hdc );
424 return TRUE;
428 /***********************************************************************
429 * WIN_CreateWindowEx
431 * Implementation of CreateWindowEx().
433 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
434 BOOL unicode )
436 CLASS *classPtr;
437 WND *wndPtr;
438 HWND16 hwnd;
439 POINT16 maxSize, maxPos, minTrack, maxTrack;
440 LRESULT wmcreate;
442 dprintf_win( stddeb, "CreateWindowEx: " );
443 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
444 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
445 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
446 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
448 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
449 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
450 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
452 /* Find the parent window */
454 if (cs->hwndParent)
456 /* Make sure parent is valid */
457 if (!IsWindow( cs->hwndParent ))
459 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
460 return 0;
463 else if (cs->style & WS_CHILD)
465 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
466 return 0; /* WS_CHILD needs a parent */
469 /* Find the window class */
471 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
472 GetExePtr(cs->hInstance) )))
474 char buffer[256];
475 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
476 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
477 return 0;
480 /* Fix the coordinates */
482 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
483 if (cs->cx == CW_USEDEFAULT32)
485 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
486 else */
488 cs->cx = 600;
489 cs->cy = 400;
493 /* Create the window structure */
495 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
496 - sizeof(wndPtr->wExtra) )))
498 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
499 return 0;
502 /* Fill the window structure */
504 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
505 wndPtr->next = NULL;
506 wndPtr->child = NULL;
507 wndPtr->parent = (cs->style & WS_CHILD) ?
508 WIN_FindWndPtr( cs->hwndParent ) : pWndDesktop;
509 wndPtr->owner = (cs->style & WS_CHILD) ? NULL :
510 WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
511 wndPtr->window = 0;
512 wndPtr->class = classPtr;
513 wndPtr->winproc = NULL;
514 wndPtr->dwMagic = WND_MAGIC;
515 wndPtr->hwndSelf = hwnd;
516 wndPtr->hInstance = cs->hInstance;
517 wndPtr->ptIconPos.x = -1;
518 wndPtr->ptIconPos.y = -1;
519 wndPtr->ptMaxPos.x = -1;
520 wndPtr->ptMaxPos.y = -1;
521 wndPtr->text = NULL;
522 wndPtr->hmemTaskQ = GetTaskQueue(0);
523 wndPtr->hrgnUpdate = 0;
524 wndPtr->hwndLastActive = hwnd;
525 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
526 wndPtr->dwExStyle = cs->dwExStyle;
527 wndPtr->wIDmenu = 0;
528 wndPtr->flags = 0;
529 wndPtr->pVScroll = NULL;
530 wndPtr->pHScroll = NULL;
531 wndPtr->hSysMenu = MENU_GetDefSysMenu();
532 wndPtr->hProp = 0;
533 wndPtr->userdata = 0;
535 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
536 classPtr->cWindows++;
538 /* Set the window procedure */
540 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
542 /* Correct the window style */
544 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
546 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
547 wndPtr->flags |= WIN_NEED_SIZE;
549 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
551 /* Get class or window DC if needed */
553 if (classPtr->style & CS_OWNDC) wndPtr->hdce = DCE_AllocDCE(hwnd, DCE_WINDOW_DC);
554 else if (classPtr->style & CS_CLASSDC) wndPtr->hdce = classPtr->hdce;
555 else wndPtr->hdce = 0;
557 /* Insert the window in the linked list */
559 WIN_LinkWindow( hwnd, HWND_BOTTOM );
561 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
563 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
565 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
566 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
567 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
569 if (cs->cx <= 0) cs->cx = 1;
570 if (cs->cy <= 0) cs->cy = 1;
572 wndPtr->rectWindow.left = cs->x;
573 wndPtr->rectWindow.top = cs->y;
574 wndPtr->rectWindow.right = cs->x + cs->cx;
575 wndPtr->rectWindow.bottom = cs->y + cs->cy;
576 wndPtr->rectClient = wndPtr->rectWindow;
577 wndPtr->rectNormal = wndPtr->rectWindow;
579 /* Create the X window (only for top-level windows, and then only */
580 /* when there's no desktop window) */
582 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
584 XSetWindowAttributes win_attr;
585 Atom XA_WM_DELETE_WINDOW;
587 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
588 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
590 win_attr.event_mask = ExposureMask | KeyPressMask |
591 KeyReleaseMask | PointerMotionMask |
592 ButtonPressMask | ButtonReleaseMask |
593 FocusChangeMask | StructureNotifyMask;
594 win_attr.override_redirect = FALSE;
595 wndPtr->flags |= WIN_MANAGED;
597 else
599 win_attr.event_mask = ExposureMask | KeyPressMask |
600 KeyReleaseMask | PointerMotionMask |
601 ButtonPressMask | ButtonReleaseMask |
602 FocusChangeMask;
603 win_attr.override_redirect = TRUE;
605 win_attr.colormap = COLOR_GetColormap();
606 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
607 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
608 win_attr.cursor = CURSORICON_XCursor;
609 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
610 cs->cx, cs->cy, 0, CopyFromParent,
611 InputOutput, CopyFromParent,
612 CWEventMask | CWOverrideRedirect |
613 CWColormap | CWCursor | CWSaveUnder |
614 CWBackingStore, &win_attr );
615 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
616 False );
617 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
619 if ((wndPtr->flags & WIN_MANAGED) &&
620 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
622 XSizeHints* size_hints = XAllocSizeHints();
624 if (size_hints)
626 size_hints->min_width = size_hints->max_width = cs->cx;
627 size_hints->min_height = size_hints->max_height = cs->cy;
628 size_hints->flags = (PSize | PMinSize | PMaxSize);
629 XSetWMSizeHints( display, wndPtr->window, size_hints,
630 XA_WM_NORMAL_HINTS );
631 XFree(size_hints);
635 if (cs->hwndParent) /* Get window owner */
637 Window win = WIN_GetXWindow( cs->hwndParent );
638 if (win) XSetTransientForHint( display, wndPtr->window, win );
640 EVENT_RegisterWindow( wndPtr );
643 /* Set the window menu */
645 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
647 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
648 else
650 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
651 if (classPtr->menuNameA)
652 cs->hMenu = HIWORD(classPtr->menuNameA) ?
653 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
654 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
655 #else
656 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
657 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
658 #endif
660 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
662 else wndPtr->wIDmenu = (UINT)cs->hMenu;
664 /* Send the WM_CREATE message */
666 if (unicode)
668 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
669 else
671 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
672 NULL, NULL, 0, &wndPtr->rectClient );
673 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
676 else
678 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
679 else
681 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
682 NULL, NULL, 0, &wndPtr->rectClient );
683 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
687 if (wmcreate == -1)
689 /* Abort window creation */
690 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
691 WIN_DestroyWindow( hwnd );
692 return 0;
695 /* Send the size messages */
697 if (!(wndPtr->flags & WIN_NEED_SIZE))
699 /* send it anyway */
700 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
701 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
702 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
703 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
704 wndPtr->rectClient.top ));
707 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
708 if (!IsWindow(hwnd)) return 0;
710 /* Show the window, maximizing or minimizing if needed */
712 if (wndPtr->dwStyle & WS_MINIMIZE)
714 wndPtr->dwStyle &= ~WS_MAXIMIZE;
715 WINPOS_FindIconPos( hwnd );
716 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
717 SYSMETRICS_CXICON, SYSMETRICS_CYICON, SWP_FRAMECHANGED |
718 ((cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 ));
720 else if (wndPtr->dwStyle & WS_MAXIMIZE)
722 POINT16 maxSize, maxPos, minTrack, maxTrack;
723 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
724 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
725 SWP_FRAMECHANGED | ((cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0) );
727 else if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
729 /* Call WH_SHELL hook */
731 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
732 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
734 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
735 return hwnd;
739 /***********************************************************************
740 * CreateWindow16 (USER.41)
742 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
743 DWORD style, INT16 x, INT16 y, INT16 width,
744 INT16 height, HWND16 parent, HMENU16 menu,
745 HINSTANCE16 instance, LPVOID data )
747 return CreateWindowEx16( 0, className, windowName, style,
748 x, y, width, height, parent, menu, instance, data );
752 /***********************************************************************
753 * CreateWindowEx16 (USER.452)
755 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
756 DWORD style, INT16 x, INT16 y, INT16 width,
757 INT16 height, HWND16 parent, HMENU16 menu,
758 HINSTANCE16 instance, LPVOID data )
760 ATOM classAtom;
761 CREATESTRUCT32A cs;
763 /* Find the class atom */
765 if (!(classAtom = GlobalFindAtom32A( className )))
767 fprintf( stderr, "CreateWindowEx16: bad class name " );
768 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
769 else fprintf( stderr, "'%s'\n", className );
770 return 0;
773 /* Fix the coordinates */
775 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
776 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
777 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
778 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
780 /* Create the window */
782 cs.lpCreateParams = data;
783 cs.hInstance = (HINSTANCE32)instance;
784 cs.hMenu = (HMENU32)menu;
785 cs.hwndParent = (HWND32)parent;
786 cs.style = style;
787 cs.lpszName = windowName;
788 cs.lpszClass = className;
789 cs.dwExStyle = exStyle;
790 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
794 /***********************************************************************
795 * CreateWindowEx32A (USER32.82)
797 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
798 DWORD style, INT32 x, INT32 y, INT32 width,
799 INT32 height, HWND32 parent, HMENU32 menu,
800 HINSTANCE32 instance, LPVOID data )
802 ATOM classAtom;
803 CREATESTRUCT32A cs;
805 /* Find the class atom */
807 if (!(classAtom = GlobalFindAtom32A( className )))
809 fprintf( stderr, "CreateWindowEx32A: bad class name " );
810 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
811 else fprintf( stderr, "'%s'\n", className );
812 return 0;
815 /* Create the window */
817 cs.lpCreateParams = data;
818 cs.hInstance = instance;
819 cs.hMenu = menu;
820 cs.hwndParent = parent;
821 cs.x = x;
822 cs.y = y;
823 cs.cx = width;
824 cs.cy = height;
825 cs.style = style;
826 cs.lpszName = windowName;
827 cs.lpszClass = className;
828 cs.dwExStyle = exStyle;
829 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
833 /***********************************************************************
834 * CreateWindowEx32W (USER32.83)
836 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
837 DWORD style, INT32 x, INT32 y, INT32 width,
838 INT32 height, HWND32 parent, HMENU32 menu,
839 HINSTANCE32 instance, LPVOID data )
841 ATOM classAtom;
842 CREATESTRUCT32W cs;
844 /* Find the class atom */
846 if (!(classAtom = GlobalFindAtom32W( className )))
848 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
849 return 0;
852 /* Create the window */
854 cs.lpCreateParams = data;
855 cs.hInstance = instance;
856 cs.hMenu = menu;
857 cs.hwndParent = parent;
858 cs.x = x;
859 cs.y = y;
860 cs.cx = width;
861 cs.cy = height;
862 cs.style = style;
863 cs.lpszName = windowName;
864 cs.lpszClass = className;
865 cs.dwExStyle = exStyle;
866 /* Note: we rely on the fact that CREATESTRUCT32A and */
867 /* CREATESTRUCT32W have the same layout. */
868 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
872 /***********************************************************************
873 * DestroyWindow (USER.53)
875 BOOL DestroyWindow( HWND hwnd )
877 WND * wndPtr;
879 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
881 /* Initialization */
883 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
884 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
886 /* Top-level window */
888 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
890 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
891 /* FIXME: clean up palette - see "Internals" p.352 */
894 /* Hide the window */
896 if (wndPtr->dwStyle & WS_VISIBLE)
897 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
898 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
899 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
900 ReleaseCapture();
901 if (!QUEUE_GetDoomedQueue())
902 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
904 /* Recursively destroy owned windows */
906 for (;;)
908 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
909 while (siblingPtr)
911 if (siblingPtr->owner == wndPtr) break;
912 siblingPtr = siblingPtr->next;
914 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
915 else break;
918 CLIPBOARD_DisOwn( hwnd );
920 /* Send destroy messages and destroy children */
922 SendMessage16( hwnd, WM_DESTROY, 0, 0 );
923 while (wndPtr->child) /* The child removes itself from the list */
924 DestroyWindow( wndPtr->child->hwndSelf );
925 SendMessage16( hwnd, WM_NCDESTROY, 0, 0 );
927 /* Destroy the window */
929 WIN_DestroyWindow( hwnd );
930 return TRUE;
934 /***********************************************************************
935 * CloseWindow (USER.43)
937 BOOL CloseWindow(HWND hWnd)
939 WND * wndPtr = WIN_FindWndPtr(hWnd);
940 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
941 ShowWindow(hWnd, SW_MINIMIZE);
942 return TRUE;
946 /***********************************************************************
947 * OpenIcon (USER.44)
949 BOOL OpenIcon(HWND hWnd)
951 if (!IsIconic(hWnd)) return FALSE;
952 ShowWindow(hWnd, SW_SHOWNORMAL);
953 return(TRUE);
957 /***********************************************************************
958 * WIN_FindWindow
960 * Implementation of FindWindow() and FindWindowEx().
962 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
963 LPCSTR title )
965 WND *pWnd;
966 CLASS *pClass = NULL;
968 if (child)
970 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
971 if (parent)
973 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
975 else if (pWnd->parent != pWndDesktop) return 0;
976 pWnd = pWnd->next;
978 else
980 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
981 pWnd = pWnd->child;
983 if (!pWnd) return 0;
985 /* For a child window, all siblings will have the same hInstance, */
986 /* so we can look for the class once and for all. */
988 if (className && (pWnd->dwStyle & WS_CHILD))
990 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
991 return 0;
994 for ( ; pWnd; pWnd = pWnd->next)
996 if (className && !(pWnd->dwStyle & WS_CHILD))
998 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
999 continue; /* Skip this window */
1001 if (pClass && (pWnd->class != pClass))
1002 continue; /* Not the right class */
1004 /* Now check the title */
1006 if (!title) return pWnd->hwndSelf;
1007 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1009 return 0;
1014 /***********************************************************************
1015 * FindWindow16 (USER.50)
1017 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1019 return FindWindowEx16( 0, 0, className, title );
1023 /***********************************************************************
1024 * FindWindowEx16 (USER.427)
1026 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1027 SEGPTR className, LPCSTR title )
1029 ATOM atom;
1031 atom = className ? GlobalFindAtom16( className ) : 0;
1032 return WIN_FindWindow( parent, child, atom, title );
1036 /***********************************************************************
1037 * FindWindow32A (USER32.197)
1039 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1041 return FindWindowEx32A( 0, 0, className, title );
1045 /***********************************************************************
1046 * FindWindowEx32A (USER32.198)
1048 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1049 LPCSTR className, LPCSTR title )
1051 ATOM atom;
1053 atom = className ? GlobalFindAtom32A( className ) : 0;
1054 return WIN_FindWindow( 0, 0, atom, title );
1058 /***********************************************************************
1059 * FindWindowEx32W (USER32.199)
1061 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1062 LPCWSTR className, LPCWSTR title )
1064 ATOM atom;
1065 char *buffer;
1066 HWND hwnd;
1068 atom = className ? GlobalFindAtom32W( className ) : 0;
1069 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1070 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1071 if (buffer) free( buffer );
1072 return hwnd;
1076 /***********************************************************************
1077 * FindWindow32W (USER32.200)
1079 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1081 return FindWindowEx32W( 0, 0, className, title );
1085 /**********************************************************************
1086 * WIN_GetDesktop
1088 WND *WIN_GetDesktop(void)
1090 return pWndDesktop;
1094 /**********************************************************************
1095 * GetDesktopWindow (USER.286)
1097 HWND GetDesktopWindow(void)
1099 return pWndDesktop->hwndSelf;
1103 /**********************************************************************
1104 * GetDesktopHwnd (USER.278)
1106 * Exactly the same thing as GetDesktopWindow(), but not documented.
1107 * Don't ask me why...
1109 HWND GetDesktopHwnd(void)
1111 return pWndDesktop->hwndSelf;
1115 /*******************************************************************
1116 * EnableWindow (USER.34)
1118 BOOL EnableWindow( HWND hwnd, BOOL enable )
1120 WND *wndPtr;
1122 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1123 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1125 /* Enable window */
1126 wndPtr->dwStyle &= ~WS_DISABLED;
1127 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1128 return TRUE;
1130 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1132 /* Disable window */
1133 wndPtr->dwStyle |= WS_DISABLED;
1134 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1135 SetFocus( 0 ); /* A disabled window can't have the focus */
1136 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1137 ReleaseCapture(); /* A disabled window can't capture the mouse */
1138 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1139 return FALSE;
1141 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1145 /***********************************************************************
1146 * IsWindowEnabled (USER.35) (USER32.348)
1148 BOOL IsWindowEnabled(HWND hWnd)
1150 WND * wndPtr;
1152 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1153 return !(wndPtr->dwStyle & WS_DISABLED);
1157 /***********************************************************************
1158 * IsWindowUnicode (USER32.349)
1160 BOOL32 IsWindowUnicode( HWND32 hwnd )
1162 WND * wndPtr;
1164 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1165 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1169 /**********************************************************************
1170 * GetWindowWord (USER.133) (USER32.313)
1172 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1174 WND * wndPtr = WIN_FindWndPtr( hwnd );
1175 if (!wndPtr) return 0;
1176 if (offset >= 0)
1178 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1180 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1181 return 0;
1183 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1185 switch(offset)
1187 case GWW_ID: return wndPtr->wIDmenu;
1188 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1189 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1190 default:
1191 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1192 return 0;
1197 /**********************************************************************
1198 * WIN_GetWindowInstance
1200 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
1202 WND * wndPtr = WIN_FindWndPtr( hwnd );
1203 if (!wndPtr) return (HINSTANCE)0;
1204 return wndPtr->hInstance;
1208 /**********************************************************************
1209 * SetWindowWord (USER.134) (USER32.523)
1211 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1213 WORD *ptr, retval;
1214 WND * wndPtr = WIN_FindWndPtr( hwnd );
1215 if (!wndPtr) return 0;
1216 if (offset >= 0)
1218 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1220 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1221 return 0;
1223 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1225 else switch(offset)
1227 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1228 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1229 default:
1230 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1231 return 0;
1233 retval = *ptr;
1234 *ptr = newval;
1235 return retval;
1239 /**********************************************************************
1240 * WIN_GetWindowLong
1242 * Helper function for GetWindowLong().
1244 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1246 LONG retval;
1247 WND * wndPtr = WIN_FindWndPtr( hwnd );
1248 if (!wndPtr) return 0;
1249 if (offset >= 0)
1251 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1253 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1254 return 0;
1256 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1257 /* Special case for dialog window procedure */
1258 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1259 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1260 return retval;
1262 switch(offset)
1264 case GWL_USERDATA: return wndPtr->userdata;
1265 case GWL_STYLE: return wndPtr->dwStyle;
1266 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1267 case GWL_ID: return wndPtr->wIDmenu;
1268 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1269 type );
1270 case GWL_HWNDPARENT: return wndPtr->parent ?
1271 (HWND32)wndPtr->parent->hwndSelf : 0;
1272 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1273 default:
1274 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1276 return 0;
1280 /**********************************************************************
1281 * WIN_SetWindowLong
1283 * Helper function for SetWindowLong().
1285 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1286 WINDOWPROCTYPE type )
1288 LONG *ptr, retval;
1289 WND * wndPtr = WIN_FindWndPtr( hwnd );
1290 if (!wndPtr) return 0;
1291 if (offset >= 0)
1293 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1295 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1296 return 0;
1298 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1299 /* Special case for dialog window procedure */
1300 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1302 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1303 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1304 return retval;
1307 else switch(offset)
1309 case GWL_ID:
1310 case GWL_HINSTANCE:
1311 return SetWindowWord( hwnd, offset, (WORD)newval );
1312 case GWL_WNDPROC:
1313 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1314 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1315 return retval;
1316 case GWL_STYLE:
1317 ptr = &wndPtr->dwStyle;
1318 /* Some bits can't be changed this way */
1319 newval &= ~(WS_VISIBLE | WS_CHILD);
1320 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1321 break;
1322 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1323 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1324 default:
1325 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1326 return 0;
1328 retval = *ptr;
1329 *ptr = newval;
1330 return retval;
1334 /**********************************************************************
1335 * GetWindowLong16 (USER.135)
1337 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1339 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1343 /**********************************************************************
1344 * GetWindowLong32A (USER32.304)
1346 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1348 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1352 /**********************************************************************
1353 * GetWindowLong32W (USER32.305)
1355 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1357 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1361 /**********************************************************************
1362 * SetWindowLong16 (USER.136)
1364 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1366 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1370 /**********************************************************************
1371 * SetWindowLong32A (USER32.516)
1373 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1375 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1379 /**********************************************************************
1380 * SetWindowLong32W (USER32.517)
1382 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1384 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1388 /*******************************************************************
1389 * GetWindowText16 (USER.36)
1391 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1393 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1397 /*******************************************************************
1398 * GetWindowText32A (USER32.308)
1400 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1402 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1403 (LPARAM)lpString );
1407 /*******************************************************************
1408 * GetWindowText32W (USER32.311)
1410 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1412 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1413 (LPARAM)lpString );
1417 /*******************************************************************
1418 * SetWindowText16 (USER.37)
1420 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1422 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1426 /*******************************************************************
1427 * SetWindowText32A (USER32.)
1429 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1431 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1435 /*******************************************************************
1436 * SetWindowText32W (USER32.)
1438 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1440 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1444 /*******************************************************************
1445 * GetWindowTextLength (USER.38)
1447 int GetWindowTextLength(HWND hwnd)
1449 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1453 /*******************************************************************
1454 * IsWindow (USER.47) (USER32.347)
1456 BOOL16 IsWindow( HWND32 hwnd )
1458 WND * wndPtr = WIN_FindWndPtr( hwnd );
1459 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1463 /*****************************************************************
1464 * GetParent (USER.46)
1466 HWND GetParent(HWND hwnd)
1468 WND *wndPtr = WIN_FindWndPtr(hwnd);
1469 if (!wndPtr) return 0;
1470 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1471 return wndPtr ? wndPtr->hwndSelf : 0;
1475 /*****************************************************************
1476 * WIN_GetTopParent
1478 * Get the top-level parent for a child window.
1480 HWND WIN_GetTopParent( HWND hwnd )
1482 WND *wndPtr = WIN_FindWndPtr( hwnd );
1483 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1484 return wndPtr ? wndPtr->hwndSelf : 0;
1488 /*****************************************************************
1489 * SetParent (USER.233)
1491 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1493 HWND oldParent;
1495 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1496 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1497 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1499 oldParent = wndPtr->parent->hwndSelf;
1501 WIN_UnlinkWindow(hwndChild);
1502 if (hwndNewParent) wndPtr->parent = pWndParent;
1503 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1505 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1507 return oldParent;
1512 /*******************************************************************
1513 * IsChild (USER.48)
1515 BOOL IsChild( HWND parent, HWND child )
1517 WND * wndPtr = WIN_FindWndPtr( child );
1518 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1520 wndPtr = wndPtr->parent;
1521 if (wndPtr->hwndSelf == parent) return TRUE;
1523 return FALSE;
1527 /***********************************************************************
1528 * IsWindowVisible (USER.49) (USER32.350)
1530 BOOL IsWindowVisible( HWND hwnd )
1532 WND *wndPtr = WIN_FindWndPtr( hwnd );
1533 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1535 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1536 wndPtr = wndPtr->parent;
1538 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1543 /*******************************************************************
1544 * GetTopWindow (USER.229)
1546 HWND GetTopWindow( HWND hwnd )
1548 WND * wndPtr = WIN_FindWndPtr( hwnd );
1549 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1550 else return 0;
1554 /*******************************************************************
1555 * GetWindow (USER.262)
1557 HWND GetWindow( HWND hwnd, WORD rel )
1559 WND * wndPtr = WIN_FindWndPtr( hwnd );
1560 if (!wndPtr) return 0;
1561 switch(rel)
1563 case GW_HWNDFIRST:
1564 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1565 else return 0;
1567 case GW_HWNDLAST:
1568 if (!wndPtr->parent) return 0; /* Desktop window */
1569 while (wndPtr->next) wndPtr = wndPtr->next;
1570 return wndPtr->hwndSelf;
1572 case GW_HWNDNEXT:
1573 if (!wndPtr->next) return 0;
1574 return wndPtr->next->hwndSelf;
1576 case GW_HWNDPREV:
1577 if (!wndPtr->parent) return 0; /* Desktop window */
1578 wndPtr = wndPtr->parent->child; /* First sibling */
1579 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1580 while (wndPtr->next)
1582 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1583 wndPtr = wndPtr->next;
1585 return 0;
1587 case GW_OWNER:
1588 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1590 case GW_CHILD:
1591 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1593 return 0;
1597 /*******************************************************************
1598 * GetNextWindow (USER.230)
1600 HWND GetNextWindow( HWND hwnd, WORD flag )
1602 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1603 return GetWindow( hwnd, flag );
1606 /*******************************************************************
1607 * ShowOwnedPopups (USER.265)
1609 void ShowOwnedPopups( HWND owner, BOOL fShow )
1611 WND *pWnd = pWndDesktop->child;
1612 while (pWnd)
1614 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1615 (pWnd->dwStyle & WS_POPUP))
1616 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1617 pWnd = pWnd->next;
1622 /*******************************************************************
1623 * GetLastActivePopup (USER.287)
1625 HWND GetLastActivePopup(HWND hwnd)
1627 WND *wndPtr;
1628 wndPtr = WIN_FindWndPtr(hwnd);
1629 if (wndPtr == NULL) return hwnd;
1630 return wndPtr->hwndLastActive;
1634 /*******************************************************************
1635 * WIN_BuildWinArray
1637 * Build an array of pointers to all children of a given window.
1638 * The array must be freed with HeapFree(SystemHeap).
1640 WND **WIN_BuildWinArray( WND *wndPtr )
1642 WND **list, **ppWnd;
1643 WND *pWnd;
1644 INT32 count;
1646 /* First count the windows */
1648 if (!wndPtr) wndPtr = pWndDesktop;
1649 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1650 count++; /* For the terminating NULL */
1652 /* Now build the list of all windows */
1654 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1655 return NULL;
1656 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1657 *ppWnd++ = pWnd;
1658 *ppWnd = NULL;
1659 return list;
1663 /*******************************************************************
1664 * EnumWindows16 (USER.54)
1666 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1668 WND **list, **ppWnd;
1670 /* We have to build a list of all windows first, to avoid */
1671 /* unpleasant side-effects, for instance if the callback */
1672 /* function changes the Z-order of the windows. */
1674 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1676 /* Now call the callback function for every window */
1678 for (ppWnd = list; *ppWnd; ppWnd++)
1680 /* Make sure that the window still exists */
1681 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1682 if (!CallEnumWindowsProc16( (FARPROC16)lpEnumFunc,
1683 (*ppWnd)->hwndSelf, lParam ))
1684 break;
1686 HeapFree( SystemHeap, 0, list );
1687 return TRUE;
1691 /*******************************************************************
1692 * EnumWindows32 (USER32.192)
1694 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1696 WND **list, **ppWnd;
1698 /* We have to build a list of all windows first, to avoid */
1699 /* unpleasant side-effects, for instance if the callback */
1700 /* function changes the Z-order of the windows. */
1702 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1704 /* Now call the callback function for every window */
1706 for (ppWnd = list; *ppWnd; ppWnd++)
1708 /* Make sure that the window still exists */
1709 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1710 if (!CallEnumWindowsProc32( lpEnumFunc, (*ppWnd)->hwndSelf, lParam ))
1711 break;
1713 HeapFree( SystemHeap, 0, list );
1714 return TRUE;
1718 /**********************************************************************
1719 * EnumTaskWindows16 (USER.225)
1721 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1723 WND **list, **ppWnd;
1724 HANDLE hQueue = GetTaskQueue( hTask );
1726 /* This function is the same as EnumWindows(), */
1727 /* except for an added check on the window queue. */
1729 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1731 /* Now call the callback function for every window */
1733 for (ppWnd = list; *ppWnd; ppWnd++)
1735 /* Make sure that the window still exists */
1736 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1737 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1738 if (!CallEnumWindowsProc16( (FARPROC16)func,
1739 (*ppWnd)->hwndSelf, lParam ))
1740 break;
1742 HeapFree( SystemHeap, 0, list );
1743 return TRUE;
1747 /**********************************************************************
1748 * EnumThreadWindows (USER32.189)
1750 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1752 WND **list, **ppWnd;
1753 HANDLE hQueue = GetTaskQueue( (DWORD)id );
1755 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1757 /* Now call the callback function for every window */
1759 for (ppWnd = list; *ppWnd; ppWnd++)
1761 /* Make sure that the window still exists */
1762 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1763 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1764 if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
1765 break;
1767 HeapFree( SystemHeap, 0, list );
1768 return TRUE;
1772 /**********************************************************************
1773 * WIN_EnumChildWindows16
1775 * Helper function for EnumChildWindows16().
1777 static BOOL16 WIN_EnumChildWindows16( WND **ppWnd, WNDENUMPROC16 func,
1778 LPARAM lParam )
1780 WND **childList;
1781 BOOL16 ret = FALSE;
1783 while (*ppWnd)
1785 /* Make sure that the window still exists */
1786 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1787 /* Build children list first */
1788 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1789 if (!CallEnumWindowsProc16((FARPROC16)func,(*ppWnd)->hwndSelf,lParam))
1790 return FALSE;
1791 ret = WIN_EnumChildWindows16( childList, func, lParam );
1792 HeapFree( SystemHeap, 0, childList );
1793 if (!ret) return FALSE;
1794 ppWnd++;
1796 return TRUE;
1800 /**********************************************************************
1801 * WIN_EnumChildWindows32
1803 * Helper function for EnumChildWindows32().
1805 static BOOL32 WIN_EnumChildWindows32( WND **ppWnd, WNDENUMPROC32 func,
1806 LPARAM lParam )
1808 WND **childList;
1809 BOOL32 ret = FALSE;
1811 while (*ppWnd)
1813 /* Make sure that the window still exists */
1814 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1815 /* Build children list first */
1816 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1817 if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
1818 return FALSE;
1819 ret = WIN_EnumChildWindows32( childList, func, lParam );
1820 HeapFree( SystemHeap, 0, childList );
1821 if (!ret) return FALSE;
1822 ppWnd++;
1824 return TRUE;
1828 /**********************************************************************
1829 * EnumChildWindows16 (USER.55)
1831 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1833 WND **list, *pParent;
1835 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1836 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1837 WIN_EnumChildWindows16( list, func, lParam );
1838 HeapFree( SystemHeap, 0, list );
1839 return TRUE;
1843 /**********************************************************************
1844 * EnumChildWindows32 (USER32.177)
1846 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1848 WND **list, *pParent;
1850 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1851 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1852 WIN_EnumChildWindows32( list, func, lParam );
1853 HeapFree( SystemHeap, 0, list );
1854 return TRUE;
1858 /*******************************************************************
1859 * AnyPopup (USER.52)
1861 BOOL AnyPopup(void)
1863 WND *wndPtr;
1864 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1865 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1866 return FALSE;
1869 /*******************************************************************
1870 * FlashWindow [USER.105]
1872 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1874 WND *wndPtr = WIN_FindWndPtr(hWnd);
1876 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
1878 if (!wndPtr) return FALSE;
1880 if (wndPtr->dwStyle & WS_MINIMIZE)
1882 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1884 HDC hDC = GetDC(hWnd);
1886 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1887 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1889 ReleaseDC( hWnd, hDC );
1890 wndPtr->flags |= WIN_NCACTIVATED;
1892 else
1894 RedrawWindow32( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1895 RDW_UPDATENOW | RDW_FRAME );
1896 wndPtr->flags &= ~WIN_NCACTIVATED;
1898 return TRUE;
1900 else
1902 WPARAM wparam;
1903 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1904 else wparam = (hWnd == GetActiveWindow());
1906 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1907 return wparam;
1912 /*******************************************************************
1913 * SetSysModalWindow16 (USER.188)
1915 HWND16 SetSysModalWindow16( HWND16 hWnd )
1917 HWND hWndOldModal = hwndSysModal;
1918 hwndSysModal = hWnd;
1919 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
1920 return hWndOldModal;
1924 /*******************************************************************
1925 * GetSysModalWindow16 (USER.52)
1927 HWND16 GetSysModalWindow16(void)
1929 return hwndSysModal;
1933 /*******************************************************************
1934 * DRAG_QueryUpdate
1936 * recursively find a child that contains spDragInfo->pt point
1937 * and send WM_QUERYDROPOBJECT
1939 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1941 BOOL wParam,bResult = 0;
1942 POINT16 pt;
1943 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1944 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1945 RECT16 tempRect; /* this sucks */
1947 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1949 pt = ptrDragInfo->pt;
1951 GetWindowRect16(hQueryWnd,&tempRect);
1953 if( !PtInRect16(&tempRect,pt) ||
1954 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1955 return 0;
1957 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1959 tempRect = ptrQueryWnd->rectClient;
1960 if(ptrQueryWnd->dwStyle & WS_CHILD)
1961 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
1963 if( PtInRect16(&tempRect,pt) )
1965 wParam = 0;
1967 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
1968 if( ptrWnd->dwStyle & WS_VISIBLE )
1970 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
1972 if( PtInRect16(&tempRect,pt) )
1973 break;
1976 if(ptrWnd)
1978 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
1979 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
1980 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
1981 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1982 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo);
1985 if(bResult) return bResult;
1987 else wParam = 1;
1989 else wParam = 1;
1991 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
1993 ptrDragInfo->hScope = hQueryWnd;
1995 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
1996 (WPARAM)wParam ,(LPARAM) spDragInfo );
1997 if( !bResult )
1998 ptrDragInfo->pt = pt;
2000 return bResult;
2003 /*******************************************************************
2004 * DragDetect ( USER.465 )
2007 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2009 MSG16 msg;
2010 RECT16 rect;
2012 rect.left = pt.x - wDragWidth;
2013 rect.right = pt.x + wDragWidth;
2015 rect.top = pt.y - wDragHeight;
2016 rect.bottom = pt.y + wDragHeight;
2018 SetCapture(hWnd);
2020 while(1)
2022 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2024 if( msg.message == WM_LBUTTONUP )
2026 ReleaseCapture();
2027 return 0;
2029 if( msg.message == WM_MOUSEMOVE )
2031 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2033 ReleaseCapture();
2034 return 1;
2038 WaitMessage();
2041 return 0;
2044 /******************************************************************************
2045 * DragObject ( USER.464 )
2048 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
2049 WORD szList , HCURSOR hCursor)
2051 MSG16 msg;
2052 LPDRAGINFO lpDragInfo;
2053 SEGPTR spDragInfo;
2054 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
2055 HANDLE hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2056 WND *wndPtr = WIN_FindWndPtr(hWnd);
2057 DWORD dwRet = 0;
2058 short dragDone = 0;
2059 HCURSOR hCurrentCursor = 0;
2060 HWND hCurrentWnd = 0;
2061 WORD btemp;
2063 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2064 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2066 if( !lpDragInfo || !spDragInfo ) return 0L;
2068 hBummer = LoadCursor16(0,IDC_BUMMER);
2070 if( !hBummer || !wndPtr )
2072 GlobalFree16(hDragInfo);
2073 return 0L;
2076 if(hCursor)
2078 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
2080 GlobalFree16(hDragInfo);
2081 return 0L;
2084 if( hDragCursor == hCursor ) hDragCursor = 0;
2085 else hCursor = hDragCursor;
2087 hOldCursor = SetCursor(hDragCursor);
2090 lpDragInfo->hWnd = hWnd;
2091 lpDragInfo->hScope = 0;
2092 lpDragInfo->wFlags = wObj;
2093 lpDragInfo->hList = szList; /* near pointer! */
2094 lpDragInfo->hOfStruct = hOfStruct;
2095 lpDragInfo->l = 0L;
2097 SetCapture(hWnd);
2098 ShowCursor(1);
2100 while( !dragDone )
2102 WaitMessage();
2104 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2105 continue;
2107 *(lpDragInfo+1) = *lpDragInfo;
2109 lpDragInfo->pt = msg.pt;
2111 /* update DRAGINFO struct */
2112 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2114 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
2115 hCurrentCursor = hCursor;
2116 else
2118 hCurrentCursor = hBummer;
2119 lpDragInfo->hScope = 0;
2121 if( hCurrentCursor )
2122 SetCursor(hCurrentCursor);
2124 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
2126 /* send WM_DRAGLOOP */
2127 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
2128 (LPARAM) spDragInfo );
2129 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2130 if( hCurrentWnd != lpDragInfo->hScope )
2132 if( hCurrentWnd )
2133 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2134 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2135 HIWORD(spDragInfo)) );
2136 hCurrentWnd = lpDragInfo->hScope;
2137 if( hCurrentWnd )
2138 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2140 else
2141 if( hCurrentWnd )
2142 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2145 /* check if we're done */
2146 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2147 dragDone = TRUE;
2150 ReleaseCapture();
2151 ShowCursor(0);
2153 if( hCursor )
2155 SetCursor(hOldCursor);
2156 if( hDragCursor )
2157 DestroyCursor(hDragCursor);
2160 if( hCurrentCursor != hBummer )
2161 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2162 (WPARAM)hWnd, (LPARAM)spDragInfo );
2163 GlobalFree16(hDragInfo);
2165 return dwRet;