/*
 * This file is part of the WebKit project.
 *
 * Copyright (C) 2006 Apple Computer, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "RenderThemeWin.h"

#include <cairo-win32.h>
#include "Document.h"
#include "GraphicsContext.h"

/* 
 * The following constants are used to determine how a widget is drawn using
 * Windows' Theme API. For more information on theme parts and states see
 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
 */
#define THEME_COLOR 204
#define THEME_FONT  210

// Generic state constants
#define TS_NORMAL    1
#define TS_HOVER     2
#define TS_ACTIVE    3
#define TS_DISABLED  4
#define TS_FOCUSED   5

// Button constants
#define BP_BUTTON    1
#define BP_RADIO     2
#define BP_CHECKBOX  3

// Textfield constants
#define TFP_TEXTFIELD 1
#define TFS_READONLY  6

// Combobox constants
#define CP_DROPDOWNBUTTON 1

typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme);
typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId, 
                                          int iStateId, const RECT *pRect,
                                          const RECT* pClipRect);
typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId, 
                                          int iStateId, const RECT *pRect,
                                          unsigned uEdge, unsigned uFlags,
                                          const RECT* pClipRect);
typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
                                          int iStateId, const RECT* pRect,
                                          RECT* pContentRect);
typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
                                       int iStateId, RECT* prc, int ts,
                                       SIZE* psz);
typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
                                   int iStateId, int iPropId, OUT COLORREF* pFont);

static openThemeDataPtr openTheme = 0;
static closeThemeDataPtr closeTheme = 0;
static drawThemeBackgroundPtr drawThemeBG = 0;
static drawThemeEdgePtr drawThemeEdge = 0;
static getThemeContentRectPtr getThemeContentRect = 0;
static getThemePartSizePtr getThemePartSize = 0;
static getThemeSysFontPtr getThemeSysFont = 0;
static getThemeColorPtr getThemeColor = 0;

namespace WebCore {

RenderTheme* theme()
{
    static RenderThemeWin winTheme;
    return &winTheme;
}

RenderThemeWin::RenderThemeWin()
:m_themeDLL(0), m_buttonTheme(0), m_textFieldTheme(0), m_menuListTheme(0)
{
    m_themeDLL = ::LoadLibrary(L"uxtheme.dll");
    if (m_themeDLL) {
        openTheme = (openThemeDataPtr)GetProcAddress(m_themeDLL, "OpenThemeData");
        closeTheme = (closeThemeDataPtr)GetProcAddress(m_themeDLL, "CloseThemeData");
        drawThemeBG = (drawThemeBackgroundPtr)GetProcAddress(m_themeDLL, "DrawThemeBackground");
        drawThemeEdge = (drawThemeEdgePtr)GetProcAddress(m_themeDLL, "DrawThemeEdge");
        getThemeContentRect = (getThemeContentRectPtr)GetProcAddress(m_themeDLL, "GetThemeBackgroundContentRect");
        getThemePartSize = (getThemePartSizePtr)GetProcAddress(m_themeDLL, "GetThemePartSize");
        getThemeSysFont = (getThemeSysFontPtr)GetProcAddress(m_themeDLL, "GetThemeSysFont");
        getThemeColor = (getThemeColorPtr)GetProcAddress(m_themeDLL, "GetThemeColor");
    }
}

RenderThemeWin::~RenderThemeWin()
{
    if (!m_themeDLL)
        return;

    close();

    ::FreeLibrary(m_themeDLL);
}

void RenderThemeWin::close()
{
    // This method will need to be called when the OS theme changes to flush our cached themes.
    if (m_buttonTheme)
        closeTheme(m_buttonTheme);
    if (m_textFieldTheme)
        closeTheme(m_textFieldTheme);
    if (m_menuListTheme)
        closeTheme(m_menuListTheme);
    m_buttonTheme = m_textFieldTheme = m_menuListTheme = 0;
}

Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
{
    COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}

Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
{
    COLORREF color = GetSysColor(COLOR_GRAYTEXT);
    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}

Color RenderThemeWin::platformActiveSelectionForegroundColor() const
{
    COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}

Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
{
    return Color::white;
}

bool RenderThemeWin::supportsFocus(EAppearance appearance)
{
    switch (appearance) {
        case PushButtonAppearance:
        case DefaultButtonAppearance:
        case ButtonAppearance:
        case TextFieldAppearance:
        case TextAreaAppearance:
            return true;
        default:
            return false;
    }

    return false;
}

unsigned RenderThemeWin::determineState(RenderObject* o)
{
    unsigned result = TS_NORMAL;
    if (!isEnabled(o))
        result = TS_DISABLED;
    else if (isReadOnlyControl(o))
        result = TFS_READONLY; // Readonly is supported on textfields.
    else if (supportsFocus(o->style()->appearance()) && isFocused(o))
        result = TS_FOCUSED;
    else if (isPressed(o)) // Active overrides hover.
        result = TS_ACTIVE;
    else if (isHovered(o))
        result = TS_HOVER;
    if (isChecked(o))
        result += 4; // 4 unchecked states, 4 checked states.
    return result;
}

unsigned RenderThemeWin::determineClassicState(RenderObject* o)
{
    unsigned result = 0;
    if (!isEnabled(o) || isReadOnlyControl(o))
        result = DFCS_INACTIVE;
    else if (isPressed(o)) // Active supersedes hover
        result = DFCS_PUSHED;
    else if (isHovered(o))
        result = DFCS_HOT;
    if (isChecked(o))
        result |= DFCS_CHECKED;
    return result;
}

ThemeData RenderThemeWin::getThemeData(RenderObject* o)
{
    ThemeData result;
    switch (o->style()->appearance()) {
        case PushButtonAppearance:
        case ButtonAppearance:
            result.m_part = BP_BUTTON;
            result.m_classicState = DFCS_BUTTONPUSH;
            break;
        case CheckboxAppearance:
            result.m_part = BP_CHECKBOX;
            result.m_classicState = DFCS_BUTTONCHECK;
            break;
        case RadioAppearance:
            result.m_part = BP_RADIO;
            result.m_classicState = DFCS_BUTTONRADIO;
            break;
        case ListboxAppearance:
        case MenulistAppearance:
        case TextFieldAppearance:
        case TextAreaAppearance:
            result.m_part = TFP_TEXTFIELD;
            break;
    }

    result.m_state = determineState(o);
    result.m_classicState |= determineClassicState(o);

    return result;
}

// May need to add stuff to these later, so keep the graphics context retrieval/release in some helpers.
static HDC prepareForDrawing(GraphicsContext* g)
{
    return g->getWindowsContext();
}
 
static void doneDrawing(GraphicsContext* g, HDC hdc)
{
    g->releaseWindowsContext(hdc);
}

bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
    // Get the correct theme data for a button
    ThemeData themeData = getThemeData(o);

    // Now paint the button.
    HDC hdc = prepareForDrawing(i.context);  
    RECT widgetRect = r;
    if (m_themeDLL && !m_buttonTheme)
        m_buttonTheme = openTheme(0, L"Button");
    if (m_buttonTheme && drawThemeBG) {
        drawThemeBG(m_buttonTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
    } else {
        if ((themeData.m_part == BP_BUTTON) && isFocused(o)) {
            // Draw black focus rect around button outer edge
            HBRUSH brush = GetSysColorBrush(COLOR_3DDKSHADOW);
            if (brush) {
                FrameRect(hdc, &widgetRect, brush);
                InflateRect(&widgetRect, -1, -1);
            }
        }
        DrawFrameControl(hdc, &widgetRect, DFC_BUTTON, themeData.m_classicState);
        if ((themeData.m_part != BP_BUTTON) && isFocused(o)) {
            DrawFocusRect(hdc, &widgetRect);
        }
    }
    doneDrawing(i.context, hdc);

    return false;
}

void RenderThemeWin::setCheckboxSize(RenderStyle* style) const
{
    // If the width and height are both specified, then we have nothing to do.
    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
        return;

    // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary for now.  It matches Firefox.
    // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
    // the higher DPI.  Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
    // metrics.
    if (style->width().isIntrinsicOrAuto())
        style->setWidth(Length(13, Fixed));
    if (style->height().isAuto())
        style->setHeight(Length(13, Fixed));
}

bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
    // Get the correct theme data for a textfield
    ThemeData themeData = getThemeData(o);

    // Now paint the text field.
    HDC hdc = prepareForDrawing(i.context);
    RECT widgetRect = r;
    if (m_themeDLL && !m_textFieldTheme)
        m_textFieldTheme = openTheme(0, L"Edit");
    if (m_textFieldTheme && drawThemeBG) {
        drawThemeBG(m_textFieldTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
    } else {
        DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
        FillRect(hdc, &widgetRect, reinterpret_cast<HBRUSH>(((themeData.m_classicState & DFCS_INACTIVE) ? COLOR_BTNFACE : COLOR_WINDOW) + 1));
    }
    doneDrawing(i.context, hdc);

    return false;
}

void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
    // Height is locked to auto.
    style->setHeight(Length(Auto));

    // White-space is locked to pre
    style->setWhiteSpace(PRE);

    // Add in the padding that we'd like to use.
    const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
    style->setPaddingLeft(Length(2, Fixed));
    style->setPaddingRight(Length(buttonWidth + 2, Fixed));
    style->setPaddingTop(Length(1, Fixed));
    style->setPaddingBottom(Length(1, Fixed));
}

bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
    // FIXME: All these inflate() calls are bogus, causing painting problems,
    // as well as sizing wackiness in Classic mode
    IntRect editRect(r);
    paintTextField(o, i, editRect);

    const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
    IntRect buttonRect(r.right() - buttonWidth - 1, r.y(), buttonWidth, r.height());
    buttonRect.inflateY(-1);
    paintMenuListButton(o, i, buttonRect);

    return false;
}

bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
    HDC hdc = prepareForDrawing(i.context);
    RECT widgetRect = r;
    if (m_themeDLL && !m_menuListTheme)
        m_menuListTheme = openTheme(0, L"Combobox");
    if (m_menuListTheme && drawThemeBG)
        drawThemeBG(m_menuListTheme, hdc, CP_DROPDOWNBUTTON, determineState(o), &widgetRect, NULL);
    else
        DrawFrameControl(hdc, &widgetRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(o));
    doneDrawing(i.context, hdc);

    return false;
}

}
