Release 951226
[wine/multimedia.git] / windows / win.c
blobda50aec573475afd7dc50c294c47946ac968e43f
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "menu.h"
17 #include "cursoricon.h"
18 #include "event.h"
19 #include "message.h"
20 #include "nonclient.h"
21 #include "winpos.h"
22 #include "color.h"
23 #include "shm_main_blk.h"
24 #include "dde_proc.h"
25 #include "callback.h"
26 #include "stddebug.h"
27 /* #define DEBUG_WIN */
28 /* #define DEBUG_MENU */
29 #include "debug.h"
31 static HWND hwndDesktop = 0;
32 static HWND hwndSysModal = 0;
34 static WORD wDragWidth = 4;
35 static WORD wDragHeight= 3;
37 extern HCURSOR CURSORICON_IconToCursor(HICON);
39 /***********************************************************************
40 * WIN_FindWndPtr
42 * Return a pointer to the WND structure corresponding to a HWND.
44 WND * WIN_FindWndPtr( HWND hwnd )
46 WND * ptr;
48 if (!hwnd) return NULL;
49 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
50 if (ptr->dwMagic != WND_MAGIC) return NULL;
51 return ptr;
55 /***********************************************************************
56 * WIN_GetXWindow
58 * Return the X window associated to a window.
60 Window WIN_GetXWindow( HWND hwnd )
62 WND *wndPtr = WIN_FindWndPtr( hwnd );
63 while (wndPtr && !wndPtr->window)
65 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
67 return wndPtr ? wndPtr->window : 0;
71 /***********************************************************************
72 * WIN_UnlinkWindow
74 * Remove a window from the siblings linked list.
76 BOOL WIN_UnlinkWindow( HWND hwnd )
78 HWND * curWndPtr;
79 WND *parentPtr, *wndPtr;
81 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
82 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
84 curWndPtr = &parentPtr->hwndChild;
86 while (*curWndPtr != hwnd)
88 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
89 curWndPtr = &curPtr->hwndNext;
91 *curWndPtr = wndPtr->hwndNext;
92 return TRUE;
96 /***********************************************************************
97 * WIN_LinkWindow
99 * Insert a window into the siblings linked list.
100 * The window is inserted after the specified window, which can also
101 * be specified as HWND_TOP or HWND_BOTTOM.
103 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
105 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
106 WND *wndPtr, *parentPtr;
108 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
109 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
111 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
113 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
114 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
115 while (*hwndPtr)
117 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
118 hwndPtr = &nextPtr->hwndNext;
121 else /* Normal case */
123 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
124 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
126 if (!hwndPtr) return FALSE;
127 wndPtr->hwndNext = *hwndPtr;
128 *hwndPtr = hwnd;
129 return TRUE;
133 /***********************************************************************
134 * WIN_FindWinToRepaint
136 * Find a window that needs repaint.
138 HWND WIN_FindWinToRepaint( HWND hwnd )
140 WND * wndPtr;
142 /* Note: the desktop window never gets WM_PAINT messages */
143 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
144 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
146 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
147 dprintf_win( stddeb, "WIN_FindWinToRepaint: "NPFMT", style %08lx\n",
148 hwnd, wndPtr->dwStyle );
149 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
150 continue;
151 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
152 continue;
153 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
154 return hwnd;
155 if (wndPtr->hwndChild)
157 HWND child;
158 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
159 return child;
162 return 0;
166 /***********************************************************************
167 * WIN_SendParentNotify
169 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
170 * the window has the WS_EX_NOPARENTNOTIFY style.
172 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
174 WND *wndPtr = WIN_FindWndPtr( hwnd );
176 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
178 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
179 #ifdef WINELIB32
180 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY,
181 MAKEWPARAM(event,idChild),
182 (LPARAM)lValue );
183 #else
184 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event,
185 MAKELPARAM(LOWORD(lValue), idChild) );
186 #endif
187 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
192 /***********************************************************************
193 * WIN_DestroyWindow
195 * Destroy storage associated to a window
197 static void WIN_DestroyWindow( HWND hwnd )
199 WND *wndPtr = WIN_FindWndPtr( hwnd );
200 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
202 #ifdef CONFIG_IPC
203 if (main_block)
204 DDE_DestroyWindow(hwnd);
205 #endif /* CONFIG_IPC */
207 if (!wndPtr || !classPtr) return;
208 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
209 wndPtr->dwMagic = 0; /* Mark it as invalid */
210 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
212 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
213 MSG_DecPaintCount( wndPtr->hmemTaskQ );
215 if (!(wndPtr->dwStyle & WS_CHILD))
217 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
219 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
220 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
221 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
222 classPtr->cWindows--;
223 USER_HEAP_FREE( hwnd );
227 /***********************************************************************
228 * WIN_CreateDesktopWindow
230 * Create the desktop window.
232 BOOL WIN_CreateDesktopWindow(void)
234 WND *wndPtr;
235 HCLASS hclass;
236 CLASS *classPtr;
237 HDC hdc;
239 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
240 return FALSE;
242 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
243 if (!hwndDesktop) return FALSE;
244 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
246 wndPtr->hwndNext = 0;
247 wndPtr->hwndChild = 0;
248 wndPtr->dwMagic = WND_MAGIC;
249 wndPtr->hwndParent = 0;
250 wndPtr->hwndOwner = 0;
251 wndPtr->hClass = hclass;
252 wndPtr->hInstance = 0;
253 wndPtr->rectWindow.left = 0;
254 wndPtr->rectWindow.top = 0;
255 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
256 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
257 wndPtr->rectClient = wndPtr->rectWindow;
258 wndPtr->rectNormal = wndPtr->rectWindow;
259 wndPtr->ptIconPos.x = -1;
260 wndPtr->ptIconPos.y = -1;
261 wndPtr->ptMaxPos.x = -1;
262 wndPtr->ptMaxPos.y = -1;
263 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
264 wndPtr->hrgnUpdate = 0;
265 wndPtr->hwndLastActive = hwndDesktop;
266 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
267 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
268 wndPtr->dwExStyle = 0;
269 wndPtr->hdce = 0;
270 wndPtr->hVScroll = 0;
271 wndPtr->hHScroll = 0;
272 wndPtr->wIDmenu = 0;
273 wndPtr->hText = 0;
274 wndPtr->flags = 0;
275 wndPtr->window = rootWindow;
276 wndPtr->hSysMenu = 0;
277 wndPtr->hProp = 0;
278 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
279 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
280 if ((hdc = GetDC( hwndDesktop )) != 0)
282 SendMessage( hwndDesktop, WM_ERASEBKGND, (WPARAM)hdc, 0 );
283 ReleaseDC( hwndDesktop, hdc );
285 return TRUE;
289 /***********************************************************************
290 * CreateWindow (USER.41)
292 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
293 DWORD style, INT x, INT y, INT width, INT height,
294 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
296 return CreateWindowEx( 0, className, windowName, style,
297 x, y, width, height, parent, menu, instance, data );
301 /***********************************************************************
302 * CreateWindowEx (USER.452)
304 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
305 DWORD style, INT x, INT y, INT width, INT height,
306 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
308 HANDLE class, hwnd;
309 CLASS *classPtr;
310 WND *wndPtr;
311 POINT maxSize, maxPos, minTrack, maxTrack;
312 CREATESTRUCT createStruct;
313 int wmcreate;
314 XSetWindowAttributes win_attr;
316 /* FIXME: windowName and className should be SEGPTRs */
318 dprintf_win( stddeb, "CreateWindowEx: " );
319 if (HIWORD(windowName))
320 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
321 else
322 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
323 if (HIWORD(className))
324 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
325 else
326 dprintf_win( stddeb, "%04x ", LOWORD(className) );
328 dprintf_win(stddeb, "%08lx %08lx %d,%d %dx%d "NPFMT" "NPFMT" "NPFMT" %08lx\n",
329 exStyle, style, x, y, width, height,
330 parent, menu, instance, (DWORD)data);
332 if (x == CW_USEDEFAULT) x = y = 0;
333 if (width == CW_USEDEFAULT)
335 width = 600;
336 height = 400;
339 /* Find the parent and class */
341 if (parent)
343 /* Make sure parent is valid */
344 if (!IsWindow( parent )) {
345 dprintf_win(stddeb,"CreateWindowEx: Parent "NPFMT" is not a window\n", parent);
346 return 0;
349 else
351 if (style & WS_CHILD) {
352 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
353 return 0; /* WS_CHILD needs a parent */
357 if (!(class = CLASS_FindClassByName( className, GetExePtr(instance),
358 &classPtr )))
360 fprintf(stderr,"CreateWindow BAD CLASSNAME " );
361 if (HIWORD(className)) fprintf( stderr, "'%s'\n",
362 (char *)PTR_SEG_TO_LIN(className) );
363 else fprintf( stderr, "%04x\n", LOWORD(className) );
364 return 0;
367 /* Correct the window style */
369 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
370 style |= WS_CAPTION | WS_CLIPSIBLINGS;
371 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
373 /* Create the window structure */
375 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
376 if (!hwnd) {
377 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
378 return 0;
381 /* Fill the structure */
383 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
384 wndPtr->hwndNext = 0;
385 wndPtr->hwndChild = 0;
386 wndPtr->window = 0;
387 wndPtr->dwMagic = WND_MAGIC;
388 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
389 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
390 wndPtr->hClass = class;
391 wndPtr->hInstance = instance;
392 wndPtr->ptIconPos.x = -1;
393 wndPtr->ptIconPos.y = -1;
394 wndPtr->ptMaxPos.x = -1;
395 wndPtr->ptMaxPos.y = -1;
396 wndPtr->hmemTaskQ = GetTaskQueue(0);
397 wndPtr->hrgnUpdate = 0;
398 wndPtr->hwndLastActive = hwnd;
399 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
400 wndPtr->dwStyle = style & ~WS_VISIBLE;
401 wndPtr->dwExStyle = exStyle;
402 wndPtr->wIDmenu = 0;
403 wndPtr->hText = 0;
404 wndPtr->flags = 0;
405 wndPtr->hVScroll = 0;
406 wndPtr->hHScroll = 0;
407 wndPtr->hSysMenu = 0;
408 wndPtr->hProp = 0;
410 if (classPtr->wc.cbWndExtra)
411 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
412 classPtr->cWindows++;
414 /* Get class or window DC if needed */
416 if (classPtr->wc.style & CS_OWNDC)
417 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
418 else if (classPtr->wc.style & CS_CLASSDC)
419 wndPtr->hdce = classPtr->hdce;
420 else
421 wndPtr->hdce = 0;
423 /* Insert the window in the linked list */
425 WIN_LinkWindow( hwnd, HWND_TOP );
427 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
429 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
431 if (maxSize.x < width) width = maxSize.x;
432 if (maxSize.y < height) height = maxSize.y;
433 if (width <= 0) width = 1;
434 if (height <= 0) height = 1;
436 wndPtr->rectWindow.left = x;
437 wndPtr->rectWindow.top = y;
438 wndPtr->rectWindow.right = x + width;
439 wndPtr->rectWindow.bottom = y + height;
440 wndPtr->rectClient = wndPtr->rectWindow;
441 wndPtr->rectNormal = wndPtr->rectWindow;
443 /* Create the X window (only for top-level windows, and then only */
444 /* when there's no desktop window) */
446 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
448 if(Options.managed && className != POPUPMENU_CLASS_ATOM) {
449 win_attr.event_mask = ExposureMask | KeyPressMask |
450 KeyReleaseMask | PointerMotionMask |
451 ButtonPressMask | ButtonReleaseMask |
452 FocusChangeMask | StructureNotifyMask;
453 win_attr.override_redirect = FALSE;
455 else {
456 win_attr.event_mask = ExposureMask | KeyPressMask |
457 KeyReleaseMask | PointerMotionMask |
458 ButtonPressMask | ButtonReleaseMask |
459 FocusChangeMask;
460 win_attr.override_redirect = TRUE;
462 win_attr.colormap = COLOR_WinColormap;
463 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
464 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
465 win_attr.cursor = CURSORICON_XCursor;
466 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
467 width, height, 0, CopyFromParent,
468 InputOutput, CopyFromParent,
469 CWEventMask | CWOverrideRedirect |
470 CWColormap | CWCursor | CWSaveUnder |
471 CWBackingStore, &win_attr );
472 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
473 EVENT_RegisterWindow( wndPtr->window, hwnd );
476 if ((style & WS_CAPTION) && !(style & WS_CHILD))
478 if (menu) SetMenu(hwnd, menu);
479 else if (classPtr->wc.lpszMenuName)
480 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
482 else wndPtr->wIDmenu = (UINT)menu;
484 /* Send the WM_CREATE message */
486 createStruct.lpCreateParams = (LPSTR)data;
487 createStruct.hInstance = instance;
488 createStruct.hMenu = menu;
489 createStruct.hwndParent = parent;
490 createStruct.cx = width;
491 createStruct.cy = height;
492 createStruct.x = x;
493 createStruct.y = y;
494 createStruct.style = style;
495 createStruct.lpszName = windowName;
496 createStruct.lpszClass = className;
497 createStruct.dwExStyle = 0;
499 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct) );
500 if (!wmcreate)
502 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
503 wmcreate = -1;
505 else
507 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
508 NULL, NULL, NULL, &wndPtr->rectClient );
509 wmcreate = SendMessage(hwnd, WM_CREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct));
512 if (wmcreate == -1)
514 /* Abort window creation */
515 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
516 WIN_DestroyWindow( hwnd );
517 return 0;
520 /* Create a copy of SysMenu */
521 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
523 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
525 /* Show the window, maximizing or minimizing if needed */
527 if (wndPtr->dwStyle & WS_MINIMIZE)
529 wndPtr->dwStyle &= ~WS_MAXIMIZE;
530 WINPOS_FindIconPos( hwnd );
531 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
532 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
533 SWP_FRAMECHANGED |
534 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
536 else if (wndPtr->dwStyle & WS_MAXIMIZE)
538 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
539 SWP_FRAMECHANGED |
540 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
542 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
544 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
545 return hwnd;
549 /***********************************************************************
550 * DestroyWindow (USER.53)
552 BOOL DestroyWindow( HWND hwnd )
554 WND * wndPtr;
555 CLASS * classPtr;
557 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
559 /* Initialisation */
561 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
562 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
563 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
565 /* Hide the window */
567 if (wndPtr->dwStyle & WS_VISIBLE)
568 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
569 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
570 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
571 ReleaseCapture();
572 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
574 /* Recursively destroy owned windows */
576 for (;;)
578 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
579 while (hwndSibling)
581 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
582 if (siblingPtr->hwndOwner == hwnd) break;
583 hwndSibling = siblingPtr->hwndNext;
585 if (hwndSibling) DestroyWindow( hwndSibling );
586 else break;
589 /* Send destroy messages and destroy children */
591 SendMessage( hwnd, WM_DESTROY, 0, 0 );
592 while (wndPtr->hwndChild) /* The child removes itself from the list */
593 DestroyWindow( wndPtr->hwndChild );
594 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
596 /* Destroy the window */
598 WIN_DestroyWindow( hwnd );
599 return TRUE;
603 /***********************************************************************
604 * CloseWindow (USER.43)
606 void CloseWindow(HWND hWnd)
608 WND * wndPtr = WIN_FindWndPtr(hWnd);
609 if (wndPtr->dwStyle & WS_CHILD) return;
610 ShowWindow(hWnd, SW_MINIMIZE);
614 /***********************************************************************
615 * OpenIcon (USER.44)
617 BOOL OpenIcon(HWND hWnd)
619 if (!IsIconic(hWnd)) return FALSE;
620 ShowWindow(hWnd, SW_SHOWNORMAL);
621 return(TRUE);
625 /***********************************************************************
626 * FindWindow (USER.50)
628 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
630 HCLASS hclass;
631 CLASS *classPtr;
632 HWND hwnd;
634 if (ClassMatch)
636 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
637 &classPtr );
638 if (!hclass) return 0;
640 else hclass = 0;
642 hwnd = GetTopWindow( hwndDesktop );
643 while(hwnd)
645 WND *wndPtr = WIN_FindWndPtr( hwnd );
646 if (!hclass || (wndPtr->hClass == hclass))
648 /* Found matching class */
649 if (!TitleMatch) return hwnd;
650 if (wndPtr->hText)
652 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
653 if (!strcmp( textPtr, TitleMatch )) return hwnd;
656 hwnd = wndPtr->hwndNext;
658 return 0;
662 /**********************************************************************
663 * GetDesktopWindow (USER.286)
664 * GetDeskTopHwnd (USER.278)
666 HWND GetDesktopWindow(void)
668 return hwndDesktop;
672 /*******************************************************************
673 * EnableWindow (USER.34)
675 BOOL EnableWindow( HWND hwnd, BOOL enable )
677 WND *wndPtr;
679 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
680 if (enable && (wndPtr->dwStyle & WS_DISABLED))
682 /* Enable window */
683 wndPtr->dwStyle &= ~WS_DISABLED;
684 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
685 return TRUE;
687 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
689 /* Disable window */
690 wndPtr->dwStyle |= WS_DISABLED;
691 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
692 SetFocus( 0 ); /* A disabled window can't have the focus */
693 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
694 ReleaseCapture(); /* A disabled window can't capture the mouse */
695 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
696 return FALSE;
698 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
702 /***********************************************************************
703 * IsWindowEnabled (USER.35)
705 BOOL IsWindowEnabled(HWND hWnd)
707 WND * wndPtr;
709 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
710 return !(wndPtr->dwStyle & WS_DISABLED);
714 /**********************************************************************
715 * GetWindowWord (USER.133)
717 WORD GetWindowWord( HWND hwnd, short offset )
719 WND * wndPtr = WIN_FindWndPtr( hwnd );
720 if (!wndPtr) return 0;
721 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
722 switch(offset)
724 case GWW_ID: return wndPtr->wIDmenu;
725 #ifdef WINELIB32
726 case GWW_HWNDPARENT:
727 case GWW_HINSTANCE:
728 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
729 return 0;
730 #else
731 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
732 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
733 #endif
735 return 0;
739 /**********************************************************************
740 * WIN_GetWindowInstance
742 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
744 WND * wndPtr = WIN_FindWndPtr( hwnd );
745 if (!wndPtr) return (HINSTANCE)0;
746 return wndPtr->hInstance;
750 /**********************************************************************
751 * SetWindowWord (USER.134)
753 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
755 WORD *ptr, retval;
756 WND * wndPtr = WIN_FindWndPtr( hwnd );
757 if (!wndPtr) return 0;
758 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
759 else switch(offset)
761 #ifdef WINELIB32
762 case GWW_ID:
763 case GWW_HINSTANCE:
764 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
765 return 0;
766 #else
767 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
768 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
769 #endif
770 default: return 0;
772 retval = *ptr;
773 *ptr = newval;
774 return retval;
778 /**********************************************************************
779 * GetWindowLong (USER.135)
781 LONG GetWindowLong( HWND hwnd, short offset )
783 WND * wndPtr = WIN_FindWndPtr( hwnd );
784 if (!wndPtr) return 0;
785 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
786 switch(offset)
788 case GWL_STYLE: return wndPtr->dwStyle;
789 case GWL_EXSTYLE: return wndPtr->dwExStyle;
790 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
791 #ifdef WINELIB32
792 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
793 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
794 #endif
796 return 0;
800 /**********************************************************************
801 * SetWindowLong (USER.136)
803 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
805 LONG *ptr, retval;
806 WND * wndPtr = WIN_FindWndPtr( hwnd );
807 if (!wndPtr) return 0;
808 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
809 else switch(offset)
811 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
812 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
813 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
814 default: return 0;
816 retval = *ptr;
817 *ptr = newval;
818 return retval;
822 /*******************************************************************
823 * GetWindowText (USER.36)
825 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
827 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
828 (DWORD)lpString);
831 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
833 int len;
834 HANDLE handle;
836 /* We have to allocate a buffer on the USER heap */
837 /* to be able to pass its address to 16-bit code */
838 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
839 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
840 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
841 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
842 USER_HEAP_FREE( handle );
843 return len;
847 /*******************************************************************
848 * SetWindowText (USER.37)
850 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
852 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
855 void SetWindowText( HWND hwnd, LPSTR lpString )
857 HANDLE handle;
859 /* We have to allocate a buffer on the USER heap */
860 /* to be able to pass its address to 16-bit code */
861 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
862 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
863 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
864 USER_HEAP_FREE( handle );
868 /*******************************************************************
869 * GetWindowTextLength (USER.38)
871 int GetWindowTextLength(HWND hwnd)
873 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
877 /*******************************************************************
878 * IsWindow (USER.47)
880 BOOL IsWindow( HWND hwnd )
882 WND * wndPtr = WIN_FindWndPtr( hwnd );
883 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
887 /*****************************************************************
888 * GetParent (USER.46)
890 HWND GetParent(HWND hwnd)
892 WND *wndPtr = WIN_FindWndPtr(hwnd);
893 if (!wndPtr) return 0;
894 return (wndPtr->dwStyle & WS_CHILD) ?
895 wndPtr->hwndParent : wndPtr->hwndOwner;
899 /*****************************************************************
900 * WIN_GetTopParent
902 * Get the top-level parent for a child window.
904 HWND WIN_GetTopParent( HWND hwnd )
906 while (hwnd)
908 WND *wndPtr = WIN_FindWndPtr( hwnd );
909 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
910 else break;
912 return hwnd;
916 /*****************************************************************
917 * SetParent (USER.233)
919 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
921 HWND temp;
923 WND *wndPtr = WIN_FindWndPtr(hwndChild);
924 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
926 temp = wndPtr->hwndParent;
928 WIN_UnlinkWindow(hwndChild);
929 if (hwndNewParent)
930 wndPtr->hwndParent = hwndNewParent;
931 else
932 wndPtr->hwndParent = GetDesktopWindow();
933 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
935 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
937 return temp;
942 /*******************************************************************
943 * IsChild (USER.48)
945 BOOL IsChild( HWND parent, HWND child )
947 WND * wndPtr = WIN_FindWndPtr( child );
948 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
950 if (wndPtr->hwndParent == parent) return TRUE;
951 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
953 return FALSE;
957 /***********************************************************************
958 * IsWindowVisible (USER.49)
960 BOOL IsWindowVisible( HWND hwnd )
962 WND *wndPtr = WIN_FindWndPtr( hwnd );
963 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
965 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
966 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
968 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
973 /*******************************************************************
974 * GetTopWindow (USER.229)
976 HWND GetTopWindow( HWND hwnd )
978 WND * wndPtr = WIN_FindWndPtr( hwnd );
979 if (wndPtr) return wndPtr->hwndChild;
980 else return 0;
984 /*******************************************************************
985 * GetWindow (USER.262)
987 HWND GetWindow( HWND hwnd, WORD rel )
989 WND * wndPtr = WIN_FindWndPtr( hwnd );
990 if (!wndPtr) return 0;
991 switch(rel)
993 case GW_HWNDFIRST:
994 if (wndPtr->hwndParent)
996 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
997 return parentPtr->hwndChild;
999 else return 0;
1001 case GW_HWNDLAST:
1002 if (!wndPtr->hwndParent) return 0; /* Desktop window */
1003 while (wndPtr->hwndNext)
1005 hwnd = wndPtr->hwndNext;
1006 wndPtr = WIN_FindWndPtr( hwnd );
1008 return hwnd;
1010 case GW_HWNDNEXT:
1011 return wndPtr->hwndNext;
1013 case GW_HWNDPREV:
1015 HWND hwndPrev;
1017 if (wndPtr->hwndParent)
1019 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1020 hwndPrev = parentPtr->hwndChild;
1022 else return 0; /* Desktop window */
1023 if (hwndPrev == hwnd) return 0;
1024 while (hwndPrev)
1026 wndPtr = WIN_FindWndPtr( hwndPrev );
1027 if (wndPtr->hwndNext == hwnd) break;
1028 hwndPrev = wndPtr->hwndNext;
1030 return hwndPrev;
1033 case GW_OWNER:
1034 return wndPtr->hwndOwner;
1036 case GW_CHILD:
1037 return wndPtr->hwndChild;
1039 return 0;
1043 /*******************************************************************
1044 * GetNextWindow (USER.230)
1046 HWND GetNextWindow( HWND hwnd, WORD flag )
1048 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1049 return GetWindow( hwnd, flag );
1052 /*******************************************************************
1053 * ShowOwnedPopups (USER.265)
1055 void ShowOwnedPopups( HWND owner, BOOL fShow )
1057 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1058 while (hwnd)
1060 WND *wnd = WIN_FindWndPtr(hwnd);
1061 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1062 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1063 hwnd = wnd->hwndNext;
1068 /*******************************************************************
1069 * GetLastActivePopup (USER.287)
1071 HWND GetLastActivePopup(HWND hwnd)
1073 WND *wndPtr;
1074 wndPtr = WIN_FindWndPtr(hwnd);
1075 if (wndPtr == NULL) return hwnd;
1076 return wndPtr->hwndLastActive;
1080 /*******************************************************************
1081 * EnumWindows (USER.54)
1083 BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
1085 HWND hwnd;
1086 WND *wndPtr;
1087 HWND *list, *pWnd;
1088 int count;
1090 /* We have to build a list of all windows first, to avoid */
1091 /* unpleasant side-effects, for instance if the callback */
1092 /* function changes the Z-order of the windows. */
1094 /* First count the windows */
1096 count = 0;
1097 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1099 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1100 count++;
1102 if (!count) return TRUE;
1104 /* Now build the list of all windows */
1106 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1107 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1109 wndPtr = WIN_FindWndPtr( hwnd );
1110 *pWnd++ = hwnd;
1113 /* Now call the callback function for every window */
1115 for (pWnd = list; count > 0; count--, pWnd++)
1117 /* Make sure that window still exists */
1118 if (!IsWindow(*pWnd)) continue;
1119 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1121 free( list );
1122 return TRUE;
1126 /**********************************************************************
1127 * EnumTaskWindows (USER.225)
1129 BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
1131 HWND hwnd;
1132 WND *wndPtr;
1133 HWND *list, *pWnd;
1134 HANDLE hQueue = GetTaskQueue( hTask );
1135 int count;
1137 /* This function is the same as EnumWindows(), */
1138 /* except for an added check on the window queue. */
1140 /* First count the windows */
1142 count = 0;
1143 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1145 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1146 if (wndPtr->hmemTaskQ == hQueue) count++;
1148 if (!count) return TRUE;
1150 /* Now build the list of all windows */
1152 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1153 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1155 wndPtr = WIN_FindWndPtr( hwnd );
1156 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1159 /* Now call the callback function for every window */
1161 for (pWnd = list; count > 0; count--, pWnd++)
1163 /* Make sure that window still exists */
1164 if (!IsWindow(*pWnd)) continue;
1165 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1167 free( list );
1168 return TRUE;
1172 /*******************************************************************
1173 * WIN_EnumChildWin
1175 * o hwnd is the first child to use, loop until all next windows
1176 * are processed
1178 * o call wdnenumprc
1180 * o call ourselves with the next child window
1183 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1185 WND *wndPtr;
1187 while (hwnd)
1189 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1190 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1191 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1192 hwnd=wndPtr->hwndNext;
1194 return 1;
1197 /*******************************************************************
1198 * EnumChildWindows (USER.55)
1200 * o gets the first child of hwnd
1202 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1204 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1206 WND *wndPtr;
1208 dprintf_enum(stddeb,"EnumChildWindows\n");
1210 if (hwnd == 0) return 0;
1211 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1212 hwnd = wndPtr->hwndChild;
1213 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1217 /*******************************************************************
1218 * AnyPopup [USER.52]
1220 BOOL AnyPopup()
1222 WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
1223 HWND hwnd = wndPtr->hwndChild;
1225 for( ; hwnd ; hwnd = wndPtr->hwndNext )
1227 wndPtr = WIN_FindWndPtr(hwnd);
1228 if(wndPtr->hwndOwner)
1229 if(wndPtr->dwStyle & WS_VISIBLE)
1230 return TRUE;
1232 return FALSE;
1235 /*******************************************************************
1236 * FlashWindow [USER.105]
1238 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1240 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1241 return FALSE;
1245 /*******************************************************************
1246 * SetSysModalWindow [USER.188]
1248 HWND SetSysModalWindow(HWND hWnd)
1250 HWND hWndOldModal = hwndSysModal;
1251 hwndSysModal = hWnd;
1252 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1253 return hWndOldModal;
1257 /*******************************************************************
1258 * GetSysModalWindow [USER.189]
1260 HWND GetSysModalWindow(void)
1262 return hwndSysModal;
1265 /*******************************************************************
1266 * DRAG_QueryUpdate
1268 * recursively find a child that contains spDragInfo->pt point
1269 * and send WM_QUERYDROPOBJECT
1271 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1273 HWND hWnd;
1274 BOOL wParam,bResult = 0;
1275 POINT pt;
1276 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1277 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1278 RECT tempRect; /* this sucks */
1280 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1282 pt = ptrDragInfo->pt;
1284 GetWindowRect(hQueryWnd,&tempRect);
1286 if( !PtInRect(&tempRect,pt) ||
1287 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1288 return 0;
1290 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1292 tempRect = ptrQueryWnd->rectClient;
1293 if(ptrQueryWnd->dwStyle & WS_CHILD)
1294 MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
1296 if( PtInRect(&tempRect,pt) )
1298 wParam = 0;
1299 ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
1301 for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
1302 if( ptrWnd->dwStyle & WS_VISIBLE )
1304 GetWindowRect(hWnd,&tempRect);
1306 if( PtInRect(&tempRect,pt) )
1307 break;
1310 if(ptrWnd)
1311 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
1312 (int)ptrWnd->rectWindow.left,(int)ptrWnd->rectWindow.top,
1313 (int)ptrWnd->rectWindow.right,(int)ptrWnd->rectWindow.bottom);
1314 else
1315 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
1317 if(ptrWnd)
1318 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1319 bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
1321 if(bResult) return bResult;
1323 else wParam = 1;
1325 else wParam = 1;
1327 ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
1329 ptrDragInfo->hScope = hQueryWnd;
1331 bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
1332 (WPARAM)wParam ,(LPARAM) spDragInfo );
1333 if( !bResult )
1334 ptrDragInfo->pt = pt;
1336 return bResult;
1339 /*******************************************************************
1340 * DragDetect ( USER.465 )
1343 BOOL DragDetect(HWND hWnd, POINT pt)
1345 MSG msg;
1346 RECT rect;
1348 rect.left = pt.x - wDragWidth;
1349 rect.right = pt.x + wDragWidth;
1351 rect.top = pt.y - wDragHeight;
1352 rect.bottom = pt.y + wDragHeight;
1354 SetCapture(hWnd);
1356 while(1)
1358 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1360 if( msg.message == WM_LBUTTONUP )
1362 ReleaseCapture();
1363 return 0;
1365 if( msg.message == WM_MOUSEMOVE )
1367 POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
1368 if( !PtInRect( &rect, pt ) )
1370 ReleaseCapture();
1371 return 1;
1375 WaitMessage();
1378 return 0;
1381 /******************************************************************************
1382 * DragObject ( USER.464 )
1385 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1386 WORD szList , HCURSOR hCursor)
1388 MSG msg;
1389 LPDRAGINFO lpDragInfo;
1390 SEGPTR spDragInfo;
1391 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1392 HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1393 WND *wndPtr = WIN_FindWndPtr(hWnd);
1394 DWORD dwRet = 0;
1395 short dragDone = 0;
1396 HCURSOR hCurrentCursor = 0;
1397 HWND hCurrentWnd = 0;
1398 WORD btemp;
1400 fprintf(stdnimp,"DragObject: experimental\n");
1402 lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
1403 spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
1405 if( !lpDragInfo || !spDragInfo ) return 0L;
1407 hBummer = LoadCursor(0,IDC_BUMMER);
1409 if( !hBummer || !wndPtr )
1411 GlobalFree(hDragInfo);
1412 return 0L;
1415 if(hCursor)
1417 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1419 GlobalFree(hDragInfo);
1420 return 0L;
1423 if( hDragCursor == hCursor ) hDragCursor = 0;
1424 else hCursor = hDragCursor;
1426 hOldCursor = SetCursor(hDragCursor);
1429 lpDragInfo->hWnd = hWnd;
1430 lpDragInfo->hScope = 0;
1431 lpDragInfo->wFlags = wObj;
1432 lpDragInfo->hList = szList; /* near pointer! */
1433 lpDragInfo->hOfStruct = hOfStruct;
1434 lpDragInfo->l = 0L;
1436 SetCapture(hWnd);
1437 ShowCursor(1);
1439 while( !dragDone )
1441 WaitMessage();
1443 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1444 continue;
1446 *(lpDragInfo+1) = *lpDragInfo;
1448 lpDragInfo->pt = msg.pt;
1450 /* update DRAGINFO struct */
1451 dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
1453 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1454 hCurrentCursor = hCursor;
1455 else
1457 hCurrentCursor = hBummer;
1458 lpDragInfo->hScope = 0;
1460 if( hCurrentCursor )
1461 SetCursor(hCurrentCursor);
1463 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1465 /* send WM_DRAGLOOP */
1466 SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1467 (LPARAM) spDragInfo );
1468 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1469 if( hCurrentWnd != lpDragInfo->hScope )
1471 if( hCurrentWnd )
1472 SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
1473 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1474 HIWORD(spDragInfo)) );
1475 hCurrentWnd = lpDragInfo->hScope;
1476 if( hCurrentWnd )
1477 SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1479 else
1480 if( hCurrentWnd )
1481 SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1484 /* check if we're done */
1485 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1486 dragDone = TRUE;
1489 ReleaseCapture();
1490 ShowCursor(0);
1492 if( hCursor )
1494 SetCursor(hOldCursor);
1495 if( hDragCursor )
1496 DestroyCursor(hDragCursor);
1499 if( hCurrentCursor != hBummer )
1500 dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
1501 (WPARAM)hWnd, (LPARAM)spDragInfo );
1502 GlobalFree(hDragInfo);
1504 return dwRet;