Release 950918
[wine/hacks.git] / windows / win.c
blobd7e2d2d653899ff87ad000806d89d95c0e103236
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
10 #include "options.h"
11 #include "class.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "menu.h"
17 #include "icon.h"
18 #include "cursor.h"
19 #include "event.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "winpos.h"
23 #include "color.h"
24 #include "shm_main_blk.h"
25 #include "dde_proc.h"
26 #include "callback.h"
27 #include "stddebug.h"
28 /* #define DEBUG_WIN */
29 /* #define DEBUG_MENU */
30 #include "debug.h"
32 static HWND hwndDesktop = 0;
33 static HWND hWndSysModal = 0;
35 /***********************************************************************
36 * WIN_FindWndPtr
38 * Return a pointer to the WND structure corresponding to a HWND.
40 WND * WIN_FindWndPtr( HWND hwnd )
42 WND * ptr;
44 if (!hwnd) return NULL;
45 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
46 if (ptr->dwMagic != WND_MAGIC) return NULL;
47 return ptr;
51 /***********************************************************************
52 * WIN_GetXWindow
54 * Return the X window associated to a window.
56 Window WIN_GetXWindow( HWND hwnd )
58 WND *wndPtr = WIN_FindWndPtr( hwnd );
59 while (wndPtr && !wndPtr->window)
61 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
63 return wndPtr ? wndPtr->window : 0;
67 /***********************************************************************
68 * WIN_UnlinkWindow
70 * Remove a window from the siblings linked list.
72 BOOL WIN_UnlinkWindow( HWND hwnd )
74 HWND * curWndPtr;
75 WND *parentPtr, *wndPtr;
77 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
78 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
80 curWndPtr = &parentPtr->hwndChild;
82 while (*curWndPtr != hwnd)
84 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
85 curWndPtr = &curPtr->hwndNext;
87 *curWndPtr = wndPtr->hwndNext;
88 return TRUE;
92 /***********************************************************************
93 * WIN_LinkWindow
95 * Insert a window into the siblings linked list.
96 * The window is inserted after the specified window, which can also
97 * be specified as HWND_TOP or HWND_BOTTOM.
99 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
101 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
102 WND *wndPtr, *parentPtr;
104 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
105 if (!(parentPtr = WIN_FindWndPtr( wndPtr->hwndParent ))) return FALSE;
107 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
109 hwndPtr = &parentPtr->hwndChild; /* Point to first sibling hwnd */
110 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
111 while (*hwndPtr)
113 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
114 hwndPtr = &nextPtr->hwndNext;
117 else /* Normal case */
119 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
120 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
122 if (!hwndPtr) return FALSE;
123 wndPtr->hwndNext = *hwndPtr;
124 *hwndPtr = hwnd;
125 return TRUE;
129 /***********************************************************************
130 * WIN_FindWinToRepaint
132 * Find a window that needs repaint.
134 HWND WIN_FindWinToRepaint( HWND hwnd )
136 WND * wndPtr;
138 /* Note: the desktop window never gets WM_PAINT messages */
139 if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
140 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
142 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
143 dprintf_win( stddeb, "WIN_FindWinToRepaint: %04x, style %08lx\n",
144 hwnd, wndPtr->dwStyle );
145 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
146 continue;
147 if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
148 continue;
149 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
150 return hwnd;
151 if (wndPtr->hwndChild)
153 HWND child;
154 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
155 return child;
158 return 0;
162 /***********************************************************************
163 * WIN_SendParentNotify
165 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
166 * the window has the WS_EX_NOPARENTNOTIFY style.
168 void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam )
170 WND *wndPtr = WIN_FindWndPtr( hwnd );
172 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
174 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
175 SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event, lParam );
176 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
182 /***********************************************************************
183 * WIN_DestroyWindow
185 * Destroy storage associated to a window
187 static void WIN_DestroyWindow( HWND hwnd )
189 WND *wndPtr = WIN_FindWndPtr( hwnd );
190 CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
192 #ifdef CONFIG_IPC
193 if (main_block)
194 DDE_DestroyWindow(hwnd);
195 #endif /* CONFIG_IPC */
197 if (!wndPtr || !classPtr) return;
198 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
199 wndPtr->dwMagic = 0; /* Mark it as invalid */
200 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
202 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
203 MSG_DecPaintCount( wndPtr->hmemTaskQ );
205 if (!(wndPtr->dwStyle & WS_CHILD))
207 if (wndPtr->wIDmenu) DestroyMenu( wndPtr->wIDmenu );
209 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
210 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
211 if (classPtr->wc.style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
212 classPtr->cWindows--;
213 USER_HEAP_FREE( hwnd );
217 /***********************************************************************
218 * WIN_CreateDesktopWindow
220 * Create the desktop window.
222 BOOL WIN_CreateDesktopWindow(void)
224 WND *wndPtr;
225 HCLASS hclass;
226 CLASS *classPtr;
227 HDC hdc;
229 if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_ATOM, 0, &classPtr )))
230 return FALSE;
232 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
233 if (!hwndDesktop) return FALSE;
234 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
236 wndPtr->hwndNext = 0;
237 wndPtr->hwndChild = 0;
238 wndPtr->dwMagic = WND_MAGIC;
239 wndPtr->hwndParent = 0;
240 wndPtr->hwndOwner = 0;
241 wndPtr->hClass = hclass;
242 wndPtr->hInstance = 0;
243 wndPtr->rectWindow.left = 0;
244 wndPtr->rectWindow.top = 0;
245 wndPtr->rectWindow.right = SYSMETRICS_CXSCREEN;
246 wndPtr->rectWindow.bottom = SYSMETRICS_CYSCREEN;
247 wndPtr->rectClient = wndPtr->rectWindow;
248 wndPtr->rectNormal = wndPtr->rectWindow;
249 wndPtr->ptIconPos.x = -1;
250 wndPtr->ptIconPos.y = -1;
251 wndPtr->ptMaxPos.x = -1;
252 wndPtr->ptMaxPos.y = -1;
253 wndPtr->hmemTaskQ = 0; /* Desktop does not belong to a task */
254 wndPtr->hrgnUpdate = 0;
255 wndPtr->hwndLastActive = hwndDesktop;
256 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
257 wndPtr->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
258 wndPtr->dwExStyle = 0;
259 wndPtr->hdce = 0;
260 wndPtr->hVScroll = 0;
261 wndPtr->hHScroll = 0;
262 wndPtr->wIDmenu = 0;
263 wndPtr->hText = 0;
264 wndPtr->flags = 0;
265 wndPtr->window = rootWindow;
266 wndPtr->hSysMenu = 0;
267 wndPtr->hProp = 0;
268 EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
269 SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
270 if ((hdc = GetDC( hwndDesktop )) != 0)
272 SendMessage( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
273 ReleaseDC( hwndDesktop, hdc );
275 return TRUE;
279 /***********************************************************************
280 * CreateWindow (USER.41)
282 HWND CreateWindow( SEGPTR className, SEGPTR windowName,
283 DWORD style, short x, short y, short width, short height,
284 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
286 return CreateWindowEx( 0, className, windowName, style,
287 x, y, width, height, parent, menu, instance, data );
291 /***********************************************************************
292 * CreateWindowEx (USER.452)
294 HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
295 DWORD style, short x, short y, short width, short height,
296 HWND parent, HMENU menu, HANDLE instance, SEGPTR data )
298 HANDLE class, hwnd;
299 CLASS *classPtr;
300 WND *wndPtr;
301 POINT maxSize, maxPos, minTrack, maxTrack;
302 CREATESTRUCT createStruct;
303 int wmcreate;
304 XSetWindowAttributes win_attr;
306 /* FIXME: windowName and className should be SEGPTRs */
308 dprintf_win( stddeb, "CreateWindowEx: " );
309 if (HIWORD(windowName))
310 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName) );
311 else
312 dprintf_win( stddeb, "%04x ", LOWORD(windowName) );
313 if (HIWORD(className))
314 dprintf_win( stddeb, "'%s' ", (char *)PTR_SEG_TO_LIN(className) );
315 else
316 dprintf_win( stddeb, "%04x ", LOWORD(className) );
318 dprintf_win(stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %08lx\n",
319 exStyle, style, x, y, width, height,
320 parent, menu, instance, data);
322 if (x == CW_USEDEFAULT) x = y = 0;
323 if (width == CW_USEDEFAULT)
325 width = 600;
326 height = 400;
329 /* Find the parent and class */
331 if (parent)
333 /* Make sure parent is valid */
334 if (!IsWindow( parent )) {
335 dprintf_win(stddeb,"CreateWindowEx: Parent %x is not a window\n", parent);
336 return 0;
339 else
341 if (style & WS_CHILD) {
342 dprintf_win(stddeb,"CreateWindowEx: no parent\n");
343 return 0; /* WS_CHILD needs a parent */
347 if (!(class = CLASS_FindClassByName( className, GetExePtr(instance),
348 &classPtr )))
350 fprintf(stderr,"CreateWindow BAD CLASSNAME " );
351 if (HIWORD(className)) fprintf( stderr, "'%s'\n",
352 (char *)PTR_SEG_TO_LIN(className) );
353 else fprintf( stderr, "%04x\n", LOWORD(className) );
354 return 0;
357 /* Correct the window style */
359 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
360 style |= WS_CAPTION | WS_CLIPSIBLINGS;
361 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
363 /* Create the window structure */
365 hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
366 if (!hwnd) {
367 dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
368 return 0;
371 /* Fill the structure */
373 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
374 wndPtr->hwndNext = 0;
375 wndPtr->hwndChild = 0;
376 wndPtr->window = 0;
377 wndPtr->dwMagic = WND_MAGIC;
378 wndPtr->hwndParent = (style & WS_CHILD) ? parent : hwndDesktop;
379 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
380 wndPtr->hClass = class;
381 wndPtr->hInstance = instance;
382 wndPtr->ptIconPos.x = -1;
383 wndPtr->ptIconPos.y = -1;
384 wndPtr->ptMaxPos.x = -1;
385 wndPtr->ptMaxPos.y = -1;
386 wndPtr->hmemTaskQ = GetTaskQueue(0);
387 wndPtr->hrgnUpdate = 0;
388 wndPtr->hwndPrevActive = 0;
389 wndPtr->hwndLastActive = hwnd;
390 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
391 wndPtr->dwStyle = style & ~WS_VISIBLE;
392 wndPtr->dwExStyle = exStyle;
393 wndPtr->wIDmenu = 0;
394 wndPtr->hText = 0;
395 wndPtr->flags = 0;
396 wndPtr->hVScroll = 0;
397 wndPtr->hHScroll = 0;
398 wndPtr->hSysMenu = 0;
399 wndPtr->hProp = 0;
401 if (classPtr->wc.cbWndExtra)
402 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
403 classPtr->cWindows++;
405 /* Get class or window DC if needed */
407 if (classPtr->wc.style & CS_OWNDC)
408 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
409 else if (classPtr->wc.style & CS_CLASSDC)
410 wndPtr->hdce = classPtr->hdce;
411 else
412 wndPtr->hdce = 0;
414 /* Insert the window in the linked list */
416 WIN_LinkWindow( hwnd, HWND_TOP );
418 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
420 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
422 if (maxSize.x < width) width = maxSize.x;
423 if (maxSize.y < height) height = maxSize.y;
424 if (width <= 0) width = 1;
425 if (height <= 0) height = 1;
427 wndPtr->rectWindow.left = x;
428 wndPtr->rectWindow.top = y;
429 wndPtr->rectWindow.right = x + width;
430 wndPtr->rectWindow.bottom = y + height;
431 wndPtr->rectClient = wndPtr->rectWindow;
432 wndPtr->rectNormal = wndPtr->rectWindow;
434 /* Create the X window (only for top-level windows, and then only */
435 /* when there's no desktop window) */
437 if (!(style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
439 CURSORALLOC *cursor;
440 HCURSOR hCursor = classPtr->wc.hCursor;
441 if (!hCursor) hCursor = LoadCursor( 0, IDC_ARROW );
442 cursor = (CURSORALLOC *) GlobalLock(hCursor);
444 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
445 PointerMotionMask | ButtonPressMask |
446 ButtonReleaseMask | FocusChangeMask;
447 win_attr.override_redirect = TRUE;
448 win_attr.colormap = COLOR_WinColormap;
449 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
450 win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
451 win_attr.cursor = cursor ? cursor->xcursor : None;
452 wndPtr->window = XCreateWindow( display, rootWindow, x, y,
453 width, height, 0, CopyFromParent,
454 InputOutput, CopyFromParent,
455 CWEventMask | CWOverrideRedirect |
456 CWColormap | CWCursor | CWSaveUnder |
457 CWBackingStore, &win_attr );
458 XStoreName( display, wndPtr->window, PTR_SEG_TO_LIN(windowName) );
459 EVENT_RegisterWindow( wndPtr->window, hwnd );
460 GlobalUnlock( hCursor );
463 if ((style & WS_CAPTION) && !(style & WS_CHILD))
465 if (menu) SetMenu(hwnd, menu);
466 else if (classPtr->wc.lpszMenuName)
467 SetMenu( hwnd, LoadMenu( instance, classPtr->wc.lpszMenuName ) );
469 else wndPtr->wIDmenu = menu;
471 /* Send the WM_CREATE message */
473 createStruct.lpCreateParams = (LPSTR)data;
474 createStruct.hInstance = instance;
475 createStruct.hMenu = menu;
476 createStruct.hwndParent = parent;
477 createStruct.cx = width;
478 createStruct.cy = height;
479 createStruct.x = x;
480 createStruct.y = y;
481 createStruct.style = style;
482 createStruct.lpszName = windowName;
483 createStruct.lpszClass = className;
484 createStruct.dwExStyle = 0;
486 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, MAKE_SEGPTR(&createStruct) );
487 if (!wmcreate)
489 dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
490 wmcreate = -1;
492 else
494 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
495 NULL, NULL, NULL, &wndPtr->rectClient );
496 wmcreate = SendMessage(hwnd, WM_CREATE, 0, MAKE_SEGPTR(&createStruct));
499 if (wmcreate == -1)
501 /* Abort window creation */
502 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
503 WIN_DestroyWindow( hwnd );
504 return 0;
507 /* Create a copy of SysMenu */
508 if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
510 WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
512 /* Show the window, maximizing or minimizing if needed */
514 if (wndPtr->dwStyle & WS_MINIMIZE)
516 wndPtr->dwStyle &= ~WS_MAXIMIZE;
517 WINPOS_FindIconPos( hwnd );
518 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
519 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
520 SWP_FRAMECHANGED |
521 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
523 else if (wndPtr->dwStyle & WS_MAXIMIZE)
525 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
526 SWP_FRAMECHANGED |
527 (style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
529 else if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
531 dprintf_win(stddeb, "CreateWindowEx: return %04X \n", hwnd);
532 return hwnd;
536 /***********************************************************************
537 * DestroyWindow (USER.53)
539 BOOL DestroyWindow( HWND hwnd )
541 WND * wndPtr;
542 CLASS * classPtr;
544 dprintf_win(stddeb, "DestroyWindow (%04x)\n", hwnd);
546 /* Initialisation */
548 if (hwnd == hwndDesktop) return FALSE; /* Can't destroy desktop */
549 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
550 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
552 /* Hide the window */
554 if (wndPtr->dwStyle & WS_VISIBLE)
555 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
556 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
557 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
558 ReleaseCapture();
559 WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
561 /* Recursively destroy owned windows */
563 for (;;)
565 HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
566 while (hwndSibling)
568 WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
569 if (siblingPtr->hwndOwner == hwnd) break;
570 hwndSibling = siblingPtr->hwndNext;
572 if (hwndSibling) DestroyWindow( hwndSibling );
573 else break;
576 /* Send destroy messages and destroy children */
578 SendMessage( hwnd, WM_DESTROY, 0, 0 );
579 while (wndPtr->hwndChild) /* The child removes itself from the list */
580 DestroyWindow( wndPtr->hwndChild );
581 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
583 /* Destroy the window */
585 WIN_DestroyWindow( hwnd );
586 return TRUE;
590 /***********************************************************************
591 * CloseWindow (USER.43)
593 void CloseWindow(HWND hWnd)
595 WND * wndPtr = WIN_FindWndPtr(hWnd);
596 if (wndPtr->dwStyle & WS_CHILD) return;
597 ShowWindow(hWnd, SW_MINIMIZE);
601 /***********************************************************************
602 * OpenIcon (USER.44)
604 BOOL OpenIcon(HWND hWnd)
606 if (!IsIconic(hWnd)) return FALSE;
607 ShowWindow(hWnd, SW_SHOWNORMAL);
608 return(TRUE);
612 /***********************************************************************
613 * FindWindow (USER.50)
615 HWND FindWindow( SEGPTR ClassMatch, LPSTR TitleMatch )
617 HCLASS hclass;
618 CLASS *classPtr;
619 HWND hwnd;
621 if (ClassMatch)
623 hclass = CLASS_FindClassByName( ClassMatch, 0xffff, &classPtr );
624 if (!hclass) return 0;
626 else hclass = 0;
628 hwnd = GetTopWindow( hwndDesktop );
629 while(hwnd)
631 WND *wndPtr = WIN_FindWndPtr( hwnd );
632 if (!hclass || (wndPtr->hClass == hclass))
634 /* Found matching class */
635 if (!TitleMatch) return hwnd;
636 if (wndPtr->hText)
638 char *textPtr = (char *) USER_HEAP_LIN_ADDR( wndPtr->hText );
639 if (!strcmp( textPtr, TitleMatch )) return hwnd;
642 hwnd = wndPtr->hwndNext;
644 return 0;
648 /**********************************************************************
649 * GetDesktopWindow (USER.286)
650 * GetDeskTopHwnd (USER.278)
652 HWND GetDesktopWindow(void)
654 return hwndDesktop;
658 /*******************************************************************
659 * EnableWindow (USER.34)
661 BOOL EnableWindow( HWND hwnd, BOOL enable )
663 WND *wndPtr;
665 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
666 if (enable && (wndPtr->dwStyle & WS_DISABLED))
668 /* Enable window */
669 wndPtr->dwStyle &= ~WS_DISABLED;
670 SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
671 return TRUE;
673 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
675 /* Disable window */
676 wndPtr->dwStyle |= WS_DISABLED;
677 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
678 SetFocus( 0 ); /* A disabled window can't have the focus */
679 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
680 ReleaseCapture(); /* A disabled window can't capture the mouse */
681 SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
682 return FALSE;
684 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
688 /***********************************************************************
689 * IsWindowEnabled (USER.35)
691 BOOL IsWindowEnabled(HWND hWnd)
693 WND * wndPtr;
695 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
696 return !(wndPtr->dwStyle & WS_DISABLED);
700 /**********************************************************************
701 * GetWindowWord (USER.133)
703 WORD GetWindowWord( HWND hwnd, short offset )
705 WND * wndPtr = WIN_FindWndPtr( hwnd );
706 if (!wndPtr) return 0;
707 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
708 switch(offset)
710 case GWW_ID: return wndPtr->wIDmenu;
711 case GWW_HWNDPARENT: return wndPtr->hwndParent;
712 case GWW_HINSTANCE: return wndPtr->hInstance;
714 return 0;
718 /**********************************************************************
719 * SetWindowWord (USER.134)
721 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
723 WORD *ptr, retval;
724 WND * wndPtr = WIN_FindWndPtr( hwnd );
725 if (!wndPtr) return 0;
726 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
727 else switch(offset)
729 case GWW_ID: ptr = &wndPtr->wIDmenu; break;
730 case GWW_HINSTANCE: ptr = &wndPtr->hInstance; break;
731 default: return 0;
733 retval = *ptr;
734 *ptr = newval;
735 return retval;
739 /**********************************************************************
740 * GetWindowLong (USER.135)
742 LONG GetWindowLong( HWND hwnd, short offset )
744 WND * wndPtr = WIN_FindWndPtr( hwnd );
745 if (!wndPtr) return 0;
746 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
747 switch(offset)
749 case GWL_STYLE: return wndPtr->dwStyle;
750 case GWL_EXSTYLE: return wndPtr->dwExStyle;
751 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
753 return 0;
757 /**********************************************************************
758 * SetWindowLong (USER.136)
760 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
762 LONG *ptr, retval;
763 WND * wndPtr = WIN_FindWndPtr( hwnd );
764 if (!wndPtr) return 0;
765 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
766 else switch(offset)
768 case GWL_STYLE: ptr = &wndPtr->dwStyle; break;
769 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
770 case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
771 default: return 0;
773 retval = *ptr;
774 *ptr = newval;
775 return retval;
779 /*******************************************************************
780 * GetWindowText (USER.36)
782 int WIN16_GetWindowText( HWND hwnd, SEGPTR lpString, int nMaxCount )
784 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
785 (DWORD)lpString);
788 int GetWindowText( HWND hwnd, LPSTR lpString, int nMaxCount )
790 int len;
791 HANDLE handle;
793 /* We have to allocate a buffer on the USER heap */
794 /* to be able to pass its address to 16-bit code */
795 if (!(handle = USER_HEAP_ALLOC( nMaxCount ))) return 0;
796 len = (int)SendMessage( hwnd, WM_GETTEXT, (WORD)nMaxCount,
797 USER_HEAP_SEG_ADDR(handle) );
798 strncpy( lpString, USER_HEAP_LIN_ADDR(handle), nMaxCount );
799 USER_HEAP_FREE( handle );
800 return len;
804 /*******************************************************************
805 * SetWindowText (USER.37)
807 void WIN16_SetWindowText( HWND hwnd, SEGPTR lpString )
809 SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
812 void SetWindowText( HWND hwnd, LPSTR lpString )
814 HANDLE handle;
816 /* We have to allocate a buffer on the USER heap */
817 /* to be able to pass its address to 16-bit code */
818 if (!(handle = USER_HEAP_ALLOC( strlen(lpString)+1 ))) return;
819 strcpy( USER_HEAP_LIN_ADDR(handle), lpString );
820 SendMessage( hwnd, WM_SETTEXT, 0, USER_HEAP_SEG_ADDR(handle) );
821 USER_HEAP_FREE( handle );
825 /*******************************************************************
826 * GetWindowTextLength (USER.38)
828 int GetWindowTextLength(HWND hwnd)
830 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0 );
834 /*******************************************************************
835 * IsWindow (USER.47)
837 BOOL IsWindow( HWND hwnd )
839 WND * wndPtr = WIN_FindWndPtr( hwnd );
840 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
844 /*****************************************************************
845 * GetParent (USER.46)
847 HWND GetParent(HWND hwnd)
849 WND *wndPtr = WIN_FindWndPtr(hwnd);
850 if (!wndPtr) return 0;
851 return (wndPtr->dwStyle & WS_CHILD) ?
852 wndPtr->hwndParent : wndPtr->hwndOwner;
856 /*****************************************************************
857 * WIN_GetTopParent
859 * Get the top-level parent for a child window.
861 HWND WIN_GetTopParent( HWND hwnd )
863 while (hwnd)
865 WND *wndPtr = WIN_FindWndPtr( hwnd );
866 if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
867 else break;
869 return hwnd;
873 /*****************************************************************
874 * SetParent (USER.233)
876 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
878 HWND temp;
880 WND *wndPtr = WIN_FindWndPtr(hwndChild);
881 if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
883 temp = wndPtr->hwndParent;
885 WIN_UnlinkWindow(hwndChild);
886 if (hwndNewParent)
887 wndPtr->hwndParent = hwndNewParent;
888 else
889 wndPtr->hwndParent = GetDesktopWindow();
890 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
892 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
894 return temp;
899 /*******************************************************************
900 * IsChild (USER.48)
902 BOOL IsChild( HWND parent, HWND child )
904 WND * wndPtr = WIN_FindWndPtr( child );
905 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
907 if (wndPtr->hwndParent == parent) return TRUE;
908 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
910 return FALSE;
914 /***********************************************************************
915 * IsWindowVisible (USER.49)
917 BOOL IsWindowVisible( HWND hwnd )
919 WND *wndPtr = WIN_FindWndPtr( hwnd );
920 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
922 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
923 wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
925 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
930 /*******************************************************************
931 * GetTopWindow (USER.229)
933 HWND GetTopWindow( HWND hwnd )
935 WND * wndPtr = WIN_FindWndPtr( hwnd );
936 if (wndPtr) return wndPtr->hwndChild;
937 else return 0;
941 /*******************************************************************
942 * GetWindow (USER.262)
944 HWND GetWindow( HWND hwnd, WORD rel )
946 WND * wndPtr = WIN_FindWndPtr( hwnd );
947 if (!wndPtr) return 0;
948 switch(rel)
950 case GW_HWNDFIRST:
951 if (wndPtr->hwndParent)
953 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
954 return parentPtr->hwndChild;
956 else return 0;
958 case GW_HWNDLAST:
959 if (!wndPtr->hwndParent) return 0; /* Desktop window */
960 while (wndPtr->hwndNext)
962 hwnd = wndPtr->hwndNext;
963 wndPtr = WIN_FindWndPtr( hwnd );
965 return hwnd;
967 case GW_HWNDNEXT:
968 return wndPtr->hwndNext;
970 case GW_HWNDPREV:
972 HWND hwndPrev;
974 if (wndPtr->hwndParent)
976 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
977 hwndPrev = parentPtr->hwndChild;
979 else return 0; /* Desktop window */
980 if (hwndPrev == hwnd) return 0;
981 while (hwndPrev)
983 wndPtr = WIN_FindWndPtr( hwndPrev );
984 if (wndPtr->hwndNext == hwnd) break;
985 hwndPrev = wndPtr->hwndNext;
987 return hwndPrev;
990 case GW_OWNER:
991 return wndPtr->hwndOwner;
993 case GW_CHILD:
994 return wndPtr->hwndChild;
996 return 0;
1000 /*******************************************************************
1001 * GetNextWindow (USER.230)
1003 HWND GetNextWindow( HWND hwnd, WORD flag )
1005 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1006 return GetWindow( hwnd, flag );
1009 /*******************************************************************
1010 * ShowOwnedPopups (USER.265)
1012 void ShowOwnedPopups( HWND owner, BOOL fShow )
1014 HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
1015 while (hwnd)
1017 WND *wnd = WIN_FindWndPtr(hwnd);
1018 if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
1019 ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
1020 hwnd = wnd->hwndNext;
1025 /*******************************************************************
1026 * GetLastActivePopup (USER.287)
1028 HWND GetLastActivePopup(HWND hwnd)
1030 WND *wndPtr;
1031 wndPtr = WIN_FindWndPtr(hwnd);
1032 if (wndPtr == NULL) return hwnd;
1033 return wndPtr->hwndLastActive;
1037 /*******************************************************************
1038 * EnumWindows (USER.54)
1040 BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
1042 HWND hwnd;
1043 WND *wndPtr;
1044 HWND *list, *pWnd;
1045 int count;
1047 /* We have to build a list of all windows first, to avoid */
1048 /* unpleasant side-effects, for instance if the callback */
1049 /* function changes the Z-order of the windows. */
1051 /* First count the windows */
1053 count = 0;
1054 for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
1056 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1057 count++;
1059 if (!count) return TRUE;
1061 /* Now build the list of all windows */
1063 if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
1064 for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
1066 wndPtr = WIN_FindWndPtr( hwnd );
1067 *pWnd++ = hwnd;
1070 /* Now call the callback function for every window */
1072 for (pWnd = list; count > 0; count--, pWnd++)
1074 /* Make sure that window still exists */
1075 if (!IsWindow(*pWnd)) continue;
1076 if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
1078 free( list );
1079 return TRUE;
1083 /**********************************************************************
1084 * EnumTaskWindows (USER.225)
1086 BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
1088 HWND hwnd;
1089 WND *wndPtr;
1090 HWND *list, *pWnd;
1091 HANDLE hQueue = GetTaskQueue( hTask );
1092 int count;
1094 /* This function is the same as EnumWindows(), */
1095 /* except for an added check on the window queue. */
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 if (wndPtr->hmemTaskQ == hQueue) 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 if (wndPtr->hmemTaskQ == hQueue) *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 (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
1124 free( list );
1125 return TRUE;
1129 /*******************************************************************
1130 * WIN_EnumChildWin
1132 * o hwnd is the first child to use, loop until all next windows
1133 * are processed
1135 * o call wdnenumprc
1137 * o call ourselves with the next child window
1140 static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1142 WND *wndPtr;
1144 while (hwnd)
1146 if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
1147 if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
1148 if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
1149 hwnd=wndPtr->hwndNext;
1151 return 1;
1154 /*******************************************************************
1155 * EnumChildWindows (USER.55)
1157 * o gets the first child of hwnd
1159 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1161 BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
1163 WND *wndPtr;
1165 dprintf_enum(stddeb,"EnumChildWindows\n");
1167 if (hwnd == 0) return 0;
1168 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1169 hwnd = wndPtr->hwndChild;
1170 return WIN_EnumChildWin(hwnd, wndenumprc, lParam);
1174 /*******************************************************************
1175 * AnyPopup [USER.52]
1177 BOOL AnyPopup()
1179 dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
1180 return FALSE;
1183 /*******************************************************************
1184 * FlashWindow [USER.105]
1186 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1188 dprintf_win(stdnimp,"EMPTY STUB !! FlashWindow !\n");
1189 return FALSE;
1193 /*******************************************************************
1194 * SetSysModalWindow [USER.188]
1196 HWND SetSysModalWindow(HWND hWnd)
1198 HWND hWndOldModal = hWndSysModal;
1199 hWndSysModal = hWnd;
1200 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04X) !\n", hWnd);
1201 return hWndOldModal;
1205 /*******************************************************************
1206 * GetSysModalWindow [USER.189]
1208 HWND GetSysModalWindow(void)
1210 return hWndSysModal;