/*
    This file is part of the WebKit open source project.
    This file has been generated by generate-bindings.pl. DO NOT MODIFY!

    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 "JSKeyboardEvent.h"

#include "JSDOMWindow.h"
#include "KURL.h"
#include "KeyboardEvent.h"
#include <runtime/Error.h>
#include <runtime/JSNumberCell.h>
#include <runtime/JSString.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

ASSERT_CLASS_FITS_IN_CELL(JSKeyboardEvent);

/* Hash table */

static const HashTableValue JSKeyboardEventTableValues[9] =
{
    { "keyIdentifier", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventKeyIdentifier), (intptr_t)0 },
    { "keyLocation", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventKeyLocation), (intptr_t)0 },
    { "ctrlKey", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventCtrlKey), (intptr_t)0 },
    { "shiftKey", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventShiftKey), (intptr_t)0 },
    { "altKey", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventAltKey), (intptr_t)0 },
    { "metaKey", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventMetaKey), (intptr_t)0 },
    { "altGraphKey", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventAltGraphKey), (intptr_t)0 },
    { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsKeyboardEventConstructor), (intptr_t)0 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSKeyboardEventTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 31, JSKeyboardEventTableValues, 0 };
#else
    { 18, 15, JSKeyboardEventTableValues, 0 };
#endif

/* Hash table for constructor */

static const HashTableValue JSKeyboardEventConstructorTableValues[1] =
{
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSKeyboardEventConstructorTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSKeyboardEventConstructorTableValues, 0 };
#else
    { 1, 0, JSKeyboardEventConstructorTableValues, 0 };
#endif

class JSKeyboardEventConstructor : public DOMConstructorObject {
public:
    JSKeyboardEventConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
        : DOMConstructorObject(JSKeyboardEventConstructor::createStructure(globalObject->objectPrototype()), globalObject)
    {
        putDirect(exec->propertyNames().prototype, JSKeyboardEventPrototype::self(exec, globalObject), None);
    }
    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    virtual const ClassInfo* classInfo() const { return &s_info; }
    static const ClassInfo s_info;

    static PassRefPtr<Structure> createStructure(JSValue proto) 
    { 
        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
    }
    
protected:
    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags;
};

const ClassInfo JSKeyboardEventConstructor::s_info = { "KeyboardEventConstructor", 0, &JSKeyboardEventConstructorTable, 0 };

bool JSKeyboardEventConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSKeyboardEventConstructor, DOMObject>(exec, &JSKeyboardEventConstructorTable, this, propertyName, slot);
}

bool JSKeyboardEventConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSKeyboardEventConstructor, DOMObject>(exec, &JSKeyboardEventConstructorTable, this, propertyName, descriptor);
}

/* Hash table for prototype */

static const HashTableValue JSKeyboardEventPrototypeTableValues[2] =
{
    { "initKeyboardEvent", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsKeyboardEventPrototypeFunctionInitKeyboardEvent), (intptr_t)11 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSKeyboardEventPrototypeTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSKeyboardEventPrototypeTableValues, 0 };
#else
    { 2, 1, JSKeyboardEventPrototypeTableValues, 0 };
#endif

const ClassInfo JSKeyboardEventPrototype::s_info = { "KeyboardEventPrototype", 0, &JSKeyboardEventPrototypeTable, 0 };

JSObject* JSKeyboardEventPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSKeyboardEvent>(exec, globalObject);
}

bool JSKeyboardEventPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticFunctionSlot<JSObject>(exec, &JSKeyboardEventPrototypeTable, this, propertyName, slot);
}

bool JSKeyboardEventPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticFunctionDescriptor<JSObject>(exec, &JSKeyboardEventPrototypeTable, this, propertyName, descriptor);
}

const ClassInfo JSKeyboardEvent::s_info = { "KeyboardEvent", &JSUIEvent::s_info, &JSKeyboardEventTable, 0 };

JSKeyboardEvent::JSKeyboardEvent(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<KeyboardEvent> impl)
    : JSUIEvent(structure, globalObject, impl)
{
}

JSObject* JSKeyboardEvent::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
{
    return new (exec) JSKeyboardEventPrototype(JSKeyboardEventPrototype::createStructure(JSUIEventPrototype::self(exec, globalObject)));
}

bool JSKeyboardEvent::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSKeyboardEvent, Base>(exec, &JSKeyboardEventTable, this, propertyName, slot);
}

bool JSKeyboardEvent::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSKeyboardEvent, Base>(exec, &JSKeyboardEventTable, this, propertyName, descriptor);
}

JSValue jsKeyboardEventKeyIdentifier(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsString(exec, imp->keyIdentifier());
    return result;
}

JSValue jsKeyboardEventKeyLocation(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsNumber(exec, imp->keyLocation());
    return result;
}

JSValue jsKeyboardEventCtrlKey(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsBoolean(imp->ctrlKey());
    return result;
}

JSValue jsKeyboardEventShiftKey(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsBoolean(imp->shiftKey());
    return result;
}

JSValue jsKeyboardEventAltKey(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsBoolean(imp->altKey());
    return result;
}

JSValue jsKeyboardEventMetaKey(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsBoolean(imp->metaKey());
    return result;
}

JSValue jsKeyboardEventAltGraphKey(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* castedThis = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThis->impl());
    JSValue result = jsBoolean(imp->altGraphKey());
    return result;
}

JSValue jsKeyboardEventConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSKeyboardEvent* domObject = static_cast<JSKeyboardEvent*>(asObject(slotBase));
    return JSKeyboardEvent::getConstructor(exec, domObject->globalObject());
}
JSValue JSKeyboardEvent::getConstructor(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSKeyboardEventConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));
}

JSValue JSC_HOST_CALL jsKeyboardEventPrototypeFunctionInitKeyboardEvent(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSKeyboardEvent::s_info))
        return throwError(exec, TypeError);
    JSKeyboardEvent* castedThisObj = static_cast<JSKeyboardEvent*>(asObject(thisValue));
    KeyboardEvent* imp = static_cast<KeyboardEvent*>(castedThisObj->impl());
    const UString& type = args.at(0).toString(exec);
    bool canBubble = args.at(1).toBoolean(exec);
    bool cancelable = args.at(2).toBoolean(exec);
    DOMWindow* view = toDOMWindow(args.at(3));
    const UString& keyIdentifier = args.at(4).toString(exec);
    unsigned keyLocation = args.at(5).toInt32(exec);
    bool ctrlKey = args.at(6).toBoolean(exec);
    bool altKey = args.at(7).toBoolean(exec);
    bool shiftKey = args.at(8).toBoolean(exec);
    bool metaKey = args.at(9).toBoolean(exec);
    bool altGraphKey = args.at(10).toBoolean(exec);

    imp->initKeyboardEvent(type, canBubble, cancelable, view, keyIdentifier, keyLocation, ctrlKey, altKey, shiftKey, metaKey, altGraphKey);
    return jsUndefined();
}


}
