/*
 * xcreatew.c --
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  Software Research
 * Associates makes no representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied
 * warranty.
 */
 
#include "xlibInt.h" 

/*
 *	XCreateWindow
 *
 */
 	
Window
XCreateWindow(Display *display, Window parent, int x, int y, UINT width, 
	UINT height, UINT border_width, int depth, UINT class, 
	Visual *visual, unsigned long valuemask, 
	XSetWindowAttributes *attributes)
{
    HWND child;
    DWORD dwStyle;
    XWindowChanges changes;
    BYTE byResult;

    display->request++;

    if (parent == NULL || attributes->override_redirect == True) {
        RECT rc;
    	if (attributes->override_redirect == True) {

	    dwStyle = WS_POPUP|WS_BORDER|WS_CLIPCHILDREN|CS_DBLCLKS;
;
	} else {
	    dwStyle = WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|CS_DBLCLKS;
	}
	child = CreateWindow("TopLevel", "", dwStyle, 
		attributes->override_redirect?x:CW_USEDEFAULT, 
		attributes->override_redirect?y:CW_USEDEFAULT, 
		AdjustWidth(width, attributes->override_redirect),
		AdjustHeight(height, attributes->override_redirect), 
    		parent, NULL, GetAppInstance(), NULL);
	GetWindowRect(child, &rc);
	y = ReAdjustY(rc.top, attributes->override_redirect);
	x = ReAdjustX(rc.left, attributes->override_redirect);
    } else {
	dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
	child = CreateWindow("Widget", "", dwStyle, x, y, width, height, 
    		parent, NULL, GetAppInstance(), NULL);
    }

    if (child == NULL) {
	postError(BadWindow, parent);
	return NULL;
    }

    byResult = _SetWindowAttributes(child, valuemask, attributes);
    if (byResult != Success) {
	goto destroy;
    }

    changes.x = x;
    changes.y = y;
    changes.width = width;
    changes.height = height;
    changes.border_width = border_width;
    byResult = _SetWindowChanges(child, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &changes);
    if (byResult != Success) {
	destroy:
	DestroyWindow(child);
	postError(byResult, parent);
	return NULL;
    }

    return child;
}

/* 
 *	XDestroyWindow
 *
 */

void  
XDestroyWindow(Display *display, Window hwnd)
{
    display->request++;

    if (DestroyWindow(hwnd) == 0) {
	postError(BadWindow, hwnd);
    }
    EnterLeave(hwnd, 0, 0, 1 /* windowMoved */);
}


/*
 *	XMapWindow
 *	
 *
 */

void	
XMapWindow(Display *display, Window w)
{
    HGLOBAL hGlobal;
    HGLOBAL hXWChanges;
    XWMHints *hPtr;
    XWindowChanges *pXWChanges;
    char propName[8];
    char *ptr;
    XWindowChanges changes;

    display->request++;

    sprintf(propName, "#0x%0.4x", XA_WM_HINTS);
    
    if ((hGlobal = GetProp(w, propName)) != NULL) {
	int state;
	long flags;

	ptr = ((char *) GlobalLock(hGlobal)) + sizeof(Atom);
	hPtr = (XWMHints *) ptr;
	flags = hPtr->flags;
	state = hPtr->initial_state;
	GlobalUnlock(hGlobal);
	if (flags & StateHint) {
	    switch (state) {
	    case NormalState:
		if (IsIconic(w)) {

		    hXWChanges = (HGLOBAL) GetWindowLong(w, XWCH_OFFSET);
		    pXWChanges = (XWindowChanges *) GlobalLock(hXWChanges);

		    /* If the window was moved while it was iconified,
		     * widthdraw it, reset its position, and then display
		     * it
		     */
		    if (pXWChanges->pos_changed) {

			changes.x = pXWChanges->x;
			changes.y = pXWChanges->y;
			changes.width = pXWChanges->width;
			changes.height = pXWChanges->height;
			ShowWindow(w, SW_SHOWNOACTIVATE);
		    }
		    ShowWindow(w, SW_SHOWNOACTIVATE);
		    GlobalUnlock(hXWChanges);

		    if (pXWChanges->pos_changed) {
			pXWChanges->pos_changed = FALSE;
			_SetWindowChanges(w, CWX|CWY|CWWidth|CWHeight,
					  &changes);
		    }
		    PostMessage(w, MAPNOTIFY, 0, 0L);
		    return;
		}
		goto normalmap;
	    case IconicState:
		ShowWindow(w, SW_SHOWMINNOACTIVE); break;
	    case WithdrawnState:
		ShowWindow(w, SW_HIDE); break;
	    }
	} 
    } else {	    	
	normalmap:
	ShowWindow(w, SW_SHOWNA);
	PostMessage(w, MAPNOTIFY, 0, 0L);
    }
}


/*
 *	XUnmapWindow
 *
 */

void  
XUnmapWindow(Display *display, Window hwnd)
{
    display->request++;

    ShowWindow(hwnd, SW_HIDE);
    PostMessage(hwnd, UNMAPNOTIFY, 0, 0L);
}

/*
 *	XIconifyWindow
 *
 */

Status
XIconifyWindow(Display *display, Window hwnd, int dummy2)
{
    display->request++;

    ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
    PostMessage(hwnd, UNMAPNOTIFY, 0, 0L);
    return 1;
}

/*
 *	XWithdrawWindow
 *
 */

Status
XWithdrawWindow(Display *display, Window hwnd, int dummy2)
{
    display->request++;

    ShowWindow(hwnd, SW_HIDE);
    PostMessage(hwnd, UNMAPNOTIFY, 0, 0L);
    return 1;
}

Window
XWindowFromPoint(Display *display, int x, int y)
{
    POINT p;
    Window w;

    display->request++;

    p.x = x;
    p.y = y;

    w = (Window) WindowFromPoint(p);
    return w;
}
