Release 960913
[wine/multimedia.git] / windows / win.c
blob80debdfacd8c49863f7c71c531c97f39990887a5
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <X11/Xatom.h>
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "heap.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "string32.h"
26 #include "queue.h"
27 #include "winpos.h"
28 #include "color.h"
29 #include "shm_main_blk.h"
30 #include "dde_proc.h"
31 #include "clipboard.h"
32 #include "winproc.h"
33 #include "stddebug.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
36 #include "debug.h"
38 /* Desktop window */
39 static WND *pWndDesktop = NULL;
41 static HWND hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16);
48 /***********************************************************************
49 * WIN_FindWndPtr
51 * Return a pointer to the WND structure corresponding to a HWND.
53 WND * WIN_FindWndPtr( HWND32 hwnd )
55 WND * ptr;
57 if (!hwnd || HIWORD(hwnd)) return NULL;
58 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
59 if (ptr->dwMagic != WND_MAGIC) return NULL;
60 if (ptr->hwndSelf != hwnd)
62 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
63 hwnd, ptr->hwndSelf );
64 return NULL;
66 return ptr;
70 /***********************************************************************
71 * WIN_DumpWindow
73 * Dump the content of a window structure to stderr.
75 void WIN_DumpWindow( HWND32 hwnd )
77 WND *ptr;
78 char className[80];
79 int i;
81 if (!(ptr = WIN_FindWndPtr( hwnd )))
83 fprintf( stderr, "%04x is not a window handle\n", hwnd );
84 return;
87 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
88 strcpy( className, "#NULL#" );
90 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
91 fprintf( stderr,
92 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
93 "inst=%04x taskQ=%04x updRgn=%04x active=%04x hdce=%04x idmenu=%04x\n"
94 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
95 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
96 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
97 ptr->next, ptr->child, ptr->parent, ptr->owner,
98 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
99 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
100 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
101 ptr->text ? ptr->text : "",
102 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
103 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
104 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
105 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
106 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
108 if (ptr->class->cbWndExtra)
110 fprintf( stderr, "extra bytes:" );
111 for (i = 0; i < ptr->class->cbWndExtra; i++)
112 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
113 fprintf( stderr, "\n" );
115 fprintf( stderr, "\n" );
119 /***********************************************************************
120 * WIN_WalkWindows
122 * Walk the windows tree and print each window on stderr.
124 void WIN_WalkWindows( HWND32 hwnd, int indent )
126 WND *ptr;
127 char className[80];
129 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
130 if (!ptr)
132 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
133 return;
136 if (!indent) /* first time around */
137 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
138 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
140 while (ptr)
142 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
144 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
146 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
147 (DWORD)ptr, ptr->hmemTaskQ, className,
148 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
150 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
151 ptr = ptr->next;
156 /***********************************************************************
157 * WIN_GetXWindow
159 * Return the X window associated to a window.
161 Window WIN_GetXWindow( HWND32 hwnd )
163 WND *wndPtr = WIN_FindWndPtr( hwnd );
164 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
165 return wndPtr ? wndPtr->window : 0;
169 /***********************************************************************
170 * WIN_UnlinkWindow
172 * Remove a window from the siblings linked list.
174 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
176 WND *wndPtr, **ppWnd;
178 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
179 ppWnd = &wndPtr->parent->child;
180 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
181 *ppWnd = wndPtr->next;
182 return TRUE;
186 /***********************************************************************
187 * WIN_LinkWindow
189 * Insert a window into the siblings linked list.
190 * The window is inserted after the specified window, which can also
191 * be specified as HWND_TOP or HWND_BOTTOM.
193 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
195 WND *wndPtr, **ppWnd;
197 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
199 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
201 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
202 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
203 while (*ppWnd) ppWnd = &(*ppWnd)->next;
205 else /* Normal case */
207 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
208 if (!afterPtr) return FALSE;
209 ppWnd = &afterPtr->next;
211 wndPtr->next = *ppWnd;
212 *ppWnd = wndPtr;
213 return TRUE;
217 /***********************************************************************
218 * WIN_FindWinToRepaint
220 * Find a window that needs repaint.
222 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
224 HWND hwndRet;
225 WND *pWnd = pWndDesktop;
227 /* Note: the desktop window never gets WM_PAINT messages
228 * The real reason why is because Windows DesktopWndProc
229 * does ValidateRgn inside WM_ERASEBKGND handler.
232 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
234 for ( ; pWnd ; pWnd = pWnd->next )
236 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
238 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
239 pWnd->hwndSelf );
240 continue;
242 if ((pWnd->hmemTaskQ == hQueue) &&
243 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
245 if (pWnd->child )
246 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
247 return hwndRet;
250 if (!pWnd) return 0;
252 hwndRet = pWnd->hwndSelf;
254 /* look among siblings if we got a transparent window */
255 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
256 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
258 pWnd = pWnd->next;
260 if (pWnd) hwndRet = pWnd->hwndSelf;
261 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
262 return hwndRet;
266 /***********************************************************************
267 * WIN_SendParentNotify
269 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
270 * the window has the WS_EX_NOPARENTNOTIFY style.
272 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
274 LPPOINT16 lppt = (LPPOINT16)&lValue;
275 WND *wndPtr = WIN_FindWndPtr( hwnd );
276 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
278 /* if lValue contains cursor coordinates they have to be
279 * mapped to the client area of parent window */
281 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
283 while (wndPtr)
285 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
286 !(wndPtr->dwStyle & WS_CHILD)) break;
288 if (bMouse)
290 lppt->x += wndPtr->rectClient.left;
291 lppt->y += wndPtr->rectClient.top;
294 wndPtr = wndPtr->parent;
295 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
296 MAKEWPARAM( event, idChild ), lValue );
301 /***********************************************************************
302 * WIN_DestroyWindow
304 * Destroy storage associated to a window
306 static void WIN_DestroyWindow( HWND hwnd )
308 WND *wndPtr = WIN_FindWndPtr( hwnd );
310 #ifdef CONFIG_IPC
311 if (main_block)
312 DDE_DestroyWindow(hwnd);
313 #endif /* CONFIG_IPC */
315 if (!wndPtr) return;
316 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
317 TIMER_RemoveWindowTimers( hwnd );
318 PROPERTY_RemoveWindowProps( wndPtr );
319 wndPtr->dwMagic = 0; /* Mark it as invalid */
320 wndPtr->hwndSelf = 0;
321 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
323 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
324 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
326 if (!(wndPtr->dwStyle & WS_CHILD))
328 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
330 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
331 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
332 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
333 WINPROC_FreeProc( wndPtr->winproc );
334 wndPtr->class->cWindows--;
335 USER_HEAP_FREE( hwnd );
339 /***********************************************************************
340 * WIN_DestroyQueueWindows
342 void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue )
344 WND* next;
346 while (wnd)
348 next = wnd->next;
349 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
350 else WIN_DestroyQueueWindows( wnd->child, hQueue );
351 wnd = next;
356 /***********************************************************************
357 * WIN_CreateDesktopWindow
359 * Create the desktop window.
361 BOOL32 WIN_CreateDesktopWindow(void)
363 CLASS *class;
364 HWND hwndDesktop;
366 dprintf_win(stddeb,"Creating desktop window\n");
368 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
369 return FALSE;
371 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
372 if (!hwndDesktop) return FALSE;
373 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
375 pWndDesktop->next = NULL;
376 pWndDesktop->child = NULL;
377 pWndDesktop->parent = NULL;
378 pWndDesktop->owner = NULL;
379 pWndDesktop->class = class;
380 pWndDesktop->winproc = NULL;
381 pWndDesktop->dwMagic = WND_MAGIC;
382 pWndDesktop->hwndSelf = hwndDesktop;
383 pWndDesktop->hInstance = 0;
384 pWndDesktop->rectWindow.left = 0;
385 pWndDesktop->rectWindow.top = 0;
386 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
387 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
388 pWndDesktop->rectClient = pWndDesktop->rectWindow;
389 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
390 pWndDesktop->ptIconPos.x = -1;
391 pWndDesktop->ptIconPos.y = -1;
392 pWndDesktop->ptMaxPos.x = -1;
393 pWndDesktop->ptMaxPos.y = -1;
394 pWndDesktop->text = NULL;
395 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
396 pWndDesktop->hrgnUpdate = 0;
397 pWndDesktop->hwndLastActive = hwndDesktop;
398 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
399 WS_CLIPSIBLINGS;
400 pWndDesktop->dwExStyle = 0;
401 pWndDesktop->hdce = 0;
402 pWndDesktop->pVScroll = NULL;
403 pWndDesktop->pHScroll = NULL;
404 pWndDesktop->pProp = NULL;
405 pWndDesktop->wIDmenu = 0;
406 pWndDesktop->flags = 0;
407 pWndDesktop->window = rootWindow;
408 pWndDesktop->hSysMenu = 0;
409 pWndDesktop->userdata = 0;
411 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
412 EVENT_RegisterWindow( pWndDesktop );
413 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
414 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
415 return TRUE;
419 /***********************************************************************
420 * WIN_CreateWindowEx
422 * Implementation of CreateWindowEx().
424 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
425 BOOL unicode )
427 CLASS *classPtr;
428 WND *wndPtr;
429 HWND16 hwnd;
430 POINT16 maxSize, maxPos, minTrack, maxTrack;
431 LRESULT wmcreate;
433 dprintf_win( stddeb, "CreateWindowEx: " );
434 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
435 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
436 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
437 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
439 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
440 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
441 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
443 /* Find the parent window */
445 if (cs->hwndParent)
447 /* Make sure parent is valid */
448 if (!IsWindow( cs->hwndParent ))
450 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
451 return 0;
454 else if (cs->style & WS_CHILD)
456 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
457 return 0; /* WS_CHILD needs a parent */
460 /* Find the window class */
462 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
463 GetExePtr(cs->hInstance) )))
465 char buffer[256];
466 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
467 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
468 return 0;
471 /* Fix the coordinates */
473 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
474 if (cs->cx == CW_USEDEFAULT32)
476 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
477 else */
479 cs->cx = 600;
480 cs->cy = 400;
484 /* Create the window structure */
486 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
487 - sizeof(wndPtr->wExtra) )))
489 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
490 return 0;
493 /* Fill the window structure */
495 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
496 wndPtr->next = NULL;
497 wndPtr->child = NULL;
498 wndPtr->parent = (cs->style & WS_CHILD) ?
499 WIN_FindWndPtr( cs->hwndParent ) : pWndDesktop;
500 wndPtr->owner = (cs->style & WS_CHILD) ? NULL :
501 WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
502 wndPtr->window = 0;
503 wndPtr->class = classPtr;
504 wndPtr->winproc = NULL;
505 wndPtr->dwMagic = WND_MAGIC;
506 wndPtr->hwndSelf = hwnd;
507 wndPtr->hInstance = cs->hInstance;
508 wndPtr->ptIconPos.x = -1;
509 wndPtr->ptIconPos.y = -1;
510 wndPtr->ptMaxPos.x = -1;
511 wndPtr->ptMaxPos.y = -1;
512 wndPtr->text = NULL;
513 wndPtr->hmemTaskQ = GetTaskQueue(0);
514 wndPtr->hrgnUpdate = 0;
515 wndPtr->hwndLastActive = hwnd;
516 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
517 wndPtr->dwExStyle = cs->dwExStyle;
518 wndPtr->wIDmenu = 0;
519 wndPtr->flags = 0;
520 wndPtr->pVScroll = NULL;
521 wndPtr->pHScroll = NULL;
522 wndPtr->pProp = NULL;
523 wndPtr->hSysMenu = MENU_GetDefSysMenu();
524 wndPtr->userdata = 0;
526 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
527 classPtr->cWindows++;
529 /* Set the window procedure */
531 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
533 /* Correct the window style */
535 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
537 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
538 wndPtr->flags |= WIN_NEED_SIZE;
540 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
542 /* Get class or window DC if needed */
544 if (classPtr->style & CS_OWNDC) wndPtr->hdce = DCE_AllocDCE(hwnd, DCE_WINDOW_DC);
545 else if (classPtr->style & CS_CLASSDC) wndPtr->hdce = classPtr->hdce;
546 else wndPtr->hdce = 0;
548 /* Insert the window in the linked list */
550 WIN_LinkWindow( hwnd, (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP );
552 /* Call the WH_CBT hook */
554 if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
556 CBT_CREATEWND16* cbtc;
558 if ((cbtc = SEGPTR_NEW(CBT_CREATEWND16)))
560 /* Dummy message params to use WINPROC_MapMsg functions */
561 UINT16 msg;
562 WPARAM16 wparam;
563 LPARAM lparam;
565 HWND hwndZnew = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
567 /* Map the CREATESTRUCT to 16-bit format */
568 lparam = (LPARAM)cs;
569 if (unicode)
570 WINPROC_MapMsg32WTo16( WM_CREATE, 0, &msg, &wparam, &lparam );
571 else
572 WINPROC_MapMsg32ATo16( WM_CREATE, 0, &msg, &wparam, &lparam );
573 cbtc->lpcs = (CREATESTRUCT16 *)lparam;
574 cbtc->hwndInsertAfter = hwndZnew;
575 wmcreate = !HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, hwnd,
576 (LPARAM)SEGPTR_GET(cbtc) );
577 WINPROC_UnmapMsg32ATo16( WM_CREATE, 0, lparam );
578 if (hwndZnew != cbtc->hwndInsertAfter)
580 WIN_UnlinkWindow( hwnd );
581 WIN_LinkWindow( hwnd, cbtc->hwndInsertAfter );
583 SEGPTR_FREE(cbtc);
584 if (!wmcreate)
586 dprintf_win(stddeb,"CreateWindowEx: CBT-hook returned 0\n" );
587 WIN_DestroyWindow( hwnd );
588 return 0;
593 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
595 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
597 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
598 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
599 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
600 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
601 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
603 if (cs->cx <= 0) cs->cx = 1;
604 if (cs->cy <= 0) cs->cy = 1;
606 wndPtr->rectWindow.left = cs->x;
607 wndPtr->rectWindow.top = cs->y;
608 wndPtr->rectWindow.right = cs->x + cs->cx;
609 wndPtr->rectWindow.bottom = cs->y + cs->cy;
610 wndPtr->rectClient = wndPtr->rectWindow;
611 wndPtr->rectNormal = wndPtr->rectWindow;
613 /* Create the X window (only for top-level windows, and then only */
614 /* when there's no desktop window) */
616 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
618 XSetWindowAttributes win_attr;
619 Atom XA_WM_DELETE_WINDOW;
621 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
622 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
624 win_attr.event_mask = ExposureMask | KeyPressMask |
625 KeyReleaseMask | PointerMotionMask |
626 ButtonPressMask | ButtonReleaseMask |
627 FocusChangeMask | StructureNotifyMask;
628 win_attr.override_redirect = FALSE;
629 wndPtr->flags |= WIN_MANAGED;
631 else
633 win_attr.event_mask = ExposureMask | KeyPressMask |
634 KeyReleaseMask | PointerMotionMask |
635 ButtonPressMask | ButtonReleaseMask |
636 FocusChangeMask | StructureNotifyMask;
637 win_attr.override_redirect = TRUE;
639 win_attr.colormap = COLOR_GetColormap();
640 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
641 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
642 win_attr.cursor = CURSORICON_XCursor;
643 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
644 cs->cx, cs->cy, 0, CopyFromParent,
645 InputOutput, CopyFromParent,
646 CWEventMask | CWOverrideRedirect |
647 CWColormap | CWCursor | CWSaveUnder |
648 CWBackingStore, &win_attr );
649 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
650 False );
651 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
653 if ((wndPtr->flags & WIN_MANAGED) &&
654 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
656 XSizeHints* size_hints = XAllocSizeHints();
658 if (size_hints)
660 size_hints->min_width = size_hints->max_width = cs->cx;
661 size_hints->min_height = size_hints->max_height = cs->cy;
662 size_hints->flags = (PSize | PMinSize | PMaxSize);
663 XSetWMSizeHints( display, wndPtr->window, size_hints,
664 XA_WM_NORMAL_HINTS );
665 XFree(size_hints);
669 if (cs->hwndParent) /* Get window owner */
671 Window win = WIN_GetXWindow( cs->hwndParent );
672 if (win) XSetTransientForHint( display, wndPtr->window, win );
674 EVENT_RegisterWindow( wndPtr );
677 /* Set the window menu */
679 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
681 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
682 else
684 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
685 if (classPtr->menuNameA)
686 cs->hMenu = HIWORD(classPtr->menuNameA) ?
687 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
688 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
689 #else
690 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
691 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
692 #endif
694 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
696 else wndPtr->wIDmenu = (UINT)cs->hMenu;
698 /* Send the WM_CREATE message */
700 if (unicode)
702 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
703 else
705 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
706 NULL, NULL, 0, &wndPtr->rectClient );
707 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
710 else
712 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
713 else
715 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
716 NULL, NULL, 0, &wndPtr->rectClient );
717 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
721 if (wmcreate == -1)
723 /* Abort window creation */
724 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
725 WIN_DestroyWindow( hwnd );
726 return 0;
729 /* Send the size messages */
731 if (!(wndPtr->flags & WIN_NEED_SIZE))
733 /* send it anyway */
734 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
735 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
736 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
737 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
738 wndPtr->rectClient.top ));
741 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
742 if (!IsWindow(hwnd)) return 0;
744 /* Show the window, maximizing or minimizing if needed */
746 if (wndPtr->dwStyle & WS_MINIMIZE)
748 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
750 wndPtr->dwStyle &= ~WS_MAXIMIZE;
751 WINPOS_FindIconPos( hwnd );
752 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
753 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
754 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
756 else if (wndPtr->dwStyle & WS_MAXIMIZE)
758 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
760 POINT16 maxSize, maxPos, minTrack, maxTrack;
761 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
762 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
763 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
766 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
768 /* Call WH_SHELL hook */
770 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
771 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
773 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
774 return hwnd;
778 /***********************************************************************
779 * CreateWindow16 (USER.41)
781 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
782 DWORD style, INT16 x, INT16 y, INT16 width,
783 INT16 height, HWND16 parent, HMENU16 menu,
784 HINSTANCE16 instance, LPVOID data )
786 return CreateWindowEx16( 0, className, windowName, style,
787 x, y, width, height, parent, menu, instance, data );
791 /***********************************************************************
792 * CreateWindowEx16 (USER.452)
794 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
795 DWORD style, INT16 x, INT16 y, INT16 width,
796 INT16 height, HWND16 parent, HMENU16 menu,
797 HINSTANCE16 instance, LPVOID data )
799 ATOM classAtom;
800 CREATESTRUCT32A cs;
802 /* Find the class atom */
804 if (!(classAtom = GlobalFindAtom32A( className )))
806 fprintf( stderr, "CreateWindowEx16: bad class name " );
807 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
808 else fprintf( stderr, "'%s'\n", className );
809 return 0;
812 /* Fix the coordinates */
814 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
815 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
816 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
817 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
819 /* Create the window */
821 cs.lpCreateParams = data;
822 cs.hInstance = (HINSTANCE32)instance;
823 cs.hMenu = (HMENU32)menu;
824 cs.hwndParent = (HWND32)parent;
825 cs.style = style;
826 cs.lpszName = windowName;
827 cs.lpszClass = className;
828 cs.dwExStyle = exStyle;
829 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
833 /***********************************************************************
834 * CreateWindowEx32A (USER32.82)
836 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
837 DWORD style, INT32 x, INT32 y, INT32 width,
838 INT32 height, HWND32 parent, HMENU32 menu,
839 HINSTANCE32 instance, LPVOID data )
841 ATOM classAtom;
842 CREATESTRUCT32A cs;
844 /* Find the class atom */
846 if (!(classAtom = GlobalFindAtom32A( className )))
848 fprintf( stderr, "CreateWindowEx32A: bad class name " );
849 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
850 else fprintf( stderr, "'%s'\n", className );
851 return 0;
854 /* Create the window */
856 cs.lpCreateParams = data;
857 cs.hInstance = instance;
858 cs.hMenu = menu;
859 cs.hwndParent = parent;
860 cs.x = x;
861 cs.y = y;
862 cs.cx = width;
863 cs.cy = height;
864 cs.style = style;
865 cs.lpszName = windowName;
866 cs.lpszClass = className;
867 cs.dwExStyle = exStyle;
868 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
872 /***********************************************************************
873 * CreateWindowEx32W (USER32.83)
875 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
876 DWORD style, INT32 x, INT32 y, INT32 width,
877 INT32 height, HWND32 parent, HMENU32 menu,
878 HINSTANCE32 instance, LPVOID data )
880 ATOM classAtom;
881 CREATESTRUCT32W cs;
883 /* Find the class atom */
885 if (!(classAtom = GlobalFindAtom32W( className )))
887 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
888 return 0;
891 /* Create the window */
893 cs.lpCreateParams = data;
894 cs.hInstance = instance;
895 cs.hMenu = menu;
896 cs.hwndParent = parent;
897 cs.x = x;
898 cs.y = y;
899 cs.cx = width;
900 cs.cy = height;
901 cs.style = style;
902 cs.lpszName = windowName;
903 cs.lpszClass = className;
904 cs.dwExStyle = exStyle;
905 /* Note: we rely on the fact that CREATESTRUCT32A and */
906 /* CREATESTRUCT32W have the same layout. */
907 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
911 /***********************************************************************
912 * DestroyWindow (USER.53)
914 BOOL DestroyWindow( HWND hwnd )
916 WND * wndPtr;
918 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
920 /* Initialization */
922 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
923 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
925 /* Top-level window */
927 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
929 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
930 /* FIXME: clean up palette - see "Internals" p.352 */
933 /* Hide the window */
935 if (wndPtr->dwStyle & WS_VISIBLE)
936 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
937 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
938 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
939 ReleaseCapture();
940 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
942 CLIPBOARD_DisOwn( hwnd );
944 /* Recursively destroy owned windows */
946 for (;;)
948 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
949 while (siblingPtr)
951 if (siblingPtr->owner == wndPtr) break;
952 siblingPtr = siblingPtr->next;
954 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
955 else break;
958 /* Send destroy messages and destroy children */
960 SendMessage16( hwnd, WM_DESTROY, 0, 0 );
961 while (wndPtr->child) /* The child removes itself from the list */
962 DestroyWindow( wndPtr->child->hwndSelf );
963 SendMessage16( hwnd, WM_NCDESTROY, 0, 0 );
965 /* Destroy the window */
967 WIN_DestroyWindow( hwnd );
968 return TRUE;
972 /***********************************************************************
973 * CloseWindow (USER.43)
975 BOOL CloseWindow(HWND hWnd)
977 WND * wndPtr = WIN_FindWndPtr(hWnd);
978 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
979 ShowWindow(hWnd, SW_MINIMIZE);
980 return TRUE;
984 /***********************************************************************
985 * OpenIcon (USER.44)
987 BOOL OpenIcon(HWND hWnd)
989 if (!IsIconic(hWnd)) return FALSE;
990 ShowWindow(hWnd, SW_SHOWNORMAL);
991 return(TRUE);
995 /***********************************************************************
996 * WIN_FindWindow
998 * Implementation of FindWindow() and FindWindowEx().
1000 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1001 LPCSTR title )
1003 WND *pWnd;
1004 CLASS *pClass = NULL;
1006 if (child)
1008 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1009 if (parent)
1011 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1013 else if (pWnd->parent != pWndDesktop) return 0;
1014 pWnd = pWnd->next;
1016 else
1018 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1019 pWnd = pWnd->child;
1021 if (!pWnd) return 0;
1023 /* For a child window, all siblings will have the same hInstance, */
1024 /* so we can look for the class once and for all. */
1026 if (className && (pWnd->dwStyle & WS_CHILD))
1028 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1029 return 0;
1032 for ( ; pWnd; pWnd = pWnd->next)
1034 if (className && !(pWnd->dwStyle & WS_CHILD))
1036 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1037 continue; /* Skip this window */
1039 if (pClass && (pWnd->class != pClass))
1040 continue; /* Not the right class */
1042 /* Now check the title */
1044 if (!title) return pWnd->hwndSelf;
1045 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1047 return 0;
1052 /***********************************************************************
1053 * FindWindow16 (USER.50)
1055 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1057 return FindWindowEx16( 0, 0, className, title );
1061 /***********************************************************************
1062 * FindWindowEx16 (USER.427)
1064 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1065 SEGPTR className, LPCSTR title )
1067 ATOM atom = 0;
1069 if (className)
1071 /* If the atom doesn't exist, then no class */
1072 /* with this name exists either. */
1073 if (!(atom = GlobalFindAtom16( className ))) return 0;
1075 return WIN_FindWindow( parent, child, atom, title );
1079 /***********************************************************************
1080 * FindWindow32A (USER32.197)
1082 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1084 return FindWindowEx32A( 0, 0, className, title );
1088 /***********************************************************************
1089 * FindWindowEx32A (USER32.198)
1091 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1092 LPCSTR className, LPCSTR title )
1094 ATOM atom = 0;
1096 if (className)
1098 /* If the atom doesn't exist, then no class */
1099 /* with this name exists either. */
1100 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1102 return WIN_FindWindow( 0, 0, atom, title );
1106 /***********************************************************************
1107 * FindWindowEx32W (USER32.199)
1109 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1110 LPCWSTR className, LPCWSTR title )
1112 ATOM atom = 0;
1113 char *buffer;
1114 HWND hwnd;
1116 if (className)
1118 /* If the atom doesn't exist, then no class */
1119 /* with this name exists either. */
1120 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1122 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1123 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1124 if (buffer) free( buffer );
1125 return hwnd;
1129 /***********************************************************************
1130 * FindWindow32W (USER32.200)
1132 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1134 return FindWindowEx32W( 0, 0, className, title );
1138 /**********************************************************************
1139 * WIN_GetDesktop
1141 WND *WIN_GetDesktop(void)
1143 return pWndDesktop;
1147 /**********************************************************************
1148 * GetDesktopWindow (USER.286)
1150 HWND GetDesktopWindow(void)
1152 return pWndDesktop->hwndSelf;
1156 /**********************************************************************
1157 * GetDesktopHwnd (USER.278)
1159 * Exactly the same thing as GetDesktopWindow(), but not documented.
1160 * Don't ask me why...
1162 HWND GetDesktopHwnd(void)
1164 return pWndDesktop->hwndSelf;
1168 /*******************************************************************
1169 * EnableWindow (USER.34)
1171 BOOL EnableWindow( HWND hwnd, BOOL enable )
1173 WND *wndPtr;
1175 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1176 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1178 /* Enable window */
1179 wndPtr->dwStyle &= ~WS_DISABLED;
1180 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1181 return TRUE;
1183 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1185 /* Disable window */
1186 wndPtr->dwStyle |= WS_DISABLED;
1187 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1188 SetFocus32( 0 ); /* A disabled window can't have the focus */
1189 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1190 ReleaseCapture(); /* A disabled window can't capture the mouse */
1191 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1192 return FALSE;
1194 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1198 /***********************************************************************
1199 * IsWindowEnabled (USER.35) (USER32.348)
1201 BOOL IsWindowEnabled(HWND hWnd)
1203 WND * wndPtr;
1205 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1206 return !(wndPtr->dwStyle & WS_DISABLED);
1210 /***********************************************************************
1211 * IsWindowUnicode (USER32.349)
1213 BOOL32 IsWindowUnicode( HWND32 hwnd )
1215 WND * wndPtr;
1217 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1218 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1222 /**********************************************************************
1223 * GetWindowWord (USER.133) (USER32.313)
1225 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1227 WND * wndPtr = WIN_FindWndPtr( hwnd );
1228 if (!wndPtr) return 0;
1229 if (offset >= 0)
1231 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1233 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1234 return 0;
1236 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1238 switch(offset)
1240 case GWW_ID: return wndPtr->wIDmenu;
1241 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1242 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1243 default:
1244 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1245 return 0;
1250 /**********************************************************************
1251 * WIN_GetWindowInstance
1253 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1255 WND * wndPtr = WIN_FindWndPtr( hwnd );
1256 if (!wndPtr) return (HINSTANCE16)0;
1257 return wndPtr->hInstance;
1261 /**********************************************************************
1262 * SetWindowWord (USER.134) (USER32.523)
1264 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1266 WORD *ptr, retval;
1267 WND * wndPtr = WIN_FindWndPtr( hwnd );
1268 if (!wndPtr) return 0;
1269 if (offset >= 0)
1271 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1273 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1274 return 0;
1276 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1278 else switch(offset)
1280 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1281 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1282 default:
1283 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1284 return 0;
1286 retval = *ptr;
1287 *ptr = newval;
1288 return retval;
1292 /**********************************************************************
1293 * WIN_GetWindowLong
1295 * Helper function for GetWindowLong().
1297 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1299 LONG retval;
1300 WND * wndPtr = WIN_FindWndPtr( hwnd );
1301 if (!wndPtr) return 0;
1302 if (offset >= 0)
1304 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1306 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1307 return 0;
1309 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1310 /* Special case for dialog window procedure */
1311 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1312 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1313 return retval;
1315 switch(offset)
1317 case GWL_USERDATA: return wndPtr->userdata;
1318 case GWL_STYLE: return wndPtr->dwStyle;
1319 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1320 case GWL_ID: return wndPtr->wIDmenu;
1321 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1322 type );
1323 case GWL_HWNDPARENT: return wndPtr->parent ?
1324 (HWND32)wndPtr->parent->hwndSelf : 0;
1325 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1326 default:
1327 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1329 return 0;
1333 /**********************************************************************
1334 * WIN_SetWindowLong
1336 * Helper function for SetWindowLong().
1338 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1339 WINDOWPROCTYPE type )
1341 LONG *ptr, retval;
1342 WND * wndPtr = WIN_FindWndPtr( hwnd );
1343 if (!wndPtr) return 0;
1344 if (offset >= 0)
1346 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1348 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1349 return 0;
1351 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1352 /* Special case for dialog window procedure */
1353 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1355 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1356 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1357 return retval;
1360 else switch(offset)
1362 case GWL_ID:
1363 case GWL_HINSTANCE:
1364 return SetWindowWord( hwnd, offset, (WORD)newval );
1365 case GWL_WNDPROC:
1366 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1367 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1368 return retval;
1369 case GWL_STYLE:
1370 ptr = &wndPtr->dwStyle;
1371 /* Some bits can't be changed this way */
1372 newval &= ~(WS_VISIBLE | WS_CHILD);
1373 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1374 break;
1375 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1376 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1377 default:
1378 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1379 return 0;
1381 retval = *ptr;
1382 *ptr = newval;
1383 return retval;
1387 /**********************************************************************
1388 * GetWindowLong16 (USER.135)
1390 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1392 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1396 /**********************************************************************
1397 * GetWindowLong32A (USER32.304)
1399 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1401 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1405 /**********************************************************************
1406 * GetWindowLong32W (USER32.305)
1408 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1410 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1414 /**********************************************************************
1415 * SetWindowLong16 (USER.136)
1417 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1419 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1423 /**********************************************************************
1424 * SetWindowLong32A (USER32.516)
1426 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1428 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1432 /**********************************************************************
1433 * SetWindowLong32W (USER32.517)
1435 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1437 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1441 /*******************************************************************
1442 * GetWindowText16 (USER.36)
1444 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1446 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1450 /*******************************************************************
1451 * GetWindowText32A (USER32.308)
1453 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1455 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1456 (LPARAM)lpString );
1460 /*******************************************************************
1461 * GetWindowText32W (USER32.311)
1463 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1465 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1466 (LPARAM)lpString );
1470 /*******************************************************************
1471 * SetWindowText16 (USER.37)
1473 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1475 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1479 /*******************************************************************
1480 * SetWindowText32A (USER32.)
1482 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1484 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1488 /*******************************************************************
1489 * SetWindowText32W (USER32.)
1491 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1493 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1497 /*******************************************************************
1498 * GetWindowTextLength (USER.38)
1500 int GetWindowTextLength(HWND hwnd)
1502 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1506 /*******************************************************************
1507 * IsWindow (USER.47) (USER32.347)
1509 BOOL16 IsWindow( HWND32 hwnd )
1511 WND * wndPtr = WIN_FindWndPtr( hwnd );
1512 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1516 /*****************************************************************
1517 * GetParent16 (USER.46)
1519 HWND16 GetParent16( HWND16 hwnd )
1521 return (HWND16)GetParent32( hwnd );
1525 /*****************************************************************
1526 * GetParent32 (USER32.277)
1528 HWND32 GetParent32( HWND32 hwnd )
1530 WND *wndPtr = WIN_FindWndPtr(hwnd);
1531 if (!wndPtr) return 0;
1532 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1533 return wndPtr ? wndPtr->hwndSelf : 0;
1537 /*****************************************************************
1538 * WIN_GetTopParent
1540 * Get the top-level parent for a child window.
1542 HWND32 WIN_GetTopParent( HWND32 hwnd )
1544 WND *wndPtr = WIN_FindWndPtr( hwnd );
1545 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1546 return wndPtr ? wndPtr->hwndSelf : 0;
1550 /*****************************************************************
1551 * SetParent (USER.233)
1553 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1555 HWND oldParent;
1557 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1558 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1559 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1561 oldParent = wndPtr->parent->hwndSelf;
1563 WIN_UnlinkWindow(hwndChild);
1564 if (hwndNewParent) wndPtr->parent = pWndParent;
1565 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1567 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1569 return oldParent;
1574 /*******************************************************************
1575 * IsChild (USER.48)
1577 BOOL IsChild( HWND parent, HWND child )
1579 WND * wndPtr = WIN_FindWndPtr( child );
1580 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1582 wndPtr = wndPtr->parent;
1583 if (wndPtr->hwndSelf == parent) return TRUE;
1585 return FALSE;
1589 /***********************************************************************
1590 * IsWindowVisible (USER.49) (USER32.350)
1592 BOOL IsWindowVisible( HWND hwnd )
1594 WND *wndPtr = WIN_FindWndPtr( hwnd );
1595 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1597 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1598 wndPtr = wndPtr->parent;
1600 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1603 /***********************************************************************
1604 * WIN_IsWindowDrawable
1606 * hwnd is drawable when it is visible, all parents are not
1607 * minimized, and it is itself not minimized unless we are
1608 * trying to draw icon and the default class icon is set.
1610 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1612 HWND hwnd= wnd->hwndSelf;
1613 BOOL32 yes = TRUE;
1615 while(wnd && yes)
1617 if( wnd->dwStyle & WS_MINIMIZE )
1618 if( wnd->hwndSelf != hwnd ) break;
1619 else if( icon && wnd->class->hIcon ) break;
1621 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1622 wnd = wnd->parent; }
1623 return (!wnd && yes);
1626 /*******************************************************************
1627 * GetTopWindow (USER.229)
1629 HWND GetTopWindow( HWND hwnd )
1631 WND * wndPtr = WIN_FindWndPtr( hwnd );
1632 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1633 else return 0;
1637 /*******************************************************************
1638 * GetWindow (USER.262)
1640 HWND GetWindow( HWND hwnd, WORD rel )
1642 WND * wndPtr = WIN_FindWndPtr( hwnd );
1643 if (!wndPtr) return 0;
1644 switch(rel)
1646 case GW_HWNDFIRST:
1647 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1648 else return 0;
1650 case GW_HWNDLAST:
1651 if (!wndPtr->parent) return 0; /* Desktop window */
1652 while (wndPtr->next) wndPtr = wndPtr->next;
1653 return wndPtr->hwndSelf;
1655 case GW_HWNDNEXT:
1656 if (!wndPtr->next) return 0;
1657 return wndPtr->next->hwndSelf;
1659 case GW_HWNDPREV:
1660 if (!wndPtr->parent) return 0; /* Desktop window */
1661 wndPtr = wndPtr->parent->child; /* First sibling */
1662 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1663 while (wndPtr->next)
1665 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1666 wndPtr = wndPtr->next;
1668 return 0;
1670 case GW_OWNER:
1671 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1673 case GW_CHILD:
1674 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1676 return 0;
1680 /*******************************************************************
1681 * GetNextWindow (USER.230)
1683 HWND GetNextWindow( HWND hwnd, WORD flag )
1685 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1686 return GetWindow( hwnd, flag );
1689 /*******************************************************************
1690 * ShowOwnedPopups (USER.265)
1692 void ShowOwnedPopups( HWND owner, BOOL fShow )
1694 WND *pWnd = pWndDesktop->child;
1695 while (pWnd)
1697 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1698 (pWnd->dwStyle & WS_POPUP))
1699 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1700 pWnd = pWnd->next;
1705 /*******************************************************************
1706 * GetLastActivePopup (USER.287)
1708 HWND GetLastActivePopup(HWND hwnd)
1710 WND *wndPtr;
1711 wndPtr = WIN_FindWndPtr(hwnd);
1712 if (wndPtr == NULL) return hwnd;
1713 return wndPtr->hwndLastActive;
1717 /*******************************************************************
1718 * WIN_BuildWinArray
1720 * Build an array of pointers to all children of a given window.
1721 * The array must be freed with HeapFree(SystemHeap).
1723 WND **WIN_BuildWinArray( WND *wndPtr )
1725 WND **list, **ppWnd;
1726 WND *pWnd;
1727 INT32 count;
1729 /* First count the windows */
1731 if (!wndPtr) wndPtr = pWndDesktop;
1732 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1733 count++; /* For the terminating NULL */
1735 /* Now build the list of all windows */
1737 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1738 return NULL;
1739 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1740 *ppWnd++ = pWnd;
1741 *ppWnd = NULL;
1742 return list;
1746 /*******************************************************************
1747 * EnumWindows16 (USER.54)
1749 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1751 WND **list, **ppWnd;
1753 /* We have to build a list of all windows first, to avoid */
1754 /* unpleasant side-effects, for instance if the callback */
1755 /* function changes the Z-order of the windows. */
1757 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1759 /* Now call the callback function for every window */
1761 for (ppWnd = list; *ppWnd; ppWnd++)
1763 /* Make sure that the window still exists */
1764 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1765 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1767 HeapFree( SystemHeap, 0, list );
1768 return TRUE;
1772 /*******************************************************************
1773 * EnumWindows32 (USER32.192)
1775 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1777 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1781 /**********************************************************************
1782 * EnumTaskWindows16 (USER.225)
1784 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1786 WND **list, **ppWnd;
1787 HANDLE hQueue = GetTaskQueue( hTask );
1789 /* This function is the same as EnumWindows(), */
1790 /* except for an added check on the window queue. */
1792 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1794 /* Now call the callback function for every window */
1796 for (ppWnd = list; *ppWnd; ppWnd++)
1798 /* Make sure that the window still exists */
1799 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1800 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1801 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1803 HeapFree( SystemHeap, 0, list );
1804 return TRUE;
1808 /**********************************************************************
1809 * EnumThreadWindows (USER32.189)
1811 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1813 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1817 /**********************************************************************
1818 * WIN_EnumChildWindows
1820 * Helper function for EnumChildWindows().
1822 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1823 LPARAM lParam )
1825 WND **childList;
1826 BOOL16 ret = FALSE;
1828 while (*ppWnd)
1830 /* Make sure that the window still exists */
1831 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1832 /* Build children list first */
1833 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1834 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1835 ret = WIN_EnumChildWindows( childList, func, lParam );
1836 HeapFree( SystemHeap, 0, childList );
1837 if (!ret) return FALSE;
1838 ppWnd++;
1840 return TRUE;
1844 /**********************************************************************
1845 * EnumChildWindows16 (USER.55)
1847 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1849 WND **list, *pParent;
1851 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1852 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1853 WIN_EnumChildWindows( list, func, lParam );
1854 HeapFree( SystemHeap, 0, list );
1855 return TRUE;
1859 /**********************************************************************
1860 * EnumChildWindows32 (USER32.177)
1862 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1864 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1865 lParam );
1869 /*******************************************************************
1870 * AnyPopup (USER.52)
1872 BOOL AnyPopup(void)
1874 WND *wndPtr;
1875 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1876 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1877 return FALSE;
1880 /*******************************************************************
1881 * FlashWindow [USER.105]
1883 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1885 WND *wndPtr = WIN_FindWndPtr(hWnd);
1887 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
1889 if (!wndPtr) return FALSE;
1891 if (wndPtr->dwStyle & WS_MINIMIZE)
1893 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1895 HDC hDC = GetDC(hWnd);
1897 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1898 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1900 ReleaseDC( hWnd, hDC );
1901 wndPtr->flags |= WIN_NCACTIVATED;
1903 else
1905 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1906 RDW_UPDATENOW | RDW_FRAME, 0 );
1907 wndPtr->flags &= ~WIN_NCACTIVATED;
1909 return TRUE;
1911 else
1913 WPARAM wparam;
1914 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1915 else wparam = (hWnd == GetActiveWindow());
1917 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1918 return wparam;
1923 /*******************************************************************
1924 * SetSysModalWindow16 (USER.188)
1926 HWND16 SetSysModalWindow16( HWND16 hWnd )
1928 HWND hWndOldModal = hwndSysModal;
1929 hwndSysModal = hWnd;
1930 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
1931 return hWndOldModal;
1935 /*******************************************************************
1936 * GetSysModalWindow16 (USER.52)
1938 HWND16 GetSysModalWindow16(void)
1940 return hwndSysModal;
1944 /*******************************************************************
1945 * DRAG_QueryUpdate
1947 * recursively find a child that contains spDragInfo->pt point
1948 * and send WM_QUERYDROPOBJECT
1950 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1952 BOOL wParam,bResult = 0;
1953 POINT16 pt;
1954 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1955 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1956 RECT16 tempRect; /* this sucks */
1958 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1960 pt = ptrDragInfo->pt;
1962 GetWindowRect16(hQueryWnd,&tempRect);
1964 if( !PtInRect16(&tempRect,pt) ||
1965 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1966 return 0;
1968 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1970 tempRect = ptrQueryWnd->rectClient;
1971 if(ptrQueryWnd->dwStyle & WS_CHILD)
1972 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
1974 if( PtInRect16(&tempRect,pt) )
1976 wParam = 0;
1978 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
1979 if( ptrWnd->dwStyle & WS_VISIBLE )
1981 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
1983 if( PtInRect16(&tempRect,pt) )
1984 break;
1987 if(ptrWnd)
1989 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
1990 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
1991 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
1992 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1993 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo);
1996 if(bResult) return bResult;
1998 else wParam = 1;
2000 else wParam = 1;
2002 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2004 ptrDragInfo->hScope = hQueryWnd;
2006 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2007 (WPARAM)wParam ,(LPARAM) spDragInfo );
2008 if( !bResult )
2009 ptrDragInfo->pt = pt;
2011 return bResult;
2014 /*******************************************************************
2015 * DragDetect ( USER.465 )
2018 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2020 MSG16 msg;
2021 RECT16 rect;
2023 rect.left = pt.x - wDragWidth;
2024 rect.right = pt.x + wDragWidth;
2026 rect.top = pt.y - wDragHeight;
2027 rect.bottom = pt.y + wDragHeight;
2029 SetCapture(hWnd);
2031 while(1)
2033 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2035 if( msg.message == WM_LBUTTONUP )
2037 ReleaseCapture();
2038 return 0;
2040 if( msg.message == WM_MOUSEMOVE )
2042 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2044 ReleaseCapture();
2045 return 1;
2049 WaitMessage();
2052 return 0;
2055 /******************************************************************************
2056 * DragObject ( USER.464 )
2059 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
2060 WORD szList , HCURSOR16 hCursor)
2062 MSG16 msg;
2063 LPDRAGINFO lpDragInfo;
2064 SEGPTR spDragInfo;
2065 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2066 HANDLE hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2067 WND *wndPtr = WIN_FindWndPtr(hWnd);
2068 DWORD dwRet = 0;
2069 short dragDone = 0;
2070 HCURSOR16 hCurrentCursor = 0;
2071 HWND hCurrentWnd = 0;
2072 WORD btemp;
2074 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2075 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2077 if( !lpDragInfo || !spDragInfo ) return 0L;
2079 hBummer = LoadCursor16(0,IDC_BUMMER);
2081 if( !hBummer || !wndPtr )
2083 GlobalFree16(hDragInfo);
2084 return 0L;
2087 if(hCursor)
2089 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
2091 GlobalFree16(hDragInfo);
2092 return 0L;
2095 if( hDragCursor == hCursor ) hDragCursor = 0;
2096 else hCursor = hDragCursor;
2098 hOldCursor = SetCursor(hDragCursor);
2101 lpDragInfo->hWnd = hWnd;
2102 lpDragInfo->hScope = 0;
2103 lpDragInfo->wFlags = wObj;
2104 lpDragInfo->hList = szList; /* near pointer! */
2105 lpDragInfo->hOfStruct = hOfStruct;
2106 lpDragInfo->l = 0L;
2108 SetCapture(hWnd);
2109 ShowCursor(1);
2111 while( !dragDone )
2113 WaitMessage();
2115 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2116 continue;
2118 *(lpDragInfo+1) = *lpDragInfo;
2120 lpDragInfo->pt = msg.pt;
2122 /* update DRAGINFO struct */
2123 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2125 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
2126 hCurrentCursor = hCursor;
2127 else
2129 hCurrentCursor = hBummer;
2130 lpDragInfo->hScope = 0;
2132 if( hCurrentCursor )
2133 SetCursor(hCurrentCursor);
2135 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
2137 /* send WM_DRAGLOOP */
2138 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
2139 (LPARAM) spDragInfo );
2140 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2141 if( hCurrentWnd != lpDragInfo->hScope )
2143 if( hCurrentWnd )
2144 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2145 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2146 HIWORD(spDragInfo)) );
2147 hCurrentWnd = lpDragInfo->hScope;
2148 if( hCurrentWnd )
2149 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2151 else
2152 if( hCurrentWnd )
2153 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2156 /* check if we're done */
2157 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2158 dragDone = TRUE;
2161 ReleaseCapture();
2162 ShowCursor(0);
2164 if( hCursor )
2166 SetCursor(hOldCursor);
2167 if( hDragCursor )
2168 DestroyCursor(hDragCursor);
2171 if( hCurrentCursor != hBummer )
2172 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2173 (WPARAM)hWnd, (LPARAM)spDragInfo );
2174 GlobalFree16(hDragInfo);
2176 return dwRet;