/*
 * icon.c ---
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * All rights reserved.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 */
#include "xlibInt.h"

typedef struct {
    Atom atomtype;
    int flags;
    Pixmap icon_pixmap;
    Pixmap icon_mask;
    HICON icon;			/* This is the icon specified by the user */
    HICON current_icon;		/* This is the current icon */
    HICON default_icon;		/* This is the default icon */
} WMIconInfo;

/*
 *----------------------------------------------------------------------
 * 
 * CreateXIconFromBitmaps --
 *
 *	Create an Icon from bitmaps that were created by GetBitmap
 *
 * Results:
 *	A Windows Icon handle
 *
 * Side Effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
static HICON
CreateXIconFromBitmaps(hinst, hbm, hbmmask)
    HINSTANCE hinst;
    HBITMAP hbm, hbmmask;
{
    HDC memDC, memDC2;
    HBITMAP cbm, cbmOld, cbmOld2;
    int width, height;
    char cbits[32*4], mbits[32*4];
    BITMAP info;
    int icon_width, icon_height;

    icon_width = GetSystemMetrics(SM_CXICON);
    icon_height = GetSystemMetrics(SM_CYICON);

    memDC = CreateCompatibleDC(NULL);
    SetMapMode(memDC, MM_TEXT);
    cbm = CreateCompatibleBitmap(memDC, icon_width, icon_height);
    cbmOld = SelectObject(memDC, cbm);
    if (hbm != 0) {
        memDC2 = CreateCompatibleDC(NULL);
        SetMapMode(memDC2, MM_TEXT);
        cbmOld2 = SelectObject(memDC2, hbm);
	GetObject(hbm, sizeof(BITMAP), &info);
	width = info.bmWidth;
	height = info.bmHeight;
        StretchBlt(memDC, 0, 0, icon_width, icon_height,
		   memDC2, 0, 0, width, height, SRCCOPY);
        SelectObject(memDC, cbmOld);
        SelectObject(memDC2, cbmOld2);
        DeleteDC(memDC2);
    }
    DeleteDC(memDC);
    GetBitmapBits(cbm, (icon_width/8)*icon_height, cbits);
    DeleteObject(cbm);

    memDC = CreateCompatibleDC(NULL);
    SetMapMode(memDC, MM_TEXT);
    cbm = CreateCompatibleBitmap(memDC, icon_width, icon_height);
    cbmOld = SelectObject(memDC, cbm);
    if (hbmmask != 0) {
        memDC2 = CreateCompatibleDC(NULL);
        SetMapMode(memDC2, MM_TEXT);
        cbmOld2 = SelectObject(memDC2, hbmmask);
	GetObject(hbmmask, sizeof(BITMAP), &info);
	width = info.bmWidth;
	height = info.bmHeight;
        StretchBlt(memDC, 0, 0, icon_width, icon_height,
		   memDC2, 0, 0, width, height, SRCCOPY);
        SelectObject(memDC, cbmOld);
        SelectObject(memDC2, cbmOld2);
        DeleteDC(memDC2);
    }
    DeleteDC(memDC);
    GetBitmapBits(cbm, (icon_width/8)*icon_height, mbits);
    DeleteObject(cbm);
    return CreateIcon(hinst, icon_width, icon_height,
		      1, 1, mbits, cbits);
}

/*
 *----------------------------------------------------------------------
 * 
 * GetXIcon --
 *
 *	For a given window, get the icon it is associated with
 *
 * Results:
 *	If an icon is associated with the window, the icon is
 *	returned.  Otherwise, NULL is returned.
 *
 * Side Effects:
 *	None
 *----------------------------------------------------------------------
 */
HICON
GetXIcon(Display *display, HWND hwnd)
{
    HGLOBAL hIconInfo;
    WMIconInfo *pIconInfo;
    HICON hicon;
    Atom atom;
    char propName[8];

    atom = XInternAtom(display, "WM_STATE", False);
    sprintf(propName, "#0x%0.4x", atom);
    hIconInfo = GetProp(hwnd, propName);
    if (hIconInfo == NULL) {
	return NULL;
    }
    pIconInfo = GlobalLock(hIconInfo);
    hicon = pIconInfo->current_icon;
    GlobalUnlock(hIconInfo);

    return hicon;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateXIcon --
 *
 *	For a given window, repaint its icon if the window is
 *	iconic.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
void
UpdateXIcon(Display *display, HWND hwnd)
{
    PAINTSTRUCT ps;
    HICON hicon;

    if (! IsIconic(hwnd)) {
	return;
    }
    hicon = GetXIcon(display, hwnd);

    InvalidateRect( hwnd, NULL, TRUE );
    BeginPaint( hwnd, (LPPAINTSTRUCT) &ps );
    SendMessage( hwnd, WM_ICONERASEBKGND, (WPARAM) ps.hdc, 0L );
    DrawIcon( ps.hdc, 2, 2, hicon);
    EndPaint( hwnd, (LPPAINTSTRUCT) &ps );
}
    
    
/*
 *----------------------------------------------------------------------
 *
 * SetXIcon --
 *
 *	For a given window, create the WMIconInfo structure 
 *	for the icon that is associated with the window.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
void
SetXIcon(Display *display, HWND hwnd, void *wmhints)
{
    HGLOBAL hIconInfo;
    WMIconInfo *pIconInfo;
    HINSTANCE hinst;
    XWMHints *hPtr = (XWMHints *) wmhints;
    Pixmap pixmap, mask, oldpixmap, oldmask;
    int oldflags, newflags;
    Atom atom;
    char propName[8];

    atom = XInternAtom(display, "WM_STATE", False);
    sprintf(propName, "#0x%0.4x", atom);

    hIconInfo = GetProp(hwnd, propName);
    if (hIconInfo == NULL) {
    	hIconInfo = GlobalAlloc(GHND, sizeof(WMIconInfo));
	SetProp(hwnd, propName, hIconInfo);

	pIconInfo = GlobalLock(hIconInfo);
	pIconInfo->atomtype = atom;
	pIconInfo->default_icon = LoadIcon(NULL, IDI_APPLICATION);
	pIconInfo->current_icon = pIconInfo->default_icon;
	GlobalUnlock(hIconInfo);
    }

    pIconInfo = GlobalLock(hIconInfo);
    oldflags = pIconInfo->flags;
    newflags = hPtr->flags;

    oldpixmap = (oldflags & IconPixmapHint) ?
	pIconInfo->icon_pixmap : pIconInfo->default_icon;
    pixmap = (newflags & IconPixmapHint) ?
	hPtr->icon_pixmap : pIconInfo->default_icon;

    oldmask = (oldflags & IconMaskHint) ?
	pIconInfo->icon_mask : 0;
    mask = (newflags & IconMaskHint) ? hPtr->icon_mask : 0;

#define ICON_CHANGE (IconPixmapHint|IconMaskHint)

    if (((oldflags & ICON_CHANGE) != (newflags & ICON_CHANGE)) ||
	(oldpixmap != pixmap) || (oldmask != mask))
    {
	if (pIconInfo->icon != pIconInfo->default_icon) {
	    DestroyIcon(pIconInfo->icon);
	}
	pIconInfo->icon = NULL;
	pIconInfo->icon_pixmap = 0;
	pIconInfo->icon_mask = 0;
	// pIconInfo->current_icon = pIconInfo->default_icon;
	// SetClassLong(hwnd, GCL_HICON, (LONG) pIconInfo->current_icon);
	
	hinst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
	pIconInfo->icon = pIconInfo->current_icon =
	    CreateXIconFromBitmaps(hinst, pixmap, mask);
	pIconInfo->icon_pixmap = pixmap;
	pIconInfo->icon_mask = mask;
	pIconInfo->flags = hPtr->flags;
	// SetClassLong(hwnd, GCL_HICON, (LONG) pIconInfo->icon);
    }

    GlobalUnlock(hIconInfo);
    UpdateXIcon(display, hwnd);
}

    
