Release 960114
[wine/gsoc-2012-control.git] / windows / win.c
blob1c7d8953601d0940422d3dd27cc2793a345445d5
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 "cursoricon.h"
17 #include "event.h"
18 #include "message.h"
19 #include "nonclient.h"
20 #include "winpos.h"
21 #include "color.h"
22 #include "shm_main_blk.h"
23 #include "dde_proc.h"
24 #include "callback.h"
25 #include "stddebug.h"
26 /* #define DEBUG_WIN */
27 /* #define DEBUG_MENU */
28 #include "debug.h"
30 static HWND hwndDesktop = 0;
31 static HWND hwndSysModal = 0;
33 static WORD wDragWidth = 4;
34 static WORD wDragHeight= 3;
36 extern HCURSOR CURSORICON_IconToCursor(HICON);
38 /***********************************************************************
39 * WIN_FindWndPtr
41 * Return a pointer to the WND structure corresponding to a HWND.
43 WND * WIN_FindWndPtr( HWND hwnd )
45 WND * ptr;
47 if (!hwnd) return NULL;
48 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
49 if (ptr->dwMagic != WND_MAGIC) return NULL;
50 return ptr;
54 /***********************************************************************
55 * WIN_GetXWindow
57 * Return the X window associated to a window.
59 Window WIN_GetXWindow( HWND hwnd )
61 WND *wndPtr = WIN_FindWndPtr( hwnd );
62 while (wndPtr && !wndPtr->window)
64 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
66 return wndPtr ? wndPtr->window : 0;
70 /***********************************************************************
71 * WIN_UnlinkWindow
73 * Remove a window from the siblings linked list.
75 BOOL WIN_UnlinkWindow( HWND hwnd )
77 HWND * curWndPtr;
78 WND *parentPtr, *wndPtr;
80 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
81 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
83 curWndPtr = &parentPtr->hwndChild;
85 while (*curWndPtr != hwnd)
87 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
88 curWndPtr = &curPtr->hwndNext;
90 *curWndPtr = wndPtr->hwndNext;
91 return TRUE;
95 /***********************************************************************
96 * WIN_LinkWindow
98 * Insert a window into the siblings linked list.
99 * The window is inserted after the specified window, which can also
100 * be specified as HWND_TOP or HWND_BOTTOM.
102 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
104 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
105 WND *wndPtr, *parentPtr;
107 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
108 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
110 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
112 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
113 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
114 while (*hwndPtr)
116 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
117 hwndPtr = &nextPtr->hwndNext;
120 else /* Normal case */
122 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
123 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
125 if (!hwndPtr) return FALSE;
126 wndPtr->hwndNext = *hwndPtr;
127 *hwndPtr = hwnd;
128 return TRUE;
132 /***********************************************************************
133 * WIN_FindWinToRepaint
135 * Find a window that needs repaint.
137 HWND WIN_FindWinToRepaint( HWND hwnd )
139 WND * wndPtr;
141 /* Note: the desktop window never gets WM_PAINT messages */
142 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
143 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
145 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
146 dprintf_win( stddeb, "WIN_FindWinToRepaint: "NPFMT", style %08lx\n",
147 hwnd, wndPtr->dwStyle );
148 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
149 continue;
150 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
151 continue;
152 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
153 return hwnd;
154 if (wndPtr->hwndChild)
156 HWND child;
157 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
158 return child;
161 return 0;
165 /***********************************************************************
166 * WIN_SendParentNotify
168 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
169 * the window has the WS_EX_NOPARENTNOTIFY style.
171 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
173 WND *wndPtr = WIN_FindWndPtr( hwnd );
175 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
177 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
178 #ifdef WINELIB32
179 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY,
180 MAKEWPARAM(event,idChild),
181 (LPARAM)lValue );
182 #else
183 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event,
184 MAKELPARAM(LOWORD(lValue), idChild) );
185 #endif
186 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
191 /***********************************************************************
192 * WIN_DestroyWindow
194 * Destroy storage associated to a window
196 static void WIN_DestroyWindow( HWND hwnd )
198 WND *wndPtr = WIN_FindWndPtr( hwnd );
199 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
201 #ifdef CONFIG_IPC
202 if (main_block)
203 DDE_DestroyWindow(hwnd);
204 #endif /* CONFIG_IPC */
206 if (!wndPtr || !classPtr) return;
207 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
208 wndPtr->dwMagic = 0; /* Mark it as invalid */
209 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
211 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
212 MSG_DecPaintCount( wndPtr->hmemTaskQ );
214 if (!(wndPtr->dwStyle & WS_CHILD))
216 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
218 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
219 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
220 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
221 classPtr->cWindows--;
222 USER_HEAP_FREE( hwnd );
226 /***********************************************************************
227 * WIN_CreateDesktopWindow
229 * Create the desktop window.
231 BOOL WIN_CreateDesktopWindow(void)
233 WND *wndPtr;
234 HCLASS hclass;
235 CLASS *classPtr;
236 HDC hdc;
238 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
239 return FALSE;
241 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
242 if (!hwndDesktop) return FALSE;
243 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
245 wndPtr->hwndNext = 0;
246 wndPtr->hwndChild = 0;
247 wndPtr->dwMagic = WND_MAGIC;
248 wndPtr->hwndParent = 0;
249 wndPtr->hwndOwner = 0;
250 wndPtr->hClass = hclass;
251 wndPtr->hInstance = 0;
252 wndPtr->rectWindow.left = 0;
253 wndPtr->rectWindow.top = 0;
254 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
255 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
256 wndPtr->rectClient = wndPtr->rectWindow;
257 wndPtr->rectNormal = wndPtr->rectWindow;
258 wndPtr->ptIconPos.x = -1;
259 wndPtr->ptIconPos.y = -1;
260 wndPtr->ptMaxPos.x = -1;
261 wndPtr->ptMaxPos.y = -1;
262 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
263 wndPtr->hrgnUpdate = 0;
264 wndPtr->hwndLastActive = hwndDesktop;
265 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
266 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
267 wndPtr->dwExStyle = 0;
268 wndPtr->hdce = 0;
269 wndPtr->hVScroll = 0;
270 wndPtr->hHScroll = 0;
271 wndPtr->wIDmenu = 0;
272 wndPtr->hText = 0;
273 wndPtr->flags = 0;
274 wndPtr->window = rootWindow;
275 wndPtr->hSysMenu = 0;
276 wndPtr->hProp = 0;
277 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
278 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
279 if ((hdc = GetDC( hwndDesktop )) != 0)
281 SendMessage( hwndDesktop, WM_ERASEBKGND, (WPARAM)hdc, 0 );
282 ReleaseDC( hwndDesktop, hdc );
284 return TRUE;
288 /***********************************************************************
289 * CreateWindow (USER.41)
291 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
292 DWORD style, INT x, INT y, INT width, INT height,
293 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
295 return CreateWindowEx( 0, className, windowName, style,
296 x, y, width, height, parent, menu, instance, data );
300 /***********************************************************************
301 * CreateWindowEx (USER.452)
303 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
304 DWORD style, INT x, INT y, INT width, INT height,
305 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
307 HANDLE class, hwnd;
308 CLASS *classPtr;
309 WND *wndPtr;
310 POINT maxSize, maxPos, minTrack, maxTrack;
311 CREATESTRUCT createStruct;
312 int wmcreate;
313 XSetWindowAttributes win_attr;
315 /* FIXME: windowName and className should be SEGPTRs */
317 dprintf_win( stddeb, "CreateWindowEx: " );
318 if (HIWORD(windowName))
319 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
320 else
321 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
322 if (HIWORD(className))
323 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
324 else
325 dprintf_win( stddeb, "%04x ", LOWORD(className) );
327 dprintf_win(stddeb, "%08lx %08lx %d,%d %dx%d "NPFMT" "NPFMT" "NPFMT" %08lx\n",
328 exStyle, style, x, y, width, height,
329 parent, menu, instance, (DWORD)data);
331 if (x == CW_USEDEFAULT) x = y = 0;
332 if (width == CW_USEDEFAULT)
334 width = 600;
335 height = 400;
338 /* Find the parent and class */
340 if (parent)
342 /* Make sure parent is valid */
343 if (!IsWindow( parent )) {
344 dprintf_win(stddeb,"CreateWindowEx: Parent "NPFMT" is not a window\n", parent);
345 return 0;
348 else
350 if (style & WS_CHILD) {
351 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
352 return 0; /* WS_CHILD needs a parent */
356 if (!(class = CLASS_FindClassByName( className, GetExePtr(instance),
357 &classPtr )))
359 fprintf(stderr,"CreateWindow BAD CLASSNAME " );
360 if (HIWORD(className)) fprintf( stderr, "'%s'\n",
361 (char *)PTR_SEG_TO_LIN(className) );
362 else fprintf( stderr, "%04x\n", LOWORD(className) );
363 return 0;
366 /* Correct the window style */
368 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
369 style |= WS_CAPTION | WS_CLIPSIBLINGS;
370 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
372 /* Create the window structure */
374 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
375 if (!hwnd) {
376 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
377 return 0;
380 /* Fill the structure */
382 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
383 wndPtr->hwndNext = 0;
384 wndPtr->hwndChild = 0;
385 wndPtr->window = 0;
386 wndPtr->dwMagic = WND_MAGIC;
387 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
388 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
389 wndPtr->hClass = class;
390 wndPtr->hInstance = instance;
391 wndPtr->ptIconPos.x = -1;
392 wndPtr->ptIconPos.y = -1;
393 wndPtr->ptMaxPos.x = -1;
394 wndPtr->ptMaxPos.y = -1;
395 wndPtr->hmemTaskQ = GetTaskQueue(0);
396 wndPtr->hrgnUpdate = 0;
397 wndPtr->hwndLastActive = hwnd;
398 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
399 wndPtr->dwStyle = style & ~WS_VISIBLE;
400 wndPtr->dwExStyle = exStyle;
401 wndPtr->wIDmenu = 0;
402 wndPtr->hText = 0;
403 wndPtr->flags = 0;
404 wndPtr->hVScroll = 0;
405 wndPtr->hHScroll = 0;
406 wndPtr->hSysMenu = 0;
407 wndPtr->hProp = 0;
409 if (classPtr->wc.cbWndExtra)
410 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
411 classPtr->cWindows++;
413 /* Get class or window DC if needed */
415 if (classPtr->wc.style & CS_OWNDC)
416 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
417 else if (classPtr->wc.style & CS_CLASSDC)
418 wndPtr->hdce = classPtr->hdce;
419 else
420 wndPtr->hdce = 0;
422 /* Insert the window in the linked list */
424 WIN_LinkWindow( hwnd, HWND_TOP );
426 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
428 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
430 if (maxSize.x < width) width = maxSize.x;
431 if (maxSize.y < height) height = maxSize.y;
432 if (width <= 0) width = 1;
433 if (height <= 0) height = 1;
435 wndPtr->rectWindow.left = x;
436 wndPtr->rectWindow.top = y;
437 wndPtr->rectWindow.right = x + width;
438 wndPtr->rectWindow.bottom = y + height;
439 wndPtr->rectClient = wndPtr->rectWindow;
440 wndPtr->rectNormal = wndPtr->rectWindow;
442 /* Create the X window (only for top-level windows, and then only */
443 /* when there's no desktop window) */
445 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
447 if(Options.managed && className != POPUPMENU_CLASS_ATOM) {
448 win_attr.event_mask = ExposureMask | KeyPressMask |
449 KeyReleaseMask | PointerMotionMask |
450 ButtonPressMask | ButtonReleaseMask |
451 FocusChangeMask | StructureNotifyMask;
452 win_attr.override_redirect = FALSE;
454 else {
455 win_attr.event_mask = ExposureMask | KeyPressMask |
456 KeyReleaseMask | PointerMotionMask |
457 ButtonPressMask | ButtonReleaseMask |
458 FocusChangeMask;
459 win_attr.override_redirect = TRUE;
461 win_attr.colormap = COLOR_WinColormap;
462 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
463 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
464 win_attr.cursor = CURSORICON_XCursor;
465 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
466 width, height, 0, CopyFromParent,
467 InputOutput, CopyFromParent,
468 CWEventMask | CWOverrideRedirect |
469 CWColormap | CWCursor | CWSaveUnder |
470 CWBackingStore, &win_attr );
471 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
472 EVENT_RegisterWindow( wndPtr->window, hwnd );
475 if ((style & WS_CAPTION) && !(style & WS_CHILD))
477 if (menu) SetMenu(hwnd, menu);
478 else if (classPtr->wc.lpszMenuName)
479 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
481 else wndPtr->wIDmenu = (UINT)menu;
483 GetSystemMenu( hwnd, TRUE ); /* Create a copy of the system menu */
485 /* Send the WM_CREATE message */
487 createStruct.lpCreateParams = (LPSTR)data;
488 createStruct.hInstance = instance;
489 createStruct.hMenu = menu;
490 createStruct.hwndParent = parent;
491 createStruct.cx = width;
492 createStruct.cy = height;
493 createStruct.x = x;
494 createStruct.y = y;
495 createStruct.style = style;
496 createStruct.lpszName = windowName;
497 createStruct.lpszClass = className;
498 createStruct.dwExStyle = 0;
500 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct) );
501 if (!wmcreate)
503 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
504 wmcreate = -1;
506 else
508 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
509 NULL, NULL, NULL, &wndPtr->rectClient );
510 wmcreate = SendMessage(hwnd, WM_CREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct));
513 if (wmcreate == -1)
515 /* Abort window creation */
516 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
517 WIN_DestroyWindow( hwnd );
518 return 0;
521 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
523 /* Show the window, maximizing or minimizing if needed */
525 if (wndPtr->dwStyle & WS_MINIMIZE)
527 wndPtr->dwStyle &= ~WS_MAXIMIZE;
528 WINPOS_FindIconPos( hwnd );
529 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
530 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
531 SWP_FRAMECHANGED |
532 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
534 else if (wndPtr->dwStyle & WS_MAXIMIZE)
536 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
537 SWP_FRAMECHANGED |
538 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
540 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
542 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
543 return hwnd;
547 /***********************************************************************
548 * DestroyWindow (USER.53)
550 BOOL DestroyWindow( HWND hwnd )
552 WND * wndPtr;
553 CLASS * classPtr;
555 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
557 /* Initialisation */
559 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
560 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
561 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
563 /* Hide the window */
565 if (wndPtr->dwStyle & WS_VISIBLE)
566 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
567 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
568 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
569 ReleaseCapture();
570 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
572 /* Recursively destroy owned windows */
574 for (;;)
576 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
577 while (hwndSibling)
579 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
580 if (siblingPtr->hwndOwner == hwnd) break;
581 hwndSibling = siblingPtr->hwndNext;
583 if (hwndSibling) DestroyWindow( hwndSibling );
584 else break;
587 /* Send destroy messages and destroy children */
589 SendMessage( hwnd, WM_DESTROY, 0, 0 );
590 while (wndPtr->hwndChild) /* The child removes itself from the list */
591 DestroyWindow( wndPtr->hwndChild );
592 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
594 /* Destroy the window */
596 WIN_DestroyWindow( hwnd );
597 return TRUE;
601 /***********************************************************************
602 * CloseWindow (USER.43)
604 void CloseWindow(HWND hWnd)
606 WND * wndPtr = WIN_FindWndPtr(hWnd);
607 if (wndPtr->dwStyle & WS_CHILD) return;
608 ShowWindow(hWnd, SW_MINIMIZE);
612 /***********************************************************************
613 * OpenIcon (USER.44)
615 BOOL OpenIcon(HWND hWnd)
617 if (!IsIconic(hWnd)) return FALSE;
618 ShowWindow(hWnd, SW_SHOWNORMAL);
619 return(TRUE);
623 /***********************************************************************
624 * FindWindow (USER.50)
626 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
628 HCLASS hclass;
629 CLASS *classPtr;
630 HWND hwnd;
632 if (ClassMatch)
634 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
635 &classPtr );
636 if (!hclass) return 0;
638 else hclass = 0;
640 hwnd = GetTopWindow( hwndDesktop );
641 while(hwnd)
643 WND *wndPtr = WIN_FindWndPtr( hwnd );
644 if (!hclass || (wndPtr->hClass == hclass))
646 /* Found matching class */
647 if (!TitleMatch) return hwnd;
648 if (wndPtr->hText)
650 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
651 if (!strcmp( textPtr, TitleMatch )) return hwnd;
654 hwnd = wndPtr->hwndNext;
656 return 0;
660 /**********************************************************************
661 * GetDesktopWindow (USER.286)
662 * GetDeskTopHwnd (USER.278)
664 HWND GetDesktopWindow(void)
666 return hwndDesktop;
670 /*******************************************************************
671 * EnableWindow (USER.34)
673 BOOL EnableWindow( HWND hwnd, BOOL enable )
675 WND *wndPtr;
677 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
678 if (enable && (wndPtr->dwStyle & WS_DISABLED))
680 /* Enable window */
681 wndPtr->dwStyle &= ~WS_DISABLED;
682 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
683 return TRUE;
685 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
687 /* Disable window */
688 wndPtr->dwStyle |= WS_DISABLED;
689 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
690 SetFocus( 0 ); /* A disabled window can't have the focus */
691 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
692 ReleaseCapture(); /* A disabled window can't capture the mouse */
693 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
694 return FALSE;
696 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
700 /***********************************************************************
701 * IsWindowEnabled (USER.35)
703 BOOL IsWindowEnabled(HWND hWnd)
705 WND * wndPtr;
707 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
708 return !(wndPtr->dwStyle & WS_DISABLED);
712 /**********************************************************************
713 * GetWindowWord (USER.133)
715 WORD GetWindowWord( HWND hwnd, short offset )
717 WND * wndPtr = WIN_FindWndPtr( hwnd );
718 if (!wndPtr) return 0;
719 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
720 switch(offset)
722 case GWW_ID: return wndPtr->wIDmenu;
723 #ifdef WINELIB32
724 case GWW_HWNDPARENT:
725 case GWW_HINSTANCE:
726 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
727 return 0;
728 #else
729 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
730 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
731 #endif
733 return 0;
737 /**********************************************************************
738 * WIN_GetWindowInstance
740 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
742 WND * wndPtr = WIN_FindWndPtr( hwnd );
743 if (!wndPtr) return (HINSTANCE)0;
744 return wndPtr->hInstance;
748 /**********************************************************************
749 * SetWindowWord (USER.134)
751 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
753 WORD *ptr, retval;
754 WND * wndPtr = WIN_FindWndPtr( hwnd );
755 if (!wndPtr) return 0;
756 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
757 else switch(offset)
759 #ifdef WINELIB32
760 case GWW_ID:
761 case GWW_HINSTANCE:
762 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
763 return 0;
764 #else
765 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
766 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
767 #endif
768 default: return 0;
770 retval = *ptr;
771 *ptr = newval;
772 return retval;
776 /**********************************************************************
777 * GetWindowLong (USER.135)
779 LONG GetWindowLong( HWND hwnd, short offset )
781 WND * wndPtr = WIN_FindWndPtr( hwnd );
782 if (!wndPtr) return 0;
783 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
784 switch(offset)
786 case GWL_STYLE: return wndPtr->dwStyle;
787 case GWL_EXSTYLE: return wndPtr->dwExStyle;
788 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
789 #ifdef WINELIB32
790 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
791 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
792 #endif
794 return 0;
798 /**********************************************************************
799 * SetWindowLong (USER.136)
801 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
803 LONG *ptr, retval;
804 WND * wndPtr = WIN_FindWndPtr( hwnd );
805 if (!wndPtr) return 0;
806 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
807 else switch(offset)
809 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
810 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
811 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
812 default: return 0;
814 retval = *ptr;
815 *ptr = newval;
816 return retval;
820 /*******************************************************************
821 * GetWindowText (USER.36)
823 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
825 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
826 (DWORD)lpString);
829 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
831 int len;
832 HANDLE handle;
834 /* We have to allocate a buffer on the USER heap */
835 /* to be able to pass its address to 16-bit code */
836 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
837 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
838 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
839 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
840 USER_HEAP_FREE( handle );
841 return len;
845 /*******************************************************************
846 * SetWindowText (USER.37)
848 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
850 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
853 void SetWindowText( HWND hwnd, LPSTR lpString )
855 HANDLE handle;
857 /* We have to allocate a buffer on the USER heap */
858 /* to be able to pass its address to 16-bit code */
859 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
860 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
861 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
862 USER_HEAP_FREE( handle );
866 /*******************************************************************
867 * GetWindowTextLength (USER.38)
869 int GetWindowTextLength(HWND hwnd)
871 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
875 /*******************************************************************
876 * IsWindow (USER.47)
878 BOOL IsWindow( HWND hwnd )
880 WND * wndPtr = WIN_FindWndPtr( hwnd );
881 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
885 /*****************************************************************
886 * GetParent (USER.46)
888 HWND GetParent(HWND hwnd)
890 WND *wndPtr = WIN_FindWndPtr(hwnd);
891 if (!wndPtr) return 0;
892 return (wndPtr->dwStyle & WS_CHILD) ?
893 wndPtr->hwndParent : wndPtr->hwndOwner;
897 /*****************************************************************
898 * WIN_GetTopParent
900 * Get the top-level parent for a child window.
902 HWND WIN_GetTopParent( HWND hwnd )
904 while (hwnd)
906 WND *wndPtr = WIN_FindWndPtr( hwnd );
907 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
908 else break;
910 return hwnd;
914 /*****************************************************************
915 * SetParent (USER.233)
917 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
919 HWND temp;
921 WND *wndPtr = WIN_FindWndPtr(hwndChild);
922 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
924 temp = wndPtr->hwndParent;
926 WIN_UnlinkWindow(hwndChild);
927 if (hwndNewParent)
928 wndPtr->hwndParent = hwndNewParent;
929 else
930 wndPtr->hwndParent = GetDesktopWindow();
931 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
933 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
935 return temp;
940 /*******************************************************************
941 * IsChild (USER.48)
943 BOOL IsChild( HWND parent, HWND child )
945 WND * wndPtr = WIN_FindWndPtr( child );
946 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
948 if (wndPtr->hwndParent == parent) return TRUE;
949 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
951 return FALSE;
955 /***********************************************************************
956 * IsWindowVisible (USER.49)
958 BOOL IsWindowVisible( HWND hwnd )
960 WND *wndPtr = WIN_FindWndPtr( hwnd );
961 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
963 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
964 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
966 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
971 /*******************************************************************
972 * GetTopWindow (USER.229)
974 HWND GetTopWindow( HWND hwnd )
976 WND * wndPtr = WIN_FindWndPtr( hwnd );
977 if (wndPtr) return wndPtr->hwndChild;
978 else return 0;
982 /*******************************************************************
983 * GetWindow (USER.262)
985 HWND GetWindow( HWND hwnd, WORD rel )
987 WND * wndPtr = WIN_FindWndPtr( hwnd );
988 if (!wndPtr) return 0;
989 switch(rel)
991 case GW_HWNDFIRST:
992 if (wndPtr->hwndParent)
994 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
995 return parentPtr->hwndChild;
997 else return 0;
999 case GW_HWNDLAST:
1000 if (!wndPtr->hwndParent) return 0; /* Desktop window */
1001 while (wndPtr->hwndNext)
1003 hwnd = wndPtr->hwndNext;
1004 wndPtr = WIN_FindWndPtr( hwnd );
1006 return hwnd;
1008 case GW_HWNDNEXT:
1009 return wndPtr->hwndNext;
1011 case GW_HWNDPREV:
1013 HWND hwndPrev;
1015 if (wndPtr->hwndParent)
1017 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1018 hwndPrev = parentPtr->hwndChild;
1020 else return 0; /* Desktop window */
1021 if (hwndPrev == hwnd) return 0;
1022 while (hwndPrev)
1024 wndPtr = WIN_FindWndPtr( hwndPrev );
1025 if (wndPtr->hwndNext == hwnd) break;
1026 hwndPrev = wndPtr->hwndNext;
1028 return hwndPrev;
1031 case GW_OWNER:
1032 return wndPtr->hwndOwner;
1034 case GW_CHILD:
1035 return wndPtr->hwndChild;
1037 return 0;
1041 /*******************************************************************
1042 * GetNextWindow (USER.230)
1044 HWND GetNextWindow( HWND hwnd, WORD flag )
1046 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1047 return GetWindow( hwnd, flag );
1050 /*******************************************************************
1051 * ShowOwnedPopups (USER.265)
1053 void ShowOwnedPopups( HWND owner, BOOL fShow )
1055 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1056 while (hwnd)
1058 WND *wnd = WIN_FindWndPtr(hwnd);
1059 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1060 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1061 hwnd = wnd->hwndNext;
1066 /*******************************************************************
1067 * GetLastActivePopup (USER.287)
1069 HWND GetLastActivePopup(HWND hwnd)
1071 WND *wndPtr;
1072 wndPtr = WIN_FindWndPtr(hwnd);
1073 if (wndPtr == NULL) return hwnd;
1074 return wndPtr->hwndLastActive;
1078 /*******************************************************************
1079 * EnumWindows (USER.54)
1081 BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
1083 HWND hwnd;
1084 WND *wndPtr;
1085 HWND *list, *pWnd;
1086 int count;
1088 /* We have to build a list of all windows first, to avoid */
1089 /* unpleasant side-effects, for instance if the callback */
1090 /* function changes the Z-order of the windows. */
1092 /* First count the windows */
1094 count = 0;
1095 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1097 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1098 count++;
1100 if (!count) return TRUE;
1102 /* Now build the list of all windows */
1104 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1105 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1107 wndPtr = WIN_FindWndPtr( hwnd );
1108 *pWnd++ = hwnd;
1111 /* Now call the callback function for every window */
1113 for (pWnd = list; count > 0; count--, pWnd++)
1115 /* Make sure that window still exists */
1116 if (!IsWindow(*pWnd)) continue;
1117 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1119 free( list );
1120 return TRUE;
1124 /**********************************************************************
1125 * EnumTaskWindows (USER.225)
1127 BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
1129 HWND hwnd;
1130 WND *wndPtr;
1131 HWND *list, *pWnd;
1132 HANDLE hQueue = GetTaskQueue( hTask );
1133 int count;
1135 /* This function is the same as EnumWindows(), */
1136 /* except for an added check on the window queue. */
1138 /* First count the windows */
1140 count = 0;
1141 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1143 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1144 if (wndPtr->hmemTaskQ == hQueue) count++;
1146 if (!count) return TRUE;
1148 /* Now build the list of all windows */
1150 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1151 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1153 wndPtr = WIN_FindWndPtr( hwnd );
1154 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1157 /* Now call the callback function for every window */
1159 for (pWnd = list; count > 0; count--, pWnd++)
1161 /* Make sure that window still exists */
1162 if (!IsWindow(*pWnd)) continue;
1163 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1165 free( list );
1166 return TRUE;
1170 /*******************************************************************
1171 * WIN_EnumChildWin
1173 * o hwnd is the first child to use, loop until all next windows
1174 * are processed
1176 * o call wdnenumprc
1178 * o call ourselves with the next child window
1181 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1183 WND *wndPtr;
1185 while (hwnd)
1187 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1188 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1189 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1190 hwnd=wndPtr->hwndNext;
1192 return 1;
1195 /*******************************************************************
1196 * EnumChildWindows (USER.55)
1198 * o gets the first child of hwnd
1200 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1202 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1204 WND *wndPtr;
1206 dprintf_enum(stddeb,"EnumChildWindows\n");
1208 if (hwnd == 0) return 0;
1209 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1210 hwnd = wndPtr->hwndChild;
1211 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1215 /*******************************************************************
1216 * AnyPopup [USER.52]
1218 BOOL AnyPopup()
1220 WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
1221 HWND hwnd = wndPtr->hwndChild;
1223 for( ; hwnd ; hwnd = wndPtr->hwndNext )
1225 wndPtr = WIN_FindWndPtr(hwnd);
1226 if(wndPtr->hwndOwner)
1227 if(wndPtr->dwStyle & WS_VISIBLE)
1228 return TRUE;
1230 return FALSE;
1233 /*******************************************************************
1234 * FlashWindow [USER.105]
1236 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1238 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1239 return FALSE;
1243 /*******************************************************************
1244 * SetSysModalWindow [USER.188]
1246 HWND SetSysModalWindow(HWND hWnd)
1248 HWND hWndOldModal = hwndSysModal;
1249 hwndSysModal = hWnd;
1250 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1251 return hWndOldModal;
1255 /*******************************************************************
1256 * GetSysModalWindow [USER.189]
1258 HWND GetSysModalWindow(void)
1260 return hwndSysModal;
1263 /*******************************************************************
1264 * DRAG_QueryUpdate
1266 * recursively find a child that contains spDragInfo->pt point
1267 * and send WM_QUERYDROPOBJECT
1269 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1271 HWND hWnd;
1272 BOOL wParam,bResult = 0;
1273 POINT pt;
1274 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1275 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1276 RECT tempRect; /* this sucks */
1278 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1280 pt = ptrDragInfo->pt;
1282 GetWindowRect(hQueryWnd,&tempRect);
1284 if( !PtInRect(&tempRect,pt) ||
1285 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1286 return 0;
1288 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1290 tempRect = ptrQueryWnd->rectClient;
1291 if(ptrQueryWnd->dwStyle & WS_CHILD)
1292 MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
1294 if( PtInRect(&tempRect,pt) )
1296 wParam = 0;
1297 ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
1299 for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
1300 if( ptrWnd->dwStyle & WS_VISIBLE )
1302 GetWindowRect(hWnd,&tempRect);
1304 if( PtInRect(&tempRect,pt) )
1305 break;
1308 if(ptrWnd)
1309 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
1310 (int)ptrWnd->rectWindow.left,(int)ptrWnd->rectWindow.top,
1311 (int)ptrWnd->rectWindow.right,(int)ptrWnd->rectWindow.bottom);
1312 else
1313 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
1315 if(ptrWnd)
1316 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1317 bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
1319 if(bResult) return bResult;
1321 else wParam = 1;
1323 else wParam = 1;
1325 ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
1327 ptrDragInfo->hScope = hQueryWnd;
1329 bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
1330 (WPARAM)wParam ,(LPARAM) spDragInfo );
1331 if( !bResult )
1332 ptrDragInfo->pt = pt;
1334 return bResult;
1337 /*******************************************************************
1338 * DragDetect ( USER.465 )
1341 BOOL DragDetect(HWND hWnd, POINT pt)
1343 MSG msg;
1344 RECT rect;
1346 rect.left = pt.x - wDragWidth;
1347 rect.right = pt.x + wDragWidth;
1349 rect.top = pt.y - wDragHeight;
1350 rect.bottom = pt.y + wDragHeight;
1352 SetCapture(hWnd);
1354 while(1)
1356 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1358 if( msg.message == WM_LBUTTONUP )
1360 ReleaseCapture();
1361 return 0;
1363 if( msg.message == WM_MOUSEMOVE )
1365 POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
1366 if( !PtInRect( &rect, pt ) )
1368 ReleaseCapture();
1369 return 1;
1373 WaitMessage();
1376 return 0;
1379 /******************************************************************************
1380 * DragObject ( USER.464 )
1383 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1384 WORD szList , HCURSOR hCursor)
1386 MSG msg;
1387 LPDRAGINFO lpDragInfo;
1388 SEGPTR spDragInfo;
1389 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1390 HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1391 WND *wndPtr = WIN_FindWndPtr(hWnd);
1392 DWORD dwRet = 0;
1393 short dragDone = 0;
1394 HCURSOR hCurrentCursor = 0;
1395 HWND hCurrentWnd = 0;
1396 WORD btemp;
1398 fprintf(stdnimp,"DragObject: experimental\n");
1400 lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
1401 spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
1403 if( !lpDragInfo || !spDragInfo ) return 0L;
1405 hBummer = LoadCursor(0,IDC_BUMMER);
1407 if( !hBummer || !wndPtr )
1409 GlobalFree(hDragInfo);
1410 return 0L;
1413 if(hCursor)
1415 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1417 GlobalFree(hDragInfo);
1418 return 0L;
1421 if( hDragCursor == hCursor ) hDragCursor = 0;
1422 else hCursor = hDragCursor;
1424 hOldCursor = SetCursor(hDragCursor);
1427 lpDragInfo->hWnd = hWnd;
1428 lpDragInfo->hScope = 0;
1429 lpDragInfo->wFlags = wObj;
1430 lpDragInfo->hList = szList; /* near pointer! */
1431 lpDragInfo->hOfStruct = hOfStruct;
1432 lpDragInfo->l = 0L;
1434 SetCapture(hWnd);
1435 ShowCursor(1);
1437 while( !dragDone )
1439 WaitMessage();
1441 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1442 continue;
1444 *(lpDragInfo+1) = *lpDragInfo;
1446 lpDragInfo->pt = msg.pt;
1448 /* update DRAGINFO struct */
1449 dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
1451 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1452 hCurrentCursor = hCursor;
1453 else
1455 hCurrentCursor = hBummer;
1456 lpDragInfo->hScope = 0;
1458 if( hCurrentCursor )
1459 SetCursor(hCurrentCursor);
1461 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1463 /* send WM_DRAGLOOP */
1464 SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1465 (LPARAM) spDragInfo );
1466 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1467 if( hCurrentWnd != lpDragInfo->hScope )
1469 if( hCurrentWnd )
1470 SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
1471 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1472 HIWORD(spDragInfo)) );
1473 hCurrentWnd = lpDragInfo->hScope;
1474 if( hCurrentWnd )
1475 SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1477 else
1478 if( hCurrentWnd )
1479 SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1482 /* check if we're done */
1483 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1484 dragDone = TRUE;
1487 ReleaseCapture();
1488 ShowCursor(0);
1490 if( hCursor )
1492 SetCursor(hOldCursor);
1493 if( hDragCursor )
1494 DestroyCursor(hDragCursor);
1497 if( hCurrentCursor != hBummer )
1498 dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
1499 (WPARAM)hWnd, (LPARAM)spDragInfo );
1500 GlobalFree(hDragInfo);
1502 return dwRet;