Release 960225
[wine/multimedia.git] / windows / win.c
blob81133a403465cb168766862d383bd485a3d426a4
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 && ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
448 (exStyle & WS_EX_DLGMODALFRAME)))
450 win_attr.event_mask = ExposureMask | KeyPressMask |
451 KeyReleaseMask | PointerMotionMask |
452 ButtonPressMask | ButtonReleaseMask |
453 FocusChangeMask | StructureNotifyMask;
454 win_attr.override_redirect = FALSE;
455 wndPtr->flags |= WIN_MANAGED;
457 else
459 win_attr.event_mask = ExposureMask | KeyPressMask |
460 KeyReleaseMask | PointerMotionMask |
461 ButtonPressMask | ButtonReleaseMask |
462 FocusChangeMask;
463 win_attr.override_redirect = TRUE;
465 win_attr.colormap = COLOR_WinColormap;
466 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
467 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
468 win_attr.cursor = CURSORICON_XCursor;
469 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
470 width, height, 0, CopyFromParent,
471 InputOutput, CopyFromParent,
472 CWEventMask | CWOverrideRedirect |
473 CWColormap | CWCursor | CWSaveUnder |
474 CWBackingStore, &win_attr );
475 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
476 EVENT_RegisterWindow( wndPtr->window, hwnd );
479 if ((style & WS_CAPTION) && !(style & WS_CHILD))
481 if (menu) SetMenu(hwnd, menu);
482 else if (classPtr->wc.lpszMenuName)
483 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
485 else wndPtr->wIDmenu = (UINT)menu;
487 GetSystemMenu( hwnd, TRUE ); /* Create a copy of the system menu */
489 /* Send the WM_CREATE message */
491 createStruct.lpCreateParams = (LPSTR)data;
492 createStruct.hInstance = instance;
493 createStruct.hMenu = menu;
494 createStruct.hwndParent = parent;
495 createStruct.cx = width;
496 createStruct.cy = height;
497 createStruct.x = x;
498 createStruct.y = y;
499 createStruct.style = style;
500 createStruct.lpszName = windowName;
501 createStruct.lpszClass = className;
502 createStruct.dwExStyle = 0;
504 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct) );
505 if (!wmcreate)
507 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
508 wmcreate = -1;
510 else
512 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
513 NULL, NULL, NULL, &wndPtr->rectClient );
514 wmcreate = SendMessage(hwnd, WM_CREATE, 0, (LPARAM)MAKE_SEGPTR(&createStruct));
517 if (wmcreate == -1)
519 /* Abort window creation */
520 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
521 WIN_DestroyWindow( hwnd );
522 return 0;
525 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
527 /* Show the window, maximizing or minimizing if needed */
529 if (wndPtr->dwStyle & WS_MINIMIZE)
531 wndPtr->dwStyle &= ~WS_MAXIMIZE;
532 WINPOS_FindIconPos( hwnd );
533 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
534 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
535 SWP_FRAMECHANGED |
536 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
538 else if (wndPtr->dwStyle & WS_MAXIMIZE)
540 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
541 SWP_FRAMECHANGED |
542 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
544 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
546 dprintf_win(stddeb, "CreateWindowEx: return "NPFMT" \n", hwnd);
547 return hwnd;
551 /***********************************************************************
552 * DestroyWindow (USER.53)
554 BOOL DestroyWindow( HWND hwnd )
556 WND * wndPtr;
557 CLASS * classPtr;
559 dprintf_win(stddeb, "DestroyWindow ("NPFMT")\n", hwnd);
561 /* Initialisation */
563 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
564 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
565 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
567 /* Hide the window */
569 if (wndPtr->dwStyle & WS_VISIBLE)
570 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
571 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
572 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
573 ReleaseCapture();
574 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
576 /* Recursively destroy owned windows */
578 for (;;)
580 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
581 while (hwndSibling)
583 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
584 if (siblingPtr->hwndOwner == hwnd) break;
585 hwndSibling = siblingPtr->hwndNext;
587 if (hwndSibling) DestroyWindow( hwndSibling );
588 else break;
591 /* Send destroy messages and destroy children */
593 SendMessage( hwnd, WM_DESTROY, 0, 0 );
594 while (wndPtr->hwndChild) /* The child removes itself from the list */
595 DestroyWindow( wndPtr->hwndChild );
596 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
598 /* Destroy the window */
600 WIN_DestroyWindow( hwnd );
601 return TRUE;
605 /***********************************************************************
606 * CloseWindow (USER.43)
608 BOOL CloseWindow(HWND hWnd)
610 WND * wndPtr = WIN_FindWndPtr(hWnd);
611 if (wndPtr->dwStyle & WS_CHILD) return TRUE;
612 ShowWindow(hWnd, SW_MINIMIZE);
613 return TRUE;
617 /***********************************************************************
618 * OpenIcon (USER.44)
620 BOOL OpenIcon(HWND hWnd)
622 if (!IsIconic(hWnd)) return FALSE;
623 ShowWindow(hWnd, SW_SHOWNORMAL);
624 return(TRUE);
628 /***********************************************************************
629 * FindWindow (USER.50)
631 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
633 HCLASS hclass;
634 CLASS *classPtr;
635 HWND hwnd;
637 if (ClassMatch)
639 hclass = CLASS_FindClassByName( ClassMatch, (HINSTANCE)0xffff,
640 &classPtr );
641 if (!hclass) return 0;
643 else hclass = 0;
645 hwnd = GetTopWindow( hwndDesktop );
646 while(hwnd)
648 WND *wndPtr = WIN_FindWndPtr( hwnd );
649 if (!hclass || (wndPtr->hClass == hclass))
651 /* Found matching class */
652 if (!TitleMatch) return hwnd;
653 if (wndPtr->hText)
655 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
656 if (!strcmp( textPtr, TitleMatch )) return hwnd;
659 hwnd = wndPtr->hwndNext;
661 return 0;
665 /**********************************************************************
666 * GetDesktopWindow (USER.286)
667 * GetDeskTopHwnd (USER.278)
669 HWND GetDesktopWindow(void)
671 return hwndDesktop;
675 /*******************************************************************
676 * EnableWindow (USER.34)
678 BOOL EnableWindow( HWND hwnd, BOOL enable )
680 WND *wndPtr;
682 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
683 if (enable && (wndPtr->dwStyle & WS_DISABLED))
685 /* Enable window */
686 wndPtr->dwStyle &= ~WS_DISABLED;
687 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
688 return TRUE;
690 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
692 /* Disable window */
693 wndPtr->dwStyle |= WS_DISABLED;
694 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
695 SetFocus( 0 ); /* A disabled window can't have the focus */
696 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
697 ReleaseCapture(); /* A disabled window can't capture the mouse */
698 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
699 return FALSE;
701 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
705 /***********************************************************************
706 * IsWindowEnabled (USER.35)
708 BOOL IsWindowEnabled(HWND hWnd)
710 WND * wndPtr;
712 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
713 return !(wndPtr->dwStyle & WS_DISABLED);
717 /**********************************************************************
718 * GetWindowWord (USER.133)
720 WORD GetWindowWord( HWND hwnd, short offset )
722 WND * wndPtr = WIN_FindWndPtr( hwnd );
723 if (!wndPtr) return 0;
724 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
725 switch(offset)
727 case GWW_ID: return wndPtr->wIDmenu;
728 #ifdef WINELIB32
729 case GWW_HWNDPARENT:
730 case GWW_HINSTANCE:
731 fprintf(stderr,"GetWindowWord called with offset %d.\n",offset);
732 return 0;
733 #else
734 case GWW_HWNDPARENT: return (WORD)wndPtr->hwndParent;
735 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
736 #endif
738 return 0;
742 /**********************************************************************
743 * WIN_GetWindowInstance
745 HINSTANCE WIN_GetWindowInstance(HWND hwnd)
747 WND * wndPtr = WIN_FindWndPtr( hwnd );
748 if (!wndPtr) return (HINSTANCE)0;
749 return wndPtr->hInstance;
753 /**********************************************************************
754 * SetWindowWord (USER.134)
756 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
758 WORD *ptr, retval;
759 WND * wndPtr = WIN_FindWndPtr( hwnd );
760 if (!wndPtr) return 0;
761 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
762 else switch(offset)
764 #ifdef WINELIB32
765 case GWW_ID:
766 case GWW_HINSTANCE:
767 fprintf(stderr,"SetWindowWord called with offset %d.\n",offset);
768 return 0;
769 #else
770 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
771 case GWW_HINSTANCE: ptr = (WORD*)&wndPtr->hInstance; break;
772 #endif
773 default: return 0;
775 retval = *ptr;
776 *ptr = newval;
777 return retval;
781 /**********************************************************************
782 * GetWindowLong (USER.135)
784 LONG GetWindowLong( HWND hwnd, short offset )
786 WND * wndPtr = WIN_FindWndPtr( hwnd );
787 if (!wndPtr) return 0;
788 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
789 switch(offset)
791 case GWL_STYLE: return wndPtr->dwStyle;
792 case GWL_EXSTYLE: return wndPtr->dwExStyle;
793 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
794 #ifdef WINELIB32
795 case GWW_HWNDPARENT: return (LONG)wndPtr->hwndParent;
796 case GWW_HINSTANCE: return (LONG)wndPtr->hInstance;
797 #endif
799 return 0;
803 /**********************************************************************
804 * SetWindowLong (USER.136)
806 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
808 LONG *ptr, retval;
809 WND * wndPtr = WIN_FindWndPtr( hwnd );
810 if (!wndPtr) return 0;
811 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
812 else switch(offset)
814 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
815 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
816 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
817 default: return 0;
819 retval = *ptr;
820 *ptr = newval;
821 return retval;
825 /*******************************************************************
826 * GetWindowText (USER.36)
828 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
830 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
831 (DWORD)lpString);
834 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
836 int len;
837 HANDLE handle;
839 /* We have to allocate a buffer on the USER heap */
840 /* to be able to pass its address to 16-bit code */
841 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
842 len = (int)SendMessage( hwnd, WM_GETTEXT, (WPARAM)nMaxCount,
843 (LPARAM)USER_HEAP_SEG_ADDR(handle) );
844 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
845 USER_HEAP_FREE( handle );
846 return len;
850 /*******************************************************************
851 * SetWindowText (USER.37)
853 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
855 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
858 void SetWindowText( HWND hwnd, LPCSTR lpString )
860 HANDLE handle;
862 /* We have to allocate a buffer on the USER heap */
863 /* to be able to pass its address to 16-bit code */
864 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
865 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
866 SendMessage( hwnd, WM_SETTEXT, 0, (LPARAM)USER_HEAP_SEG_ADDR(handle) );
867 USER_HEAP_FREE( handle );
871 /*******************************************************************
872 * GetWindowTextLength (USER.38)
874 int GetWindowTextLength(HWND hwnd)
876 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
880 /*******************************************************************
881 * IsWindow (USER.47)
883 BOOL IsWindow( HWND hwnd )
885 WND * wndPtr = WIN_FindWndPtr( hwnd );
886 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
890 /*****************************************************************
891 * GetParent (USER.46)
893 HWND GetParent(HWND hwnd)
895 WND *wndPtr = WIN_FindWndPtr(hwnd);
896 if (!wndPtr) return 0;
897 return (wndPtr->dwStyle & WS_CHILD) ?
898 wndPtr->hwndParent : wndPtr->hwndOwner;
902 /*****************************************************************
903 * WIN_GetTopParent
905 * Get the top-level parent for a child window.
907 HWND WIN_GetTopParent( HWND hwnd )
909 while (hwnd)
911 WND *wndPtr = WIN_FindWndPtr( hwnd );
912 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
913 else break;
915 return hwnd;
919 /*****************************************************************
920 * SetParent (USER.233)
922 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
924 HWND temp;
926 WND *wndPtr = WIN_FindWndPtr(hwndChild);
927 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
929 temp = wndPtr->hwndParent;
931 WIN_UnlinkWindow(hwndChild);
932 if (hwndNewParent)
933 wndPtr->hwndParent = hwndNewParent;
934 else
935 wndPtr->hwndParent = GetDesktopWindow();
936 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
938 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
940 return temp;
945 /*******************************************************************
946 * IsChild (USER.48)
948 BOOL IsChild( HWND parent, HWND child )
950 WND * wndPtr = WIN_FindWndPtr( child );
951 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
953 if (wndPtr->hwndParent == parent) return TRUE;
954 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
956 return FALSE;
960 /***********************************************************************
961 * IsWindowVisible (USER.49)
963 BOOL IsWindowVisible( HWND hwnd )
965 WND *wndPtr = WIN_FindWndPtr( hwnd );
966 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
968 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
969 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
971 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
976 /*******************************************************************
977 * GetTopWindow (USER.229)
979 HWND GetTopWindow( HWND hwnd )
981 WND * wndPtr = WIN_FindWndPtr( hwnd );
982 if (wndPtr) return wndPtr->hwndChild;
983 else return 0;
987 /*******************************************************************
988 * GetWindow (USER.262)
990 HWND GetWindow( HWND hwnd, WORD rel )
992 WND * wndPtr = WIN_FindWndPtr( hwnd );
993 if (!wndPtr) return 0;
994 switch(rel)
996 case GW_HWNDFIRST:
997 if (wndPtr->hwndParent)
999 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1000 return parentPtr->hwndChild;
1002 else return 0;
1004 case GW_HWNDLAST:
1005 if (!wndPtr->hwndParent) return 0; /* Desktop window */
1006 while (wndPtr->hwndNext)
1008 hwnd = wndPtr->hwndNext;
1009 wndPtr = WIN_FindWndPtr( hwnd );
1011 return hwnd;
1013 case GW_HWNDNEXT:
1014 return wndPtr->hwndNext;
1016 case GW_HWNDPREV:
1018 HWND hwndPrev;
1020 if (wndPtr->hwndParent)
1022 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
1023 hwndPrev = parentPtr->hwndChild;
1025 else return 0; /* Desktop window */
1026 if (hwndPrev == hwnd) return 0;
1027 while (hwndPrev)
1029 wndPtr = WIN_FindWndPtr( hwndPrev );
1030 if (wndPtr->hwndNext == hwnd) break;
1031 hwndPrev = wndPtr->hwndNext;
1033 return hwndPrev;
1036 case GW_OWNER:
1037 return wndPtr->hwndOwner;
1039 case GW_CHILD:
1040 return wndPtr->hwndChild;
1042 return 0;
1046 /*******************************************************************
1047 * GetNextWindow (USER.230)
1049 HWND GetNextWindow( HWND hwnd, WORD flag )
1051 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1052 return GetWindow( hwnd, flag );
1055 /*******************************************************************
1056 * ShowOwnedPopups (USER.265)
1058 void ShowOwnedPopups( HWND owner, BOOL fShow )
1060 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1061 while (hwnd)
1063 WND *wnd = WIN_FindWndPtr(hwnd);
1064 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1065 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1066 hwnd = wnd->hwndNext;
1071 /*******************************************************************
1072 * GetLastActivePopup (USER.287)
1074 HWND GetLastActivePopup(HWND hwnd)
1076 WND *wndPtr;
1077 wndPtr = WIN_FindWndPtr(hwnd);
1078 if (wndPtr == NULL) return hwnd;
1079 return wndPtr->hwndLastActive;
1083 /*******************************************************************
1084 * EnumWindows (USER.54)
1086 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
1088 HWND hwnd;
1089 WND *wndPtr;
1090 HWND *list, *pWnd;
1091 int count;
1093 /* We have to build a list of all windows first, to avoid */
1094 /* unpleasant side-effects, for instance if the callback */
1095 /* function changes the Z-order of the windows. */
1097 /* First count the windows */
1099 count = 0;
1100 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1102 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1103 count++;
1105 if (!count) return TRUE;
1107 /* Now build the list of all windows */
1109 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1110 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1112 wndPtr = WIN_FindWndPtr( hwnd );
1113 *pWnd++ = hwnd;
1116 /* Now call the callback function for every window */
1118 for (pWnd = list; count > 0; count--, pWnd++)
1120 /* Make sure that window still exists */
1121 if (!IsWindow(*pWnd)) continue;
1122 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1124 free( list );
1125 return TRUE;
1129 /**********************************************************************
1130 * EnumTaskWindows (USER.225)
1132 BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
1134 HWND hwnd;
1135 WND *wndPtr;
1136 HWND *list, *pWnd;
1137 HANDLE hQueue = GetTaskQueue( hTask );
1138 int count;
1140 /* This function is the same as EnumWindows(), */
1141 /* except for an added check on the window queue. */
1143 /* First count the windows */
1145 count = 0;
1146 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1148 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1149 if (wndPtr->hmemTaskQ == hQueue) count++;
1151 if (!count) return TRUE;
1153 /* Now build the list of all windows */
1155 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1156 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1158 wndPtr = WIN_FindWndPtr( hwnd );
1159 if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
1162 /* Now call the callback function for every window */
1164 for (pWnd = list; count > 0; count--, pWnd++)
1166 /* Make sure that window still exists */
1167 if (!IsWindow(*pWnd)) continue;
1168 if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1170 free( list );
1171 return TRUE;
1175 /*******************************************************************
1176 * WIN_EnumChildWin
1178 * o hwnd is the first child to use, loop until all next windows
1179 * are processed
1181 * o call wdnenumprc
1183 * o call ourselves with the next child window
1186 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1188 WND *wndPtr;
1190 while (hwnd)
1192 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1193 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1194 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1195 hwnd=wndPtr->hwndNext;
1197 return 1;
1200 /*******************************************************************
1201 * EnumChildWindows (USER.55)
1203 * o gets the first child of hwnd
1205 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1207 BOOL EnumChildWindows(HWND hwnd, WNDENUMPROC wndenumprc, LPARAM lParam)
1209 WND *wndPtr;
1211 dprintf_enum(stddeb,"EnumChildWindows\n");
1213 if (hwnd == 0) return 0;
1214 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1215 hwnd = wndPtr->hwndChild;
1216 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1220 /*******************************************************************
1221 * AnyPopup [USER.52]
1223 BOOL AnyPopup()
1225 WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
1226 HWND hwnd = wndPtr->hwndChild;
1228 for( ; hwnd ; hwnd = wndPtr->hwndNext )
1230 wndPtr = WIN_FindWndPtr(hwnd);
1231 if(wndPtr->hwndOwner)
1232 if(wndPtr->dwStyle & WS_VISIBLE)
1233 return TRUE;
1235 return FALSE;
1238 /*******************************************************************
1239 * FlashWindow [USER.105]
1241 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1243 WND *wndPtr = WIN_FindWndPtr(hWnd);
1245 dprintf_win(stddeb,"FlashWindow: "NPFMT"\n", hWnd);
1247 if (!wndPtr) return FALSE;
1249 if (wndPtr->dwStyle & WS_MINIMIZE)
1251 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1253 HDC hDC = GetDC(hWnd);
1255 if (!SendMessage( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1256 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1258 ReleaseDC( hWnd, hDC );
1259 wndPtr->flags |= WIN_NCACTIVATED;
1261 else
1263 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1264 RDW_UPDATENOW | RDW_FRAME );
1265 wndPtr->flags &= ~WIN_NCACTIVATED;
1267 return TRUE;
1269 else
1271 WPARAM wparam;
1272 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1273 else wparam = (hWnd == GetActiveWindow());
1275 SendMessage( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1276 return wparam;
1281 /*******************************************************************
1282 * SetSysModalWindow [USER.188]
1284 HWND SetSysModalWindow(HWND hWnd)
1286 HWND hWndOldModal = hwndSysModal;
1287 hwndSysModal = hWnd;
1288 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow("NPFMT") !\n", hWnd);
1289 return hWndOldModal;
1293 /*******************************************************************
1294 * GetSysModalWindow [USER.189]
1296 HWND GetSysModalWindow(void)
1298 return hwndSysModal;
1301 /*******************************************************************
1302 * DRAG_QueryUpdate
1304 * recursively find a child that contains spDragInfo->pt point
1305 * and send WM_QUERYDROPOBJECT
1307 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1309 HWND hWnd;
1310 BOOL wParam,bResult = 0;
1311 POINT pt;
1312 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1313 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1314 RECT tempRect; /* this sucks */
1316 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1318 pt = ptrDragInfo->pt;
1320 GetWindowRect(hQueryWnd,&tempRect);
1322 if( !PtInRect(&tempRect,pt) ||
1323 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1324 return 0;
1326 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1328 tempRect = ptrQueryWnd->rectClient;
1329 if(ptrQueryWnd->dwStyle & WS_CHILD)
1330 MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
1332 if( PtInRect(&tempRect,pt) )
1334 wParam = 0;
1335 ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
1337 for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
1338 if( ptrWnd->dwStyle & WS_VISIBLE )
1340 GetWindowRect(hWnd,&tempRect);
1342 if( PtInRect(&tempRect,pt) )
1343 break;
1346 if(ptrWnd)
1347 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
1348 (int)ptrWnd->rectWindow.left,(int)ptrWnd->rectWindow.top,
1349 (int)ptrWnd->rectWindow.right,(int)ptrWnd->rectWindow.bottom);
1350 else
1351 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
1353 if(ptrWnd)
1354 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1355 bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
1357 if(bResult) return bResult;
1359 else wParam = 1;
1361 else wParam = 1;
1363 ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
1365 ptrDragInfo->hScope = hQueryWnd;
1367 bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
1368 (WPARAM)wParam ,(LPARAM) spDragInfo );
1369 if( !bResult )
1370 ptrDragInfo->pt = pt;
1372 return bResult;
1375 /*******************************************************************
1376 * DragDetect ( USER.465 )
1379 BOOL DragDetect(HWND hWnd, POINT pt)
1381 MSG msg;
1382 RECT rect;
1384 rect.left = pt.x - wDragWidth;
1385 rect.right = pt.x + wDragWidth;
1387 rect.top = pt.y - wDragHeight;
1388 rect.bottom = pt.y + wDragHeight;
1390 SetCapture(hWnd);
1392 while(1)
1394 while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1396 if( msg.message == WM_LBUTTONUP )
1398 ReleaseCapture();
1399 return 0;
1401 if( msg.message == WM_MOUSEMOVE )
1403 POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
1404 if( !PtInRect( &rect, pt ) )
1406 ReleaseCapture();
1407 return 1;
1411 WaitMessage();
1414 return 0;
1417 /******************************************************************************
1418 * DragObject ( USER.464 )
1421 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1422 WORD szList , HCURSOR hCursor)
1424 MSG msg;
1425 LPDRAGINFO lpDragInfo;
1426 SEGPTR spDragInfo;
1427 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1428 HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1429 WND *wndPtr = WIN_FindWndPtr(hWnd);
1430 DWORD dwRet = 0;
1431 short dragDone = 0;
1432 HCURSOR hCurrentCursor = 0;
1433 HWND hCurrentWnd = 0;
1434 WORD btemp;
1436 lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
1437 spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
1439 if( !lpDragInfo || !spDragInfo ) return 0L;
1441 hBummer = LoadCursor(0,IDC_BUMMER);
1443 if( !hBummer || !wndPtr )
1445 GlobalFree(hDragInfo);
1446 return 0L;
1449 if(hCursor)
1451 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
1453 GlobalFree(hDragInfo);
1454 return 0L;
1457 if( hDragCursor == hCursor ) hDragCursor = 0;
1458 else hCursor = hDragCursor;
1460 hOldCursor = SetCursor(hDragCursor);
1463 lpDragInfo->hWnd = hWnd;
1464 lpDragInfo->hScope = 0;
1465 lpDragInfo->wFlags = wObj;
1466 lpDragInfo->hList = szList; /* near pointer! */
1467 lpDragInfo->hOfStruct = hOfStruct;
1468 lpDragInfo->l = 0L;
1470 SetCapture(hWnd);
1471 ShowCursor(1);
1473 while( !dragDone )
1475 WaitMessage();
1477 if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
1478 continue;
1480 *(lpDragInfo+1) = *lpDragInfo;
1482 lpDragInfo->pt = msg.pt;
1484 /* update DRAGINFO struct */
1485 dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
1487 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
1488 hCurrentCursor = hCursor;
1489 else
1491 hCurrentCursor = hBummer;
1492 lpDragInfo->hScope = 0;
1494 if( hCurrentCursor )
1495 SetCursor(hCurrentCursor);
1497 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
1499 /* send WM_DRAGLOOP */
1500 SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
1501 (LPARAM) spDragInfo );
1502 /* send WM_DRAGSELECT or WM_DRAGMOVE */
1503 if( hCurrentWnd != lpDragInfo->hScope )
1505 if( hCurrentWnd )
1506 SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
1507 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
1508 HIWORD(spDragInfo)) );
1509 hCurrentWnd = lpDragInfo->hScope;
1510 if( hCurrentWnd )
1511 SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1513 else
1514 if( hCurrentWnd )
1515 SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1518 /* check if we're done */
1519 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
1520 dragDone = TRUE;
1523 ReleaseCapture();
1524 ShowCursor(0);
1526 if( hCursor )
1528 SetCursor(hOldCursor);
1529 if( hDragCursor )
1530 DestroyCursor(hDragCursor);
1533 if( hCurrentCursor != hBummer )
1534 dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
1535 (WPARAM)hWnd, (LPARAM)spDragInfo );
1536 GlobalFree(hDragInfo);
1538 return dwRet;