/*
 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"

#include <windowsx.h>
#include <zmouse.h>

#include "jlong.h"
#include "awt_AWTEvent.h"
#include "awt_BitmapUtil.h"
#include "awt_Component.h"
#include "awt_Cursor.h"
#include "awt_Dimension.h"
#include "awt_Frame.h"
#include "awt_InputEvent.h"
#include "awt_InputTextInfor.h"
#include "awt_Insets.h"
#include "awt_KeyEvent.h"
#include "awt_MenuItem.h"
#include "awt_MouseEvent.h"
#include "awt_Palette.h"
#include "awt_Toolkit.h"
#include "awt_Window.h"
#include "awt_Win32GraphicsDevice.h"
#include "Hashtable.h"
#include "ComCtl32Util.h"

#include <Region.h>

#include <jawt.h>

#include <java_awt_Toolkit.h>
#include <java_awt_FontMetrics.h>
#include <java_awt_Color.h>
#include <java_awt_Event.h>
#include <java_awt_event_KeyEvent.h>
#include <java_awt_Insets.h>
#include <sun_awt_windows_WPanelPeer.h>
#include <java_awt_event_InputEvent.h>
#include <java_awt_event_ActionEvent.h>
#include <java_awt_event_InputMethodEvent.h>
#include <sun_awt_windows_WInputMethod.h>
#include <java_awt_event_MouseEvent.h>
#include <java_awt_event_MouseWheelEvent.h>

// Begin -- Win32 SDK include files
#include <imm.h>
#include <ime.h>
// End -- Win32 SDK include files

#include <awt_DnDDT.h>

LPCTSTR szAwtComponentClassName = TEXT("SunAwtComponent");
// register a message that no other window in the process (even in a plugin
// scenario) will be using
const UINT AwtComponent::WmAwtIsComponent =
    ::RegisterWindowMessage(szAwtComponentClassName);

static HWND g_hwndDown = NULL;
static DCList activeDCList;
static DCList passiveDCList;

extern void CheckFontSmoothingSettings(HWND);

extern "C" {
    // Remember the input language has changed by some user's action
    // (Alt+Shift or through the language icon on the Taskbar) to control the
    // race condition between the toolkit thread and the AWT event thread.
    // This flag remains TRUE until the next WInputMethod.getNativeLocale() is
    // issued.
    BOOL g_bUserHasChangedInputLang = FALSE;
}

BOOL AwtComponent::sm_suppressFocusAndActivation = FALSE;
BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE;
HWND AwtComponent::sm_focusOwner = NULL;
HWND AwtComponent::sm_focusedWindow = NULL;
BOOL AwtComponent::sm_bMenuLoop = FALSE;
AwtComponent* AwtComponent::sm_getComponentCache = NULL;
BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;

/************************************************************************/
// Struct for _Reshape() and ReshapeNoCheck() methods
struct ReshapeStruct {
    jobject component;
    jint x, y;
    jint w, h;
};
// Struct for _NativeHandleEvent() method
struct NativeHandleEventStruct {
    jobject component;
    jobject event;
};
// Struct for _SetForeground() and _SetBackground() methods
struct SetColorStruct {
    jobject component;
    jint rgb;
};
// Struct for _SetFont() method
struct SetFontStruct {
    jobject component;
    jobject font;
};
// Struct for _CreatePrintedPixels() method
struct CreatePrintedPixelsStruct {
    jobject component;
    int srcx, srcy;
    int srcw, srch;
    jint alpha;
};
// Struct for _SetRectangularShape() method
struct SetRectangularShapeStruct {
    jobject component;
    jint x1, x2, y1, y2;
    jobject region;
};
// Struct for _GetInsets function
struct GetInsetsStruct {
    jobject window;
    RECT *insets;
};
// Struct for _SetZOrder function
struct SetZOrderStruct {
    jobject component;
    jlong above;
};
// Struct for _SetFocus function
struct SetFocusStruct {
    jobject component;
    jboolean doSetFocus;
};
/************************************************************************/

//////////////////////////////////////////////////////////////////////////

/*************************************************************************
 * AwtComponent fields
 */


jfieldID AwtComponent::peerID;
jfieldID AwtComponent::xID;
jfieldID AwtComponent::yID;
jfieldID AwtComponent::widthID;
jfieldID AwtComponent::heightID;
jfieldID AwtComponent::visibleID;
jfieldID AwtComponent::backgroundID;
jfieldID AwtComponent::foregroundID;
jfieldID AwtComponent::enabledID;
jfieldID AwtComponent::parentID;
jfieldID AwtComponent::graphicsConfigID;
jfieldID AwtComponent::peerGCID;
jfieldID AwtComponent::focusableID;
jfieldID AwtComponent::appContextID;
jfieldID AwtComponent::cursorID;
jfieldID AwtComponent::hwndID;

jmethodID AwtComponent::getFontMID;
jmethodID AwtComponent::getToolkitMID;
jmethodID AwtComponent::isEnabledMID;
jmethodID AwtComponent::getLocationOnScreenMID;
jmethodID AwtComponent::replaceSurfaceDataMID;
jmethodID AwtComponent::replaceSurfaceDataLaterMID;
jmethodID AwtComponent::disposeLaterMID;

HKL    AwtComponent::m_hkl = ::GetKeyboardLayout(0);
LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0));
UINT   AwtComponent::m_CodePage
                       = AwtComponent::LangToCodePage(m_idLang);

jint *AwtComponent::masks;

static BOOL bLeftShiftIsDown = false;
static BOOL bRightShiftIsDown = false;
static UINT lastShiftKeyPressed = 0; // init to safe value

// Added by waleed to initialize the RTL Flags
BOOL AwtComponent::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC ||
                            PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW;
BOOL AwtComponent::sm_rtlReadingOrder =
    PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC;

BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE;

HWND AwtComponent::sm_cursorOn;
BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE;

CriticalSection windowMoveLock;
BOOL windowMoveLockHeld = FALSE;

/************************************************************************
 * AwtComponent methods
 */

AwtComponent::AwtComponent()
{
    m_mouseButtonClickAllowed = 0;
    m_callbacksEnabled = FALSE;
    m_hwnd = NULL;

    m_colorForeground = 0;
    m_colorBackground = 0;
    m_backgroundColorSet = FALSE;
    m_penForeground = NULL;
    m_brushBackground = NULL;
    m_DefWindowProc = NULL;
    m_nextControlID = 1;
    m_childList = NULL;
    m_myControlID = 0;
    m_hdwp = NULL;
    m_validationNestCount = 0;

    m_dropTarget = NULL;

    m_InputMethod = NULL;
    m_useNativeCompWindow = TRUE;
    m_PendingLeadByte = 0;
    m_bitsCandType = 0;

    windowMoveLockPosX = 0;
    windowMoveLockPosY = 0;
    windowMoveLockPosCX = 0;
    windowMoveLockPosCY = 0;

    m_hCursorCache = NULL;

    m_bSubclassed = FALSE;
    m_bPauseDestroy = FALSE;

    m_MessagesProcessing = 0;
    m_wheelRotationAmount = 0;
    if (!sm_PrimaryDynamicTableBuilt) {
        // do it once.
        AwtComponent::BuildPrimaryDynamicTable();
        sm_PrimaryDynamicTableBuilt = TRUE;
    }
}

AwtComponent::~AwtComponent()
{
    DASSERT(AwtToolkit::IsMainThread());

    /* Disconnect all links. */
    UnlinkObjects();

    /*
     * All the messages for this component are processed, native
     * resources are freed, and Java object is not connected to
     * the native one anymore. So we can safely destroy component's
     * handle.
     */
    DestroyHWnd();

    if (sm_getComponentCache == this) {
        sm_getComponentCache = NULL;
    }
}

void AwtComponent::Dispose()
{
    // NOTE: in case the component/toplevel was focused, Java should
    // have already taken care of proper transferring it or clearing.

    if (m_hdwp != NULL) {
    // end any deferred window positioning, regardless
    // of m_validationNestCount
        ::EndDeferWindowPos(m_hdwp);
    }

    // Send final message to release all DCs associated with this component
    SendMessage(WM_AWT_RELEASE_ALL_DCS);

    /* Stop message filtering. */
    UnsubclassHWND();

    /* Release global ref to input method */
    SetInputMethod(NULL, TRUE);

    if (m_childList != NULL)
        delete m_childList;

    DestroyDropTarget();
    ReleaseDragCapture(0);

    if (m_myControlID != 0) {
        AwtComponent* parent = GetParent();
        if (parent != NULL)
            parent->RemoveChild(m_myControlID);
    }

    ::RemoveProp(GetHWnd(), DrawingStateProp);

    /* Release any allocated resources. */
    if (m_penForeground != NULL) {
        m_penForeground->Release();
        m_penForeground = NULL;
    }
    if (m_brushBackground != NULL) {
        m_brushBackground->Release();
        m_brushBackground = NULL;
    }

    if (m_bPauseDestroy) {
        // AwtComponent::WmNcDestroy could be released now
        m_bPauseDestroy = FALSE;
        m_hwnd = NULL;
    }

    // The component instance is deleted using AwtObject::Dispose() method
    AwtObject::Dispose();
}

/* store component pointer in window extra bytes */
void AwtComponent::SetComponentInHWND() {
    DASSERT(::GetWindowLongPtr(GetHWnd(), GWLP_USERDATA) == NULL);
    ::SetWindowLongPtr(GetHWnd(), GWLP_USERDATA, (LONG_PTR)this);
}

/*
 * static function to get AwtComponent pointer from hWnd --
 * you don't want to call this from inside a wndproc to avoid
 * infinite recursion
 */
AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
    // Requests for Toolkit hwnd resolution happen pretty often. Check first.
    if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
        return NULL;
    }
    if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) {
        return sm_getComponentCache;
    }

    // check that it's an AWT component from the same toolkit as the caller
    if (::IsWindow(hWnd) &&
        AwtToolkit::MainThread() == ::GetWindowThreadProcessId(hWnd, NULL))
    {
        DASSERT(WmAwtIsComponent != 0);
        if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
            return sm_getComponentCache = GetComponentImpl(hWnd);
        }
    }
    return NULL;
}

/*
 * static function to get AwtComponent pointer from hWnd--
 * different from GetComponent because caller knows the
 * hwnd is an AWT component hwnd
 */
AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
    AwtComponent *component =
        (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
    DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
    DASSERT(!component || component->GetHWnd() == hWnd );
    return component;
}

/*
 * Single window proc for all the components. Delegates real work to
 * the component's WindowProc() member function.
 */
LRESULT CALLBACK AwtComponent::WndProc(HWND hWnd, UINT message,
                                       WPARAM wParam, LPARAM lParam)
{
    TRY;

    AwtComponent * self = AwtComponent::GetComponentImpl(hWnd);
    if (self == NULL || self->GetHWnd() != hWnd ||
        message == WM_UNDOCUMENTED_CLIENTSHUTDOWN) // handle log-off gracefully
    {
        return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam);
    } else {
        return self->WindowProc(message, wParam, lParam);
    }

    CATCH_BAD_ALLOC_RET(0);
}

BOOL AwtComponent::IsFocusable() {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject peer = GetPeer(env);
    jobject target = env->GetObjectField(peer, AwtObject::targetID);
    BOOL res = env->GetBooleanField(target, focusableID);
    AwtWindow *pCont = GetContainer();
    if (pCont) {
        res &= pCont->IsFocusableWindow();
    }
    env->DeleteLocalRef(target);
    return res;
}

/************************************************************************
 * AwtComponent dynamic methods
 *
 * Window class registration routines
 */

/*
 * Fix for 4964237: Win XP: Changing theme changes java dialogs title icon
 */
void AwtComponent::FillClassInfo(WNDCLASSEX *lpwc)
{
    lpwc->cbSize        = sizeof(WNDCLASSEX);
    lpwc->style         = 0L;//CS_OWNDC;
    lpwc->lpfnWndProc   = (WNDPROC)::DefWindowProc;
    lpwc->cbClsExtra    = 0;
    lpwc->cbWndExtra    = 0;
    lpwc->hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
    lpwc->hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
    lpwc->hCursor       = NULL;
    lpwc->hbrBackground = NULL;
    lpwc->lpszMenuName  = NULL;
    lpwc->lpszClassName = GetClassName();
    //Fixed 6233560: PIT: Java Cup Logo on the title bar of top-level windows look blurred, Win32
    lpwc->hIconSm       = AwtToolkit::GetInstance().GetAwtIconSm();
}

void AwtComponent::RegisterClass()
{
    WNDCLASSEX wc;
    if (!::GetClassInfoEx(AwtToolkit::GetInstance().GetModuleHandle(), GetClassName(), &wc)) {
        FillClassInfo(&wc);
        ATOM ret = ::RegisterClassEx(&wc);
        DASSERT(ret != 0);
    }
}

void AwtComponent::UnregisterClass()
{
    ::UnregisterClass(GetClassName(), AwtToolkit::GetInstance().GetModuleHandle());
}

/*
 * Copy the graphicsConfig reference from Component into WComponentPeer
 */
void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer)
{
    jobject target = env->GetObjectField(peer, AwtObject::targetID);
    //Get graphicsConfig object ref from Component
    jobject compGC = env->GetObjectField(target,
                      AwtComponent::graphicsConfigID);

    //Set peer's graphicsConfig to Component's graphicsConfig
    if (compGC != NULL) {
        jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig");
        DASSERT(win32GCCls != NULL);
        DASSERT(env->IsInstanceOf(compGC, win32GCCls));
        if (win32GCCls == NULL) {
            throw std::bad_alloc();
        }
        env->SetObjectField(peer, AwtComponent::peerGCID, compGC);
    }
}

void
AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title,
                         DWORD windowStyle,
                         DWORD windowExStyle,
                         int x, int y, int w, int h,
                         HWND hWndParent, HMENU hMenu,
                         COLORREF colorForeground,
                         COLORREF colorBackground,
                         jobject peer)
{
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }

    /*
     * The window class of multifont label must be "BUTTON" because
     * "STATIC" class can't get WM_DRAWITEM message, and m_peerObject
     * member is referred in the GetClassName method of AwtLabel class.
     * So m_peerObject member must be set here.
     */
    if (m_peerObject == NULL) {
        m_peerObject = env->NewGlobalRef(peer);
    } else {
        assert(env->IsSameObject(m_peerObject, peer));
    }

    RegisterClass();

    jobject target = env->GetObjectField(peer, AwtObject::targetID);
    jboolean visible = env->GetBooleanField(target, AwtComponent::visibleID);
    m_visible = visible;

    if (visible) {
        windowStyle |= WS_VISIBLE;
    } else {
        windowStyle &= ~WS_VISIBLE;
    }

    InitPeerGraphicsConfig(env, peer);

    SetLastError(0);
    HWND hwnd = ::CreateWindowEx(windowExStyle,
                                 GetClassName(),
                                 title,
                                 windowStyle,
                                 x, y, w, h,
                                 hWndParent,
                                 hMenu,
                                 AwtToolkit::GetInstance().GetModuleHandle(),
                                 NULL);

    // fix for 5088782
    // check if CreateWindowsEx() returns not null value and if it does -
    //   create an InternalError or OutOfMemoryError based on GetLastError().
    //   This error is set to createError field of WObjectPeer and then
    //   checked and thrown in WComponentPeer constructor. We can't throw an
    //   error here because this code is invoked on Toolkit thread
    if (hwnd == NULL)
    {
        DWORD dw = ::GetLastError();
        jobject createError = NULL;
        if (dw == ERROR_OUTOFMEMORY)
        {
            jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles");
            if (errorMsg == NULL || env->ExceptionCheck()) {
                env->ExceptionClear();
                createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V");
            } else {
                createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
                                                      "(Ljava/lang/String;)V",
                                                      errorMsg);
                env->DeleteLocalRef(errorMsg);
            }
        }
        else
        {
            TCHAR *buf;
            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&buf, 0, NULL);
            jstring s = JNU_NewStringPlatform(env, buf);
            if (s == NULL || env->ExceptionCheck()) {
                env->ExceptionClear();
                createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V");
            } else {
                createError = JNU_NewObjectByName(env, "java/lang/InternalError",
                                                                  "(Ljava/lang/String;)V", s);
                env->DeleteLocalRef(s);
            }
            LocalFree(buf);
        }
        if (createError != NULL) {
            env->SetObjectField(peer, AwtObject::createErrorID, createError);
            env->DeleteLocalRef(createError);
        }
        env->DeleteLocalRef(target);
        return;
    }

    m_hwnd = hwnd;

    ::ImmAssociateContext(m_hwnd, NULL);

    SetDrawState((jint)JAWT_LOCK_SURFACE_CHANGED |
        (jint)JAWT_LOCK_BOUNDS_CHANGED |
        (jint)JAWT_LOCK_CLIP_CHANGED);

    LinkObjects(env, peer);

    /* Subclass the window now so that we can snoop on its messages */
    SubclassHWND();

    /*
      * Fix for 4046446.
      */
    SetWindowPos(GetHWnd(), 0, x, y, w, h, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE);

    /* Set default colors. */
    m_colorForeground = colorForeground;
    m_colorBackground = colorBackground;

    /*
     * Only set background color if the color is actually set on the
     * target -- this avoids inheriting a parent's color unnecessarily,
     * and has to be done here because there isn't an API to get the
     * real background color from outside the AWT package.
     */
    jobject bkgrd = env->GetObjectField(target, AwtComponent::backgroundID) ;
    if (bkgrd != NULL) {
        JNU_CallMethodByName(env, NULL, peer, "setBackground",
                             "(Ljava/awt/Color;)V", bkgrd);
        DASSERT(!safe_ExceptionOccurred(env));
    }
    env->DeleteLocalRef(target);
    env->DeleteLocalRef(bkgrd);
}

/*
 * Destroy this window's HWND
 */
void AwtComponent::DestroyHWnd() {
    if (m_hwnd != NULL) {
        AwtToolkit::DestroyComponentHWND(m_hwnd);
        //AwtToolkit::DestroyComponent(this);
        m_hwnd = NULL;
    }
}

/*
 * Returns hwnd for target on non Toolkit thread
 */
HWND
AwtComponent::GetHWnd(JNIEnv* env, jobject target) {
    if (JNU_IsNull(env, target)) {
        return 0;
    }
    jobject peer = env->GetObjectField(target, AwtComponent::peerID);
    if (JNU_IsNull(env, peer)) {
        return 0;
    }
    HWND hwnd = reinterpret_cast<HWND>(static_cast<LONG_PTR> (
        env->GetLongField(peer, AwtComponent::hwndID)));
    env->DeleteLocalRef(peer);
    return hwnd;
}
//
// Propagate the background color to synchronize Java field and peer's field.
// This is needed to fix 4148334
//
void AwtComponent::UpdateBackground(JNIEnv *env, jobject target)
{
    if (env->EnsureLocalCapacity(1) < 0) {
        return;
    }

    jobject bkgrnd = env->GetObjectField(target, AwtComponent::backgroundID);

    if (bkgrnd == NULL) {
        bkgrnd = JNU_NewObjectByName(env, "java/awt/Color", "(III)V",
                                     GetRValue(m_colorBackground),
                                     GetGValue(m_colorBackground),
                                     GetBValue(m_colorBackground));
        if (bkgrnd != NULL) {
            env->SetObjectField(target, AwtComponent::backgroundID, bkgrnd);
        }
    }
    env->DeleteLocalRef(bkgrnd);
}

/*
 * Install our window proc as the proc for our HWND, and save off the
 * previous proc as the default
 */
void AwtComponent::SubclassHWND()
{
    if (m_bSubclassed) {
        return;
    }
    const WNDPROC wndproc = WndProc; // let compiler type check WndProc
    m_DefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(GetHWnd(), wndproc);
    m_bSubclassed = TRUE;
}

/*
 * Reinstall the original window proc as the proc for our HWND
 */
void AwtComponent::UnsubclassHWND()
{
    if (!m_bSubclassed) {
        return;
    }
    ComCtl32Util::GetInstance().UnsubclassHWND(GetHWnd(), WndProc, m_DefWindowProc);
    m_bSubclassed = FALSE;
}

/////////////////////////////////////
// (static method)
// Determines the top-level ancestor for a given window. If the given
// window is a top-level window, return itself.
//
// 'Top-level' includes dialogs as well.
//
HWND AwtComponent::GetTopLevelParentForWindow(HWND hwndDescendant) {
    if (hwndDescendant == NULL) {
        return NULL;
    }

    DASSERT(IsWindow(hwndDescendant));
    HWND hwnd = hwndDescendant;
    for(;;) {
        DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
        // a) found a non-child window so terminate
        // b) found real toplevel window (e.g. EmbeddedFrame
        //    that is child though)
        if ( (style & WS_CHILD) == 0 ||
             AwtComponent::IsTopLevelHWnd(hwnd) )
        {
            break;
        }
        hwnd = ::GetParent(hwnd);
    }

    return hwnd;
}
////////////////////

jobject AwtComponent::FindHeavyweightUnderCursor(BOOL useCache) {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (env->EnsureLocalCapacity(1) < 0) {
        return NULL;
    }

    HWND hit = NULL;
    POINT p = { 0, 0 };
    AwtComponent *comp = NULL;

    if (useCache) {
        if (sm_cursorOn == NULL) {
            return NULL;
        }


        DASSERT(::IsWindow(sm_cursorOn));
        VERIFY(::GetCursorPos(&p));
        /*
         * Fix for BugTraq ID 4304024.
         * Allow a non-default cursor only for the client area.
         */
        comp = AwtComponent::GetComponent(sm_cursorOn);
        if (comp != NULL &&
            ::SendMessage(sm_cursorOn, WM_NCHITTEST, 0,
                          MAKELPARAM(p.x, p.y)) == HTCLIENT) {
            goto found;
        }
    }

    ::GetCursorPos(&p);
    hit = ::WindowFromPoint(p);
    while (hit != NULL) {
        comp = AwtComponent::GetComponent(hit);

        if (comp != NULL) {
            INT nHittest = (INT)::SendMessage(hit, WM_NCHITTEST,
                                          0, MAKELPARAM(p.x, p.y));
            /*
             * Fix for BugTraq ID 4304024.
             * Allow a non-default cursor only for the client area.
             */
            if (nHittest != HTCLIENT) {
                /*
                 * When over the non-client area, send WM_SETCURSOR
                 * to revert the cursor to an arrow.
                 */
                ::SendMessage(hit, WM_SETCURSOR, (WPARAM)hit,
                              MAKELPARAM(nHittest, WM_MOUSEMOVE));
                return NULL;
            } else {
              sm_cursorOn = hit;
              goto found;
            }
        }

        if ((::GetWindowLong(hit, GWL_STYLE) & WS_CHILD) == 0) {
            return NULL;
        }
        hit = ::GetParent(hit);
    }

    return NULL;

found:
    jobject localRef = comp->GetTarget(env);
    jobject globalRef = env->NewGlobalRef(localRef);
    env->DeleteLocalRef(localRef);
    return globalRef;
}

void AwtComponent::SetColor(COLORREF c)
{
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
    if (grayscale != GS_NOTGRAY) {
        int g;

        g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
            .114 * ((c >> 16) & 0xFF) + 0.5);
        // c = g | (g << 8) | (g << 16);
        c = PALETTERGB(g, g, g);
    }

    if (m_colorForeground == c) {
        return;
    }

    m_colorForeground = c;
    if (m_penForeground != NULL) {
        m_penForeground->Release();
        m_penForeground = NULL;
    }
    VERIFY(::InvalidateRect(GetHWnd(), NULL, FALSE));
}

void AwtComponent::SetBackgroundColor(COLORREF c)
{
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
    if (grayscale != GS_NOTGRAY) {
        int g;

        g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
            .114 * ((c >> 16) & 0xFF) + 0.5);
        // c = g | (g << 8) | (g << 16);
        c = PALETTERGB(g, g, g);
    }

    if (m_colorBackground == c) {
        return;
    }
    m_colorBackground = c;
    m_backgroundColorSet = TRUE;
    if (m_brushBackground != NULL) {
        m_brushBackground->Release();
        m_brushBackground = NULL;
    }
    VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
}

HPEN AwtComponent::GetForegroundPen()
{
    if (m_penForeground == NULL) {
        m_penForeground = AwtPen::Get(m_colorForeground);
    }
    return (HPEN)m_penForeground->GetHandle();
}

COLORREF AwtComponent::GetBackgroundColor()
{
    if (m_backgroundColorSet == FALSE) {
        AwtComponent* c = this;
        while ((c = c->GetParent()) != NULL) {
            if (c->IsBackgroundColorSet()) {
                return c->GetBackgroundColor();
            }
        }
    }
    return m_colorBackground;
}

HBRUSH AwtComponent::GetBackgroundBrush()
{
    if (m_backgroundColorSet == FALSE) {
        if (m_brushBackground != NULL) {
            m_brushBackground->Release();
            m_brushBackground = NULL;
        }
          AwtComponent* c = this;
          while ((c = c->GetParent()) != NULL) {
              if (c->IsBackgroundColorSet()) {
                  m_brushBackground =
                      AwtBrush::Get(c->GetBackgroundColor());
                  break;
              }
          }
    }
    if (m_brushBackground == NULL) {
        m_brushBackground = AwtBrush::Get(m_colorBackground);
    }
    return (HBRUSH)m_brushBackground->GetHandle();
}

void AwtComponent::SetFont(AwtFont* font)
{
    DASSERT(font != NULL);
    if (font->GetAscent() < 0) {
        AwtFont::SetupAscent(font);
    }
    SendMessage(WM_SETFONT, (WPARAM)font->GetHFont(), MAKELPARAM(FALSE, 0));
    VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
}

AwtComponent* AwtComponent::GetParent()
{
    HWND hwnd = ::GetParent(GetHWnd());
    if (hwnd == NULL) {
        return NULL;
    }
    return GetComponent(hwnd);
}

AwtWindow* AwtComponent::GetContainer()
{
    AwtComponent* comp = this;
    while (comp != NULL) {
        if (comp->IsContainer()) {
            return (AwtWindow*)comp;
        }
        comp = comp->GetParent();
    }
    return NULL;
}

void AwtComponent::Show()
{
    m_visible = true;
    ::ShowWindow(GetHWnd(), SW_SHOWNA);
}

void AwtComponent::Hide()
{
    m_visible = false;
    ::ShowWindow(GetHWnd(), SW_HIDE);
}

BOOL
AwtComponent::SetWindowPos(HWND wnd, HWND after,
                           int x, int y, int w, int h, UINT flags)
{
    // Conditions we shouldn't handle:
    // z-order changes, correct window dimensions
    if (after != NULL || (w < 32767 && h < 32767)
        || ((::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD) == 0))
    {
        return ::SetWindowPos(wnd, after, x, y, w, h, flags);
    }
    WINDOWPLACEMENT wp;
    ::ZeroMemory(&wp, sizeof(wp));

    wp.length = sizeof(wp);
    ::GetWindowPlacement(wnd, &wp);
    wp.rcNormalPosition.left = x;
    wp.rcNormalPosition.top = y;
    wp.rcNormalPosition.right = x + w;
    wp.rcNormalPosition.bottom = y + h;
    if ( flags & SWP_NOACTIVATE ) {
        wp.showCmd = SW_SHOWNOACTIVATE;
    }
    ::SetWindowPlacement(wnd, &wp);
    return 1;
}


void AwtComponent::Reshape(int x, int y, int w, int h)
{
#if defined(DEBUG)
    RECT        rc;
    ::GetWindowRect(GetHWnd(), &rc);
    ::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2);
    DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
#endif

    x = ScaleUpX(x);
    y = ScaleUpY(y);
    w = ScaleUpX(w);
    h = ScaleUpY(h);

    AwtWindow* container = GetContainer();
    AwtComponent* parent = GetParent();
    if (container != NULL && container == parent) {
        container->SubtractInsetPoint(x, y);
    }
    DTRACE_PRINTLN4("AwtComponent::Reshape to %d, %d, %d, %d", x, y, w, h);
    UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;

    RECT        r;

    ::GetWindowRect(GetHWnd(), &r);
    // if the component size is changing , don't copy window bits
    if (r.right - r.left != w || r.bottom - r.top != h) {
        flags |= SWP_NOCOPYBITS;
    }

    if (parent && _tcscmp(parent->GetClassName(), TEXT("SunAwtScrollPane")) == 0) {
        if (x > 0) {
            x = 0;
        }
        if (y > 0) {
            y = 0;
        }
    }
    if (m_hdwp != NULL) {
        m_hdwp = ::DeferWindowPos(m_hdwp, GetHWnd(), 0, x, y, w, h, flags);
        DASSERT(m_hdwp != NULL);
    } else {
        /*
         * Fox for 4046446
         * If window has dimensions above the short int limit, ::SetWindowPos doesn't work.
         * We should use SetWindowPlacement instead.
         */
        SetWindowPos(GetHWnd(), 0, x, y, w, h, flags);
    }
}

void AwtComponent::SetScrollValues(UINT bar, int min, int value, int max)
{
    int minTmp, maxTmp;

    ::GetScrollRange(GetHWnd(), bar, &minTmp, &maxTmp);
    if (min == INT_MAX) {
        min = minTmp;
    }
    if (value == INT_MAX) {
        value = ::GetScrollPos(GetHWnd(), bar);
    }
    if (max == INT_MAX) {
        max = maxTmp;
    }
    if (min == max) {
        max++;
    }
    ::SetScrollRange(GetHWnd(), bar, min, max, FALSE);
    ::SetScrollPos(GetHWnd(), bar, value, TRUE);
}

/*
 * Save Global Reference of sun.awt.windows.WInputMethod object
 */
void AwtComponent::SetInputMethod(jobject im, BOOL useNativeCompWindow)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    if (m_InputMethod!=NULL)
        env->DeleteGlobalRef(m_InputMethod);

    if (im!=NULL){
        m_InputMethod = env->NewGlobalRef(im);
        m_useNativeCompWindow = useNativeCompWindow;
    } else {
        m_InputMethod = NULL;
        m_useNativeCompWindow = TRUE;
    }

}

/*
 * Opportunity to process and/or eat a message before it is dispatched
 */
MsgRouting AwtComponent::PreProcessMsg(MSG& msg)
{
    return mrPassAlong;
}

static UINT lastMessage = WM_NULL;

#ifndef SPY_MESSAGES
#define SpyWinMessage(hwin,msg,str)
#else

#define FMT_MSG(x,y) case x: _stprintf(szBuf, \
    "0x%8.8x(%s):%s\n", hwnd, szComment, y); break;
#define WIN_MSG(x) FMT_MSG(x,#x)

void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) {

    TCHAR szBuf[256];

    switch (message) {
        WIN_MSG(WM_NULL)
        WIN_MSG(WM_CREATE)
        WIN_MSG(WM_DESTROY)
        WIN_MSG(WM_MOVE)
        WIN_MSG(WM_SIZE)
        WIN_MSG(WM_ACTIVATE)
        WIN_MSG(WM_SETFOCUS)
        WIN_MSG(WM_KILLFOCUS)
        WIN_MSG(WM_ENABLE)
        WIN_MSG(WM_SETREDRAW)
        WIN_MSG(WM_SETTEXT)
        WIN_MSG(WM_GETTEXT)
        WIN_MSG(WM_GETTEXTLENGTH)
        WIN_MSG(WM_PAINT)
        WIN_MSG(WM_CLOSE)
        WIN_MSG(WM_QUERYENDSESSION)
        WIN_MSG(WM_QUIT)
        WIN_MSG(WM_QUERYOPEN)
        WIN_MSG(WM_ERASEBKGND)
        WIN_MSG(WM_SYSCOLORCHANGE)
        WIN_MSG(WM_ENDSESSION)
        WIN_MSG(WM_SHOWWINDOW)
        FMT_MSG(WM_WININICHANGE,"WM_WININICHANGE/WM_SETTINGCHANGE")
        WIN_MSG(WM_DEVMODECHANGE)
        WIN_MSG(WM_ACTIVATEAPP)
        WIN_MSG(WM_FONTCHANGE)
        WIN_MSG(WM_TIMECHANGE)
        WIN_MSG(WM_CANCELMODE)
        WIN_MSG(WM_SETCURSOR)
        WIN_MSG(WM_MOUSEACTIVATE)
        WIN_MSG(WM_CHILDACTIVATE)
        WIN_MSG(WM_QUEUESYNC)
        WIN_MSG(WM_GETMINMAXINFO)
        WIN_MSG(WM_PAINTICON)
        WIN_MSG(WM_ICONERASEBKGND)
        WIN_MSG(WM_NEXTDLGCTL)
        WIN_MSG(WM_SPOOLERSTATUS)
        WIN_MSG(WM_DRAWITEM)
        WIN_MSG(WM_MEASUREITEM)
        WIN_MSG(WM_DELETEITEM)
        WIN_MSG(WM_VKEYTOITEM)
        WIN_MSG(WM_CHARTOITEM)
        WIN_MSG(WM_SETFONT)
        WIN_MSG(WM_GETFONT)
        WIN_MSG(WM_SETHOTKEY)
        WIN_MSG(WM_GETHOTKEY)
        WIN_MSG(WM_QUERYDRAGICON)
        WIN_MSG(WM_COMPAREITEM)
        FMT_MSG(0x003D, "WM_GETOBJECT")
        WIN_MSG(WM_COMPACTING)
        WIN_MSG(WM_COMMNOTIFY)
        WIN_MSG(WM_WINDOWPOSCHANGING)
        WIN_MSG(WM_WINDOWPOSCHANGED)
        WIN_MSG(WM_POWER)
        WIN_MSG(WM_COPYDATA)
        WIN_MSG(WM_CANCELJOURNAL)
        WIN_MSG(WM_NOTIFY)
        WIN_MSG(WM_INPUTLANGCHANGEREQUEST)
        WIN_MSG(WM_INPUTLANGCHANGE)
        WIN_MSG(WM_TCARD)
        WIN_MSG(WM_HELP)
        WIN_MSG(WM_USERCHANGED)
        WIN_MSG(WM_NOTIFYFORMAT)
        WIN_MSG(WM_CONTEXTMENU)
        WIN_MSG(WM_STYLECHANGING)
        WIN_MSG(WM_STYLECHANGED)
        WIN_MSG(WM_DISPLAYCHANGE)
        WIN_MSG(WM_GETICON)
        WIN_MSG(WM_SETICON)
        WIN_MSG(WM_NCCREATE)
        WIN_MSG(WM_NCDESTROY)
        WIN_MSG(WM_NCCALCSIZE)
        WIN_MSG(WM_NCHITTEST)
        WIN_MSG(WM_NCPAINT)
        WIN_MSG(WM_NCACTIVATE)
        WIN_MSG(WM_GETDLGCODE)
        WIN_MSG(WM_SYNCPAINT)
        WIN_MSG(WM_NCMOUSEMOVE)
        WIN_MSG(WM_NCLBUTTONDOWN)
        WIN_MSG(WM_NCLBUTTONUP)
        WIN_MSG(WM_NCLBUTTONDBLCLK)
        WIN_MSG(WM_NCRBUTTONDOWN)
        WIN_MSG(WM_NCRBUTTONUP)
        WIN_MSG(WM_NCRBUTTONDBLCLK)
        WIN_MSG(WM_NCMBUTTONDOWN)
        WIN_MSG(WM_NCMBUTTONUP)
        WIN_MSG(WM_NCMBUTTONDBLCLK)
        WIN_MSG(WM_KEYDOWN)
        WIN_MSG(WM_KEYUP)
        WIN_MSG(WM_CHAR)
        WIN_MSG(WM_DEADCHAR)
        WIN_MSG(WM_SYSKEYDOWN)
        WIN_MSG(WM_SYSKEYUP)
        WIN_MSG(WM_SYSCHAR)
        WIN_MSG(WM_SYSDEADCHAR)
        WIN_MSG(WM_IME_STARTCOMPOSITION)
        WIN_MSG(WM_IME_ENDCOMPOSITION)
        WIN_MSG(WM_IME_COMPOSITION)
        WIN_MSG(WM_INITDIALOG)
        WIN_MSG(WM_COMMAND)
        WIN_MSG(WM_SYSCOMMAND)
        WIN_MSG(WM_TIMER)
        WIN_MSG(WM_HSCROLL)
        WIN_MSG(WM_VSCROLL)
        WIN_MSG(WM_INITMENU)
        WIN_MSG(WM_INITMENUPOPUP)
        WIN_MSG(WM_MENUSELECT)
        WIN_MSG(WM_MENUCHAR)
        WIN_MSG(WM_ENTERIDLE)
        FMT_MSG(0x0122, "WM_MENURBUTTONUP")
        FMT_MSG(0x0123, "WM_MENUDRAG")
        FMT_MSG(0x0124, "WM_MENUGETOBJECT")
        FMT_MSG(0x0125, "WM_UNINITMENUPOPUP")
        FMT_MSG(0x0126, "WM_MENUCOMMAND")
        WIN_MSG(WM_CTLCOLORMSGBOX)
        WIN_MSG(WM_CTLCOLOREDIT)
        WIN_MSG(WM_CTLCOLORLISTBOX)
        WIN_MSG(WM_CTLCOLORBTN)
        WIN_MSG(WM_CTLCOLORDLG)
        WIN_MSG(WM_CTLCOLORSCROLLBAR)
        WIN_MSG(WM_CTLCOLORSTATIC)
        WIN_MSG(WM_MOUSEMOVE)
        WIN_MSG(WM_LBUTTONDOWN)
        WIN_MSG(WM_LBUTTONUP)
        WIN_MSG(WM_LBUTTONDBLCLK)
        WIN_MSG(WM_RBUTTONDOWN)
        WIN_MSG(WM_RBUTTONUP)
        WIN_MSG(WM_RBUTTONDBLCLK)
        WIN_MSG(WM_MBUTTONDOWN)
        WIN_MSG(WM_MBUTTONUP)
        WIN_MSG(WM_MBUTTONDBLCLK)
        WIN_MSG(WM_XBUTTONDBLCLK)
        WIN_MSG(WM_XBUTTONDOWN)
        WIN_MSG(WM_XBUTTONUP)
        WIN_MSG(WM_MOUSEWHEEL)
        WIN_MSG(WM_PARENTNOTIFY)
        WIN_MSG(WM_ENTERMENULOOP)
        WIN_MSG(WM_EXITMENULOOP)
        WIN_MSG(WM_NEXTMENU)
        WIN_MSG(WM_SIZING)
        WIN_MSG(WM_CAPTURECHANGED)
        WIN_MSG(WM_MOVING)
        WIN_MSG(WM_POWERBROADCAST)
        WIN_MSG(WM_DEVICECHANGE)
        WIN_MSG(WM_MDICREATE)
        WIN_MSG(WM_MDIDESTROY)
        WIN_MSG(WM_MDIACTIVATE)
        WIN_MSG(WM_MDIRESTORE)
        WIN_MSG(WM_MDINEXT)
        WIN_MSG(WM_MDIMAXIMIZE)
        WIN_MSG(WM_MDITILE)
        WIN_MSG(WM_MDICASCADE)
        WIN_MSG(WM_MDIICONARRANGE)
        WIN_MSG(WM_MDIGETACTIVE)
        WIN_MSG(WM_MDISETMENU)
        WIN_MSG(WM_ENTERSIZEMOVE)
        WIN_MSG(WM_EXITSIZEMOVE)
        WIN_MSG(WM_DROPFILES)
        WIN_MSG(WM_MDIREFRESHMENU)
        WIN_MSG(WM_IME_SETCONTEXT)
        WIN_MSG(WM_IME_NOTIFY)
        WIN_MSG(WM_IME_CONTROL)
        WIN_MSG(WM_IME_COMPOSITIONFULL)
        WIN_MSG(WM_IME_SELECT)
        WIN_MSG(WM_IME_CHAR)
        FMT_MSG(WM_IME_REQUEST)
        WIN_MSG(WM_IME_KEYDOWN)
        WIN_MSG(WM_IME_KEYUP)
        FMT_MSG(0x02A1, "WM_MOUSEHOVER")
        FMT_MSG(0x02A3, "WM_MOUSELEAVE")
        WIN_MSG(WM_CUT)
        WIN_MSG(WM_COPY)
        WIN_MSG(WM_PASTE)
        WIN_MSG(WM_CLEAR)
        WIN_MSG(WM_UNDO)
        WIN_MSG(WM_RENDERFORMAT)
        WIN_MSG(WM_RENDERALLFORMATS)
        WIN_MSG(WM_DESTROYCLIPBOARD)
        WIN_MSG(WM_DRAWCLIPBOARD)
        WIN_MSG(WM_PAINTCLIPBOARD)
        WIN_MSG(WM_VSCROLLCLIPBOARD)
        WIN_MSG(WM_SIZECLIPBOARD)
        WIN_MSG(WM_ASKCBFORMATNAME)
        WIN_MSG(WM_CHANGECBCHAIN)
        WIN_MSG(WM_HSCROLLCLIPBOARD)
        WIN_MSG(WM_QUERYNEWPALETTE)
        WIN_MSG(WM_PALETTEISCHANGING)
        WIN_MSG(WM_PALETTECHANGED)
        WIN_MSG(WM_HOTKEY)
        WIN_MSG(WM_PRINT)
        WIN_MSG(WM_PRINTCLIENT)
        WIN_MSG(WM_HANDHELDFIRST)
        WIN_MSG(WM_HANDHELDLAST)
        WIN_MSG(WM_AFXFIRST)
        WIN_MSG(WM_AFXLAST)
        WIN_MSG(WM_PENWINFIRST)
        WIN_MSG(WM_PENWINLAST)
        WIN_MSG(WM_AWT_COMPONENT_CREATE)
        WIN_MSG(WM_AWT_DESTROY_WINDOW)
        WIN_MSG(WM_AWT_MOUSEENTER)
        WIN_MSG(WM_AWT_MOUSEEXIT)
        WIN_MSG(WM_AWT_COMPONENT_SHOW)
        WIN_MSG(WM_AWT_COMPONENT_HIDE)
        WIN_MSG(WM_AWT_COMPONENT_SETFOCUS)
        WIN_MSG(WM_AWT_WINDOW_SETACTIVE)
        WIN_MSG(WM_AWT_LIST_SETMULTISELECT)
        WIN_MSG(WM_AWT_HANDLE_EVENT)
        WIN_MSG(WM_AWT_PRINT_COMPONENT)
        WIN_MSG(WM_AWT_RESHAPE_COMPONENT)
        WIN_MSG(WM_AWT_SETALWAYSONTOP)
        WIN_MSG(WM_AWT_BEGIN_VALIDATE)
        WIN_MSG(WM_AWT_END_VALIDATE)
        WIN_MSG(WM_AWT_FORWARD_CHAR)
        WIN_MSG(WM_AWT_FORWARD_BYTE)
        WIN_MSG(WM_AWT_SET_SCROLL_INFO)
        WIN_MSG(WM_AWT_CREATECONTEXT)
        WIN_MSG(WM_AWT_DESTROYCONTEXT)
        WIN_MSG(WM_AWT_ASSOCIATECONTEXT)
        WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER)
        WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT)
        WIN_MSG(WM_AWT_PRE_KEYDOWN)
        WIN_MSG(WM_AWT_PRE_KEYUP)
        WIN_MSG(WM_AWT_PRE_SYSKEYDOWN)
        WIN_MSG(WM_AWT_PRE_SYSKEYUP)
        WIN_MSG(WM_AWT_ENDCOMPOSITION,)
        WIN_MSG(WM_AWT_DISPOSE,)
        WIN_MSG(WM_AWT_DELETEOBJECT,)
        WIN_MSG(WM_AWT_SETCONVERSIONSTATUS,)
        WIN_MSG(WM_AWT_GETCONVERSIONSTATUS,)
        WIN_MSG(WM_AWT_SETOPENSTATUS,)
        WIN_MSG(WM_AWT_GETOPENSTATUS)
        WIN_MSG(WM_AWT_ACTIVATEKEYBOARDLAYOUT)
        WIN_MSG(WM_AWT_OPENCANDIDATEWINDOW)
        WIN_MSG(WM_AWT_DLG_SHOWMODAL,)
        WIN_MSG(WM_AWT_DLG_ENDMODAL,)
        WIN_MSG(WM_AWT_SETCURSOR,)
        WIN_MSG(WM_AWT_WAIT_FOR_SINGLE_OBJECT,)
        WIN_MSG(WM_AWT_INVOKE_METHOD,)
        WIN_MSG(WM_AWT_INVOKE_VOID_METHOD,)
        WIN_MSG(WM_AWT_EXECUTE_SYNC,)
        WIN_MSG(WM_AWT_CURSOR_SYNC)
        WIN_MSG(WM_AWT_GETDC)
        WIN_MSG(WM_AWT_RELEASEDC)
        WIN_MSG(WM_AWT_RELEASE_ALL_DCS)
        WIN_MSG(WM_AWT_SHOWCURSOR)
        WIN_MSG(WM_AWT_HIDECURSOR)
        WIN_MSG(WM_AWT_CREATE_PRINTED_PIXELS)
        WIN_MSG(WM_AWT_OBJECTLISTCLEANUP)
        default:
            sprintf(szBuf, "0x%8.8x(%s):Unknown message 0x%8.8x\n",
                hwnd, szComment, message);
            break;
    }
    printf(szBuf);
}

#endif /* SPY_MESSAGES */

/*
 * Dispatch messages for this window class--general component
 */
LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    CounterHelper ch(&m_MessagesProcessing);

    JNILocalFrame lframe(AwtToolkit::GetEnv(), 10);
    SpyWinMessage(GetHWnd(), message,
        (message == WM_AWT_RELEASE_ALL_DCS) ? TEXT("Disposed Component") : GetClassName());

    LRESULT retValue = 0;
    MsgRouting mr = mrDoDefault;
    AwtToolkit::GetInstance().eventNumber++;

    static BOOL ignoreNextLBTNUP = FALSE; //Ignore next LBUTTONUP msg?

    lastMessage = message;

    if (message == WmAwtIsComponent) {
    // special message to identify AWT HWND's without using
    // resource hogging ::SetProp
        return (LRESULT)TRUE;
    }

    DWORD curPos = 0;

    UINT switchMessage = message;
    switch (switchMessage) {
      case WM_AWT_GETDC:
      {
            HDC hDC;
            // First, release the DCs scheduled for deletion
            ReleaseDCList(GetHWnd(), passiveDCList);

            GetDCReturnStruct *returnStruct = new GetDCReturnStruct;
            returnStruct->gdiLimitReached = FALSE;
            if (AwtGDIObject::IncrementIfAvailable()) {
                hDC = ::GetDCEx(GetHWnd(), NULL,
                                DCX_CACHE | DCX_CLIPCHILDREN |
                                DCX_CLIPSIBLINGS);
                if (hDC != NULL) {
                    // Add new DC to list of DC's associated with this Component
                    activeDCList.AddDC(hDC, GetHWnd());
                } else {
                    // Creation failed; decrement counter in AwtGDIObject
                    AwtGDIObject::Decrement();
                }
            } else {
                hDC = NULL;
                returnStruct->gdiLimitReached = TRUE;
            }
            returnStruct->hDC = hDC;
            retValue = (LRESULT)returnStruct;
            mr = mrConsume;
            break;
      }
      case WM_AWT_RELEASEDC:
      {
            HDC hDC = (HDC)wParam;
            MoveDCToPassiveList(hDC, GetHWnd());
            ReleaseDCList(GetHWnd(), passiveDCList);
            mr = mrConsume;
            break;
      }
      case WM_AWT_RELEASE_ALL_DCS:
      {
            // Called during Component destruction.  Gets current list of
            // DC's associated with Component and releases each DC.
            ReleaseDCList(GetHWnd(), activeDCList);
            ReleaseDCList(GetHWnd(), passiveDCList);
            mr = mrConsume;
            break;
      }
      case WM_AWT_SHOWCURSOR:
          ::ShowCursor(TRUE);
          break;
      case WM_AWT_HIDECURSOR:
          ::ShowCursor(FALSE);
          break;
      case WM_CREATE: mr = WmCreate(); break;
      case WM_CLOSE:      mr = WmClose(); break;
      case WM_DESTROY:    mr = WmDestroy(); break;
      case WM_NCDESTROY:  mr = WmNcDestroy(); break;

      case WM_ERASEBKGND:
          mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break;
      case WM_PAINT:
          CheckFontSmoothingSettings(GetHWnd());
          /* Set draw state */
          SetDrawState(GetDrawState() | JAWT_LOCK_CLIP_CHANGED);
          mr = WmPaint((HDC)wParam);
          break;

      case WM_GETMINMAXINFO:
          mr = WmGetMinMaxInfo((LPMINMAXINFO)lParam);
          break;

      case WM_WINDOWPOSCHANGING:
      {
          // We process this message so that we can synchronize access to
          // a moving window.  The Scale/Blt functions in Win32BlitLoops
          // take the same windowMoveLock to ensure that a window is not
          // moving while we are trying to copy pixels into it.
          WINDOWPOS *lpPosInfo = (WINDOWPOS *)lParam;
          if ((lpPosInfo->flags & (SWP_NOMOVE | SWP_NOSIZE)) !=
              (SWP_NOMOVE | SWP_NOSIZE))
          {
              // Move or Size command.
              // Windows tends to send erroneous events that the window
              // is about to move when the coordinates are exactly the
              // same as the last time.  This can cause problems with
              // our windowMoveLock CriticalSection because we enter it
              // here and never get to WM_WINDOWPOSCHANGED to release it.
              // So make sure this is a real move/size event before bothering
              // to grab the critical section.
              BOOL takeLock = FALSE;
              if (!(lpPosInfo->flags & SWP_NOMOVE) &&
                  ((windowMoveLockPosX != lpPosInfo->x) ||
                   (windowMoveLockPosY != lpPosInfo->y)))
              {
                  // Real move event
                  takeLock = TRUE;
                  windowMoveLockPosX = lpPosInfo->x;
                  windowMoveLockPosY = lpPosInfo->y;
              }
              if (!(lpPosInfo->flags & SWP_NOSIZE) &&
                  ((windowMoveLockPosCX != lpPosInfo->cx) ||
                   (windowMoveLockPosCY != lpPosInfo->cy)))
              {
                  // Real size event
                  takeLock = TRUE;
                  windowMoveLockPosCX = lpPosInfo->cx;
                  windowMoveLockPosCY = lpPosInfo->cy;
              }
              if (takeLock) {
                  if (!windowMoveLockHeld) {
                      windowMoveLock.Enter();
                      windowMoveLockHeld = TRUE;
                  }
              }
          }
          mr = WmWindowPosChanging(lParam);
          break;
      }
      case WM_WINDOWPOSCHANGED:
      {
          // Release lock grabbed in the POSCHANGING message
          if (windowMoveLockHeld) {
              windowMoveLockHeld = FALSE;
              windowMoveLock.Leave();
          }
          mr = WmWindowPosChanged(lParam);
          break;
      }
      case WM_MOVE: {
          RECT r;
          ::GetWindowRect(GetHWnd(), &r);
          mr = WmMove(r.left, r.top);
          break;
      }
      case WM_SIZE:
      {
          RECT r;
          // fix 4128317 : use GetClientRect for full 32-bit int precision and
          // to avoid negative client area dimensions overflowing 16-bit params - robi
          ::GetClientRect( GetHWnd(), &r );
          mr = WmSize(static_cast<UINT>(wParam), r.right - r.left, r.bottom - r.top);
          //mr = WmSize(wParam, LOWORD(lParam), HIWORD(lParam));
          SetCompositionWindow(r);
          break;
      }
      case WM_SIZING:
          mr = WmSizing();
          break;
      case WM_SHOWWINDOW:
          mr = WmShowWindow(static_cast<BOOL>(wParam),
                            static_cast<UINT>(lParam)); break;
      case WM_SYSCOMMAND:
          mr = WmSysCommand(static_cast<UINT>(wParam & 0xFFF0),
                            GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
          break;
      case WM_EXITSIZEMOVE:
          mr = WmExitSizeMove();
          break;
      // Bug #4039858 (Selecting menu item causes bogus mouse click event)
      case WM_ENTERMENULOOP:
          mr = WmEnterMenuLoop((BOOL)wParam);
          sm_bMenuLoop = TRUE;
          // we need to release grab if menu is shown
          if (AwtWindow::GetGrabbedWindow() != NULL) {
              AwtWindow::GetGrabbedWindow()->Ungrab();
          }
          break;
      case WM_EXITMENULOOP:
          mr = WmExitMenuLoop((BOOL)wParam);
          sm_bMenuLoop = FALSE;
          break;

      // We don't expect any focus messages on non-proxy component,
      // except those that came from Java.
      case WM_SETFOCUS:
          if (sm_inSynthesizeFocus) {
              mr = WmSetFocus((HWND)wParam);
          } else {
              mr = mrConsume;
          }
          break;
      case WM_KILLFOCUS:
          if (sm_inSynthesizeFocus) {
              mr = WmKillFocus((HWND)wParam);
          } else {
              mr = mrConsume;
          }
          break;
      case WM_ACTIVATE: {
          UINT nState = LOWORD(wParam);
          BOOL fMinimized = (BOOL)HIWORD(wParam);
          mr = mrConsume;

          if (!sm_suppressFocusAndActivation &&
              (!fMinimized || (nState == WA_INACTIVE)))
          {
              mr = WmActivate(nState, fMinimized, (HWND)lParam);

              // When the window is deactivated, send WM_IME_ENDCOMPOSITION
              // message to deactivate the composition window so that
              // it won't receive keyboard input focus.
              HIMC hIMC;
              HWND hwnd = ImmGetHWnd();
              if ((hIMC = ImmGetContext(hwnd)) != NULL) {
                  ImmReleaseContext(hwnd, hIMC);
                  DefWindowProc(WM_IME_ENDCOMPOSITION, 0, 0);
              }
          }
          break;
      }
      case WM_MOUSEACTIVATE: {
          AwtWindow *window = GetContainer();
          if (window && window->IsFocusableWindow()) {
              // AWT/Swing will later request focus to a proper component
              // on handling the Java mouse event. Anyway, we have to
              // activate the window here as it works both for AWT & Swing.
              // Do it in our own fassion,
              window->AwtSetActiveWindow(TRUE, LOWORD(lParam)/*hittest*/);
          }
          mr = mrConsume;
          retValue = MA_NOACTIVATE;
          break;
      }
      case WM_CTLCOLORMSGBOX:
      case WM_CTLCOLOREDIT:
      case WM_CTLCOLORLISTBOX:
      case WM_CTLCOLORBTN:
      case WM_CTLCOLORDLG:
      case WM_CTLCOLORSCROLLBAR:
      case WM_CTLCOLORSTATIC:
          mr = WmCtlColor((HDC)wParam, (HWND)lParam,
                          message-WM_CTLCOLORMSGBOX+CTLCOLOR_MSGBOX,
                          *(HBRUSH*)&retValue);
          break;
      case WM_HSCROLL:
          mr = WmHScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
          break;
      case WM_VSCROLL:
          mr = WmVScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
          break;
      // 4664415: We're seeing a WM_LBUTTONUP when the user releases the
      // mouse button after a WM_NCLBUTTONDBLCLK.  We want to ignore this
      // WM_LBUTTONUP, so we set a flag in WM_NCLBUTTONDBLCLK and look for the
      // flag on a WM_LBUTTONUP.  -bchristi
      case WM_NCLBUTTONDBLCLK:
          mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON | DBL_CLICK);
          if (mr == mrDoDefault) {
              ignoreNextLBTNUP = TRUE;
          }
          break;
      case WM_NCLBUTTONDOWN:
          mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
          ignoreNextLBTNUP = FALSE;
          break;
      case WM_NCLBUTTONUP:
          mr = WmNcMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
          break;
      case WM_NCRBUTTONDOWN:
           mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
           break;
      case WM_LBUTTONUP:
          if (ignoreNextLBTNUP) {
              ignoreNextLBTNUP = FALSE;
              return mrDoDefault;
          }
          //fall-through
      case WM_LBUTTONDOWN:
          ignoreNextLBTNUP = FALSE;
          //fall-through
      case WM_LBUTTONDBLCLK:
      case WM_RBUTTONDOWN:
      case WM_RBUTTONDBLCLK:
      case WM_RBUTTONUP:
      case WM_MBUTTONDOWN:
      case WM_MBUTTONDBLCLK:
      case WM_MBUTTONUP:
      case WM_XBUTTONDBLCLK:
      case WM_XBUTTONDOWN:
      case WM_XBUTTONUP:
      case WM_MOUSEMOVE:
      case WM_MOUSEWHEEL:
      case WM_AWT_MOUSEENTER:
      case WM_AWT_MOUSEEXIT:
          curPos = ::GetMessagePos();
          POINT myPos;
          myPos.x = GET_X_LPARAM(curPos);
          myPos.y = GET_Y_LPARAM(curPos);
          ::ScreenToClient(GetHWnd(), &myPos);
          switch(switchMessage) {
          case WM_AWT_MOUSEENTER:
              mr = WmMouseEnter(static_cast<UINT>(wParam), myPos.x, myPos.y);
              break;
          case WM_LBUTTONDOWN:
          case WM_LBUTTONDBLCLK:
              mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
                               LEFT_BUTTON);
              break;
          case WM_LBUTTONUP:
              mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
                             LEFT_BUTTON);
              break;
          case WM_MOUSEMOVE:
              mr = WmMouseMove(static_cast<UINT>(wParam), myPos.x, myPos.y);
              break;
          case WM_MBUTTONDOWN:
          case WM_MBUTTONDBLCLK:
              mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
                               MIDDLE_BUTTON);
              break;
          case WM_XBUTTONDOWN:
          case WM_XBUTTONDBLCLK:
              if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
                  if (HIWORD(wParam) == 1) {
                      mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
                                       X1_BUTTON);
                  }
                  if (HIWORD(wParam) == 2) {
                      mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
                                       X2_BUTTON);
                  }
              }
              break;
          case WM_XBUTTONUP:
              if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
                  if (HIWORD(wParam) == 1) {
                      mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
                                     X1_BUTTON);
                  }
                  if (HIWORD(wParam) == 2) {
                      mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
                                     X2_BUTTON);
                  }
              }
              break;
          case WM_RBUTTONDOWN:
          case WM_RBUTTONDBLCLK:
              mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
                               RIGHT_BUTTON);
              break;
          case WM_RBUTTONUP:
              mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
                             RIGHT_BUTTON);
              break;
          case WM_MBUTTONUP:
              mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
                             MIDDLE_BUTTON);
              break;
          case WM_AWT_MOUSEEXIT:
              mr = WmMouseExit(static_cast<UINT>(wParam), myPos.x, myPos.y);
              break;
          case  WM_MOUSEWHEEL:
              mr = WmMouseWheel(GET_KEYSTATE_WPARAM(wParam),
                                GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
                                GET_WHEEL_DELTA_WPARAM(wParam));
              break;
          }
          break;
      case WM_SETCURSOR:
          mr = mrDoDefault;
          if (LOWORD(lParam) == HTCLIENT) {
              if (AwtComponent* comp =
                                    AwtComponent::GetComponent((HWND)wParam)) {
                  AwtCursor::UpdateCursor(comp);
                  mr = mrConsume;
              }
          }
          break;

      case WM_KEYDOWN:
          mr = WmKeyDown(static_cast<UINT>(wParam),
                         LOWORD(lParam), HIWORD(lParam), FALSE);
          break;
      case WM_KEYUP:
          mr = WmKeyUp(static_cast<UINT>(wParam),
                       LOWORD(lParam), HIWORD(lParam), FALSE);
          break;
      case WM_SYSKEYDOWN:
          mr = WmKeyDown(static_cast<UINT>(wParam),
                         LOWORD(lParam), HIWORD(lParam), TRUE);
          break;
      case WM_SYSKEYUP:
          mr = WmKeyUp(static_cast<UINT>(wParam),
                       LOWORD(lParam), HIWORD(lParam), TRUE);
          break;
      case WM_IME_SETCONTEXT:
          // lParam is passed as pointer and it can be modified.
          mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam);
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      case WM_IME_NOTIFY:
          mr = WmImeNotify(wParam, lParam);
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      case WM_IME_STARTCOMPOSITION:
          mr = WmImeStartComposition();
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      case WM_IME_ENDCOMPOSITION:
          mr = WmImeEndComposition();
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      case WM_IME_COMPOSITION: {
          WORD dbcschar = static_cast<WORD>(wParam);
          mr = WmImeComposition(dbcschar, lParam);
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      }
      case WM_IME_CONTROL:
      case WM_IME_COMPOSITIONFULL:
      case WM_IME_SELECT:
      case WM_IME_KEYUP:
      case WM_IME_KEYDOWN:
      case WM_IME_REQUEST:
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      case WM_CHAR:
          mr = WmChar(static_cast<UINT>(wParam),
                      LOWORD(lParam), HIWORD(lParam), FALSE);
          break;
      case WM_SYSCHAR:
          mr = WmChar(static_cast<UINT>(wParam),
                      LOWORD(lParam), HIWORD(lParam), TRUE);
          break;
      case WM_IME_CHAR:
          mr = WmIMEChar(static_cast<UINT>(wParam),
                         LOWORD(lParam), HIWORD(lParam), FALSE);
          break;

      case WM_INPUTLANGCHANGEREQUEST: {
          DTRACE_PRINTLN4("WM_INPUTLANGCHANGEREQUEST: hwnd = 0x%X (%s);"//
                          "0x%08X -> 0x%08X",
                          GetHWnd(), GetClassName(),
                          (UINT_PTR)GetKeyboardLayout(), (UINT_PTR)lParam);
          // 4267428: make sure keyboard layout is turned undead.
          static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
          AwtToolkit::GetKeyboardState(keyboardState);
          WORD ignored;
          ::ToAsciiEx(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0),
                      keyboardState, &ignored, 0, GetKeyboardLayout());

          // Set this flag to block ActivateKeyboardLayout from
          // WInputMethod.activate()
          g_bUserHasChangedInputLang = TRUE;
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          break;
      }
      case WM_INPUTLANGCHANGE:
          DTRACE_PRINTLN3("WM_INPUTLANGCHANGE: hwnd = 0x%X (%s);"//
                          "new = 0x%08X",
                          GetHWnd(), GetClassName(), (UINT)lParam);
          mr = WmInputLangChange(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
          CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
          // should return non-zero if we process this message
          retValue = 1;
          break;

      case WM_AWT_FORWARD_CHAR:
          mr = WmForwardChar(LOWORD(wParam), lParam, HIWORD(wParam));
          break;

      case WM_AWT_FORWARD_BYTE:
          mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
          break;

      case WM_PASTE:
          mr = WmPaste();
          break;
      case WM_TIMER:
          mr = WmTimer(wParam);
          break;

      case WM_COMMAND:
          mr = WmCommand(LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
          break;
      case WM_COMPAREITEM:
          mr = WmCompareItem(static_cast<UINT>(wParam),
                             *(COMPAREITEMSTRUCT*)lParam, retValue);
          break;
      case WM_DELETEITEM:
          mr = WmDeleteItem(static_cast<UINT>(wParam),
                            *(DELETEITEMSTRUCT*)lParam);
          break;
      case WM_DRAWITEM:
          mr = WmDrawItem(static_cast<UINT>(wParam),
                          *(DRAWITEMSTRUCT*)lParam);
          break;
      case WM_MEASUREITEM:
          mr = WmMeasureItem(static_cast<UINT>(wParam),
                             *(MEASUREITEMSTRUCT*)lParam);
          break;

      case WM_AWT_HANDLE_EVENT:
          mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
          break;

      case WM_PRINT:
          mr = WmPrint((HDC)wParam, lParam);
          break;
      case WM_PRINTCLIENT:
          mr = WmPrintClient((HDC)wParam, lParam);
          break;

      case WM_NCCALCSIZE:
          mr = WmNcCalcSize((BOOL)wParam, (LPNCCALCSIZE_PARAMS)lParam,
                            retValue);
          break;
      case WM_NCPAINT:
          mr = WmNcPaint((HRGN)wParam);
          break;
      case WM_NCHITTEST:
          mr = WmNcHitTest(LOWORD(lParam), HIWORD(lParam), retValue);
          break;

      case WM_AWT_RESHAPE_COMPONENT: {
          RECT* r = (RECT*)lParam;
          WPARAM checkEmbedded = wParam;
          if (checkEmbedded == CHECK_EMBEDDED && IsEmbeddedFrame()) {
              ::OffsetRect(r, -r->left, -r->top);
          }
          Reshape(r->left, r->top, r->right - r->left, r->bottom - r->top);
          delete r;
          mr = mrConsume;
          break;
      }

      case WM_AWT_SETALWAYSONTOP: {
        AwtWindow* w = (AwtWindow*)lParam;
        BOOL value = (BOOL)wParam;
        UINT flags = SWP_NOMOVE | SWP_NOSIZE;
        // transient windows shouldn't change the owner window's position in the z-order
        if (w->IsRetainingHierarchyZOrder()) {
            flags |= SWP_NOOWNERZORDER;
        }
        ::SetWindowPos(w->GetHWnd(), (value != 0 ? HWND_TOPMOST : HWND_NOTOPMOST),
                       0,0,0,0, flags);
        break;
      }

      case WM_AWT_BEGIN_VALIDATE:
          BeginValidate();
          mr = mrConsume;
          break;
      case WM_AWT_END_VALIDATE:
          EndValidate();
          mr = mrConsume;
          break;

      case WM_PALETTEISCHANGING:
          mr = WmPaletteIsChanging((HWND)wParam);
          mr = mrDoDefault;
          break;
      case WM_QUERYNEWPALETTE:
          mr = WmQueryNewPalette(retValue);
          break;
      case WM_PALETTECHANGED:
          mr = WmPaletteChanged((HWND)wParam);
          break;
      case WM_STYLECHANGED:
          mr = WmStyleChanged(static_cast<int>(wParam), (LPSTYLESTRUCT)lParam);
          break;
      case WM_SETTINGCHANGE:
          CheckFontSmoothingSettings(NULL);
          mr = WmSettingChange(static_cast<UINT>(wParam), (LPCTSTR)lParam);
          break;
      case WM_CONTEXTMENU:
          mr = WmContextMenu((HWND)wParam,
                             GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
          break;

          /*
           * These messages are used to route Win32 calls to the
           * creating thread, since these calls fail unless executed
           * there.
           */
      case WM_AWT_COMPONENT_SHOW:
          Show();
          mr = mrConsume;
          break;
      case WM_AWT_COMPONENT_HIDE:
          Hide();
          mr = mrConsume;
          break;

      case WM_AWT_COMPONENT_SETFOCUS:
          if ((BOOL)wParam) {
              retValue = SynthesizeWmSetFocus(GetHWnd(), NULL);
          } else {
              retValue = SynthesizeWmKillFocus(GetHWnd(), NULL);
          }
          mr = mrConsume;
          break;
      case WM_AWT_WINDOW_SETACTIVE:
          retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam);
          mr = mrConsume;
          break;

      case WM_AWT_SET_SCROLL_INFO: {
          SCROLLINFO *si = (SCROLLINFO *) lParam;
          ::SetScrollInfo(GetHWnd(), (int) wParam, si, TRUE);
          delete si;
          mr = mrConsume;
          break;
      }
      case WM_AWT_CREATE_PRINTED_PIXELS: {
          CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam;
          SIZE loc = { cpps->srcx, cpps->srcy };
          SIZE size = { cpps->srcw, cpps->srch };
          retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha);
          mr = mrConsume;
          break;
      }
      case WM_UNDOCUMENTED_CLICKMENUBAR:
      {
          if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
              mr = mrConsume;
          }
      }
    }

    /*
     * If not a specific Consume, it was a specific DoDefault, or a
     * PassAlong (since the default is the next in chain), then call the
     * default proc.
     */
    if (mr != mrConsume) {
        retValue = DefWindowProc(message, wParam, lParam);
    }

    return retValue;
}
/*
 * Call this instance's default window proc, or if none set, call the stock
 * Window's one.
 */
LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
    return ComCtl32Util::GetInstance().DefWindowProc(m_DefWindowProc, GetHWnd(), msg, wParam, lParam);
}

/*
 * This message should only be received when a window is destroyed by
 * Windows, and not Java.  Window termination has been reworked so
 * this method should never be called during termination.
 */
MsgRouting AwtComponent::WmDestroy()
{
    return mrConsume;
}

/*
 * This message should only be received when a window is destroyed by
 * Windows, and not Java. It is sent only after child windows were destroyed.
 */
MsgRouting AwtComponent::WmNcDestroy()
{
    if (m_peerObject != NULL) { // is not being terminating
        // Stay in this handler until AwtComponent::Dispose is called.
        m_bPauseDestroy = TRUE;

        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        // Post invocation event for WObjectPeer.dispose to EDT
        env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID);
        // Wait until AwtComponent::Dispose is called
        AwtToolkit::GetInstance().PumpToDestroy(this);
    }

    return mrConsume;
}

MsgRouting AwtComponent::WmGetMinMaxInfo(LPMINMAXINFO lpmmi)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmMove(int x, int y)
{
    SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
        | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
    return mrDoDefault;
}

MsgRouting AwtComponent::WmSize(UINT type, int w, int h)
{
    SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
        | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
    return mrDoDefault;
}

MsgRouting AwtComponent::WmSizing()
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmSysCommand(UINT uCmdType, int xPos, int yPos)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmExitSizeMove()
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmEnterMenuLoop(BOOL isTrackPopupMenu)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmExitMenuLoop(BOOL isTrackPopupMenu)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmShowWindow(BOOL show, UINT status)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus)
{
    m_wheelRotationAmount = 0;
    return mrDoDefault;
}

MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus)
{
    m_wheelRotationAmount = 0;
    return mrDoDefault;
}

MsgRouting AwtComponent::WmCtlColor(HDC hDC, HWND hCtrl,
                                    UINT ctlColor, HBRUSH& retBrush)
{
    AwtComponent* child = AwtComponent::GetComponent(hCtrl);
    if (child) {
        ::SetBkColor(hDC, child->GetBackgroundColor());
        ::SetTextColor(hDC, child->GetColor());
        retBrush = child->GetBackgroundBrush();
        return mrConsume;
    }
    return mrDoDefault;
/*
    switch (ctlColor) {
        case CTLCOLOR_MSGBOX:
        case CTLCOLOR_EDIT:
        case CTLCOLOR_LISTBOX:
        case CTLCOLOR_BTN:
        case CTLCOLOR_DLG:
        case CTLCOLOR_SCROLLBAR:
        case CTLCOLOR_STATIC:
    }
*/
}

MsgRouting AwtComponent::WmHScroll(UINT scrollCode, UINT pos,
                                   HWND hScrollbar) {
    if (hScrollbar && hScrollbar != GetHWnd()) {
        /* the last test should never happen */
        AwtComponent* sb = GetComponent(hScrollbar);
        if (sb) {
            sb->WmHScroll(scrollCode, pos, hScrollbar);
        }
    }
    return mrDoDefault;
}

MsgRouting AwtComponent::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
{
    if (hScrollbar && hScrollbar != GetHWnd()) {
        /* the last test should never happen */
        AwtComponent* sb = GetComponent(hScrollbar);
        if (sb) {
            sb->WmVScroll(scrollCode, pos, hScrollbar);
        }
    }
    return mrDoDefault;
}


MsgRouting AwtComponent::WmPaint(HDC)
{
    /* Get the rectangle that covers all update regions, if any exist. */
    RECT r;
    if (::GetUpdateRect(GetHWnd(), &r, FALSE)) {
        if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0 &&
            m_peerObject != NULL && m_callbacksEnabled) {
            /*
             * Always call handlePaint, because the underlying control
             * will have painted itself (the "background") before any
             * paint method is called.
             */
            DoCallback("handlePaint", "(IIII)V",
                       r.left, r.top, r.right-r.left, r.bottom-r.top);
        }
    }
    return mrDoDefault;
}

void AwtComponent::PaintUpdateRgn(const RECT *insets)
{
    // Fix 4530093: Don't Validate if can't actually paint
    if (m_peerObject == NULL || !m_callbacksEnabled) {

        // Fix 4745222: If we don't ValidateRgn,  windows will keep sending
        // WM_PAINT messages until we do. This causes java to go into
        // a tight loop that increases CPU to 100% and starves main
        // thread which needs to complete initialization, but cant.
        ::ValidateRgn(GetHWnd(), NULL);

        return;
    }

    HRGN rgn = ::CreateRectRgn(0,0,1,1);
    int updated = ::GetUpdateRgn(GetHWnd(), rgn, FALSE);
    /*
     * Now remove all update regions from this window -- do it
     * here instead of after the Java upcall, in case any new
     * updating is requested.
     */
    ::ValidateRgn(GetHWnd(), NULL);

    if (updated == COMPLEXREGION || updated == SIMPLEREGION) {
        if (insets != NULL) {
            ::OffsetRgn(rgn, insets->left, insets->top);
        }
        DWORD size = ::GetRegionData(rgn, 0, NULL);
        if (size == 0) {
            ::DeleteObject((HGDIOBJ)rgn);
            return;
        }
        char* buffer = new char[size]; // safe because sizeof(char)==1
        memset(buffer, 0, size);
        LPRGNDATA rgndata = (LPRGNDATA)buffer;
        rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
        rgndata->rdh.iType = RDH_RECTANGLES;
        int retCode = ::GetRegionData(rgn, size, rgndata);
        VERIFY(retCode);
        if (retCode == 0) {
            delete [] buffer;
            ::DeleteObject((HGDIOBJ)rgn);
            return;
        }
        /*
         * Updating rects are divided into mostly vertical and mostly horizontal
         * Each group is united together and if not empty painted separately
         */
        RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize);
        RECT* un[2] = {0, 0};
    DWORD i;
    for (i = 0; i < rgndata->rdh.nCount; i++, r++) {
            int width = r->right-r->left;
            int height = r->bottom-r->top;
            if (width > 0 && height > 0) {
                int toAdd = (width > height) ? 0: 1;
                if (un[toAdd] != 0) {
                    ::UnionRect(un[toAdd], un[toAdd], r);
                } else {
                    un[toAdd] = r;
                }
            }
        }
        for(i = 0; i < 2; i++) {
            if (un[i] != 0) {
                DoCallback("handleExpose", "(IIII)V",
                           ScaleDownX(un[i]->left),
                           ScaleDownY(un[i]->top),
                           ScaleDownX(un[i]->right - un[i]->left),
                           ScaleDownY(un[i]->bottom - un[i]->top));
            }
        }
        delete [] buffer;
    }
    ::DeleteObject((HGDIOBJ)rgn);
}

MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y)
{
    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED,
                   ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(), 0, JNI_FALSE);
    if ((flags & ALL_MK_BUTTONS) == 0) {
        AwtCursor::UpdateCursor(this);
    }
    sm_cursorOn = GetHWnd();
    return mrConsume;   /* Don't pass our synthetic event on! */
}

MSG*
AwtComponent::CreateMessage(UINT message, WPARAM wParam, LPARAM lParam,
                            int x = 0, int y = 0)
{
    MSG* pMsg = new MSG;
    InitMessage(pMsg, message, wParam, lParam, x, y);
    return pMsg;
}


jint
AwtComponent::GetDrawState(HWND hwnd) {
    return (jint)(INT_PTR)(::GetProp(hwnd, DrawingStateProp));
}

void
AwtComponent::SetDrawState(HWND hwnd, jint state) {
    ::SetProp(hwnd, DrawingStateProp, (HANDLE)(INT_PTR)state);
}

void
AwtComponent::InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam,
                            int x = 0, int y = 0)
{
    msg->message = message;
    msg->wParam = wParam;
    msg->lParam = lParam;
    msg->time = ::GetMessageTime();
    msg->pt.x = x;
    msg->pt.y = y;
}

MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
    return mrDoDefault;
}
MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
    return mrDoDefault;
}

MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
    return mrDoDefault;
}
MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) {
    return mrDoDefault;
}

/* Double-click variables. */
static jlong multiClickTime = ::GetDoubleClickTime();
static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
static AwtComponent* lastClickWnd = NULL;
static jlong lastTime = 0;
static int lastClickX = 0;
static int lastClickY = 0;
static int lastButton = 0;
static int clickCount = 0;

// A static method that makes the clickCount available in the derived classes
// overriding WmMouseDown().
int AwtComponent::GetClickCount()
{
    return clickCount;
}

MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
{
    jlong now = ::JVM_CurrentTimeMillis(NULL, 0);

    if (lastClickWnd == this &&
        lastButton == button &&
        (now - lastTime) <= multiClickTime &&
        abs(x - lastClickX) <= multiClickMaxX &&
        abs(y - lastClickY) <= multiClickMaxY)
    {
        clickCount++;
    } else {
        clickCount = 1;
        lastClickWnd = this;
        lastButton = button;
        lastClickX = x;
        lastClickY = y;
    }
    /*
     *Set appropriate bit of the mask on WM_MOUSE_DOWN message.
     */
    m_mouseButtonClickAllowed |= GetButtonMK(button);
    lastTime = now;

    MSG msg;
    InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    AwtWindow *toplevel = GetContainer();
    if (toplevel && !toplevel->IsSimpleWindow()) {
        /*
         * The frame should be focused by click in case it is
         * the active window but not the focused window. See 6886678.
         */
        if (toplevel->GetHWnd() == ::GetActiveWindow() &&
            toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
        {
            toplevel->AwtSetActiveWindow();
        }
    }

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
                   GetJavaModifiers(), clickCount, JNI_FALSE,
                   GetButton(button), &msg);
    /*
     * NOTE: this call is intentionally placed after all other code,
     * since AwtComponent::WmMouseDown() assumes that the cached id of the
     * latest retrieved message (see lastMessage in awt_Component.cpp)
     * matches the mouse message being processed.
     * SetCapture() sends WM_CAPTURECHANGED and breaks that
     * assumption.
     */
    SetDragCapture(flags);

    AwtWindow * owner = (AwtWindow*)GetComponent(GetTopLevelParentForWindow(GetHWnd()));
    if (AwtWindow::GetGrabbedWindow() != NULL && owner != NULL) {
        if (!AwtWindow::GetGrabbedWindow()->IsOneOfOwnersOf(owner)) {
            AwtWindow::GetGrabbedWindow()->Ungrab();
        }
    }
    return mrConsume;
}

MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button)
{
    MSG msg;
    InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, ::JVM_CurrentTimeMillis(NULL, 0),
                   x, y, GetJavaModifiers(), clickCount,
                   (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                    TRUE : FALSE), GetButton(button), &msg);
    /*
     * If no movement, then report a click following the button release.
     * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN,
     * spurous MOUSE_CLICK is about to happen. See 6430553.
     */
    if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
        SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
                       ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(),
                       clickCount, JNI_FALSE, GetButton(button));
    }
    // Exclude button from allowed to generate CLICK messages
    m_mouseButtonClickAllowed &= ~GetButtonMK(button);

    if ((flags & ALL_MK_BUTTONS) == 0) {
        // only update if all buttons have been released
        AwtCursor::UpdateCursor(this);
    }
    /*
     * NOTE: this call is intentionally placed after all other code,
     * since AwtComponent::WmMouseUp() assumes that the cached id of the
     * latest retrieved message (see lastMessage in awt_Component.cpp)
     * matches the mouse message being processed.
     * ReleaseCapture() sends WM_CAPTURECHANGED and breaks that
     * assumption.
     */
    ReleaseDragCapture(flags);

    return mrConsume;
}

MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y)
{
    static AwtComponent* lastComp = NULL;
    static int lastX = 0;
    static int lastY = 0;

    /*
     * Only report mouse move and drag events if a move or drag
     * actually happened -- Windows sends a WM_MOUSEMOVE in case the
     * app wants to modify the cursor.
     */
    if (lastComp != this || x != lastX || y != lastY) {
        lastComp = this;
        lastX = x;
        lastY = y;
        BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled();
        if (((flags & (ALL_MK_BUTTONS)) != 0) ||
            (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0))
//        if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) ||
//            ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) ))
        {
            // 6404008 : if Dragged event fired we shouldn't fire
            // Clicked event: m_firstDragSent set to TRUE.
            // This is a partial backout of 5039416 fix.
            MSG msg;
            InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
                           GetJavaModifiers(), 0, JNI_FALSE,
                           java_awt_event_MouseEvent_NOBUTTON, &msg);
            //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
            m_mouseButtonClickAllowed = 0;
        } else {
            MSG msg;
            InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
                           GetJavaModifiers(), 0, JNI_FALSE,
                           java_awt_event_MouseEvent_NOBUTTON, &msg);
        }
    }

    return mrConsume;
}

MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y)
{
    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, ::JVM_CurrentTimeMillis(NULL, 0), x,
                   y, GetJavaModifiers(), 0, JNI_FALSE);
    sm_cursorOn = NULL;
    return mrConsume;   /* Don't pass our synthetic event on! */
}

MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
                                      int wheelRotation)
{
    // convert coordinates to be Component-relative, not screen relative
    // for wheeling when outside the window, this works similar to
    // coordinates during a drag
    POINT eventPt;
    eventPt.x = x;
    eventPt.y = y;
    DTRACE_PRINT2("  original coords: %i,%i\n", x, y);
    ::ScreenToClient(GetHWnd(), &eventPt);
    DTRACE_PRINT2("  new coords: %i,%i\n\n", eventPt.x, eventPt.y);

    // set some defaults
    jint scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
    jint scrollLines = 3;

    BOOL result;
    UINT platformLines;

    m_wheelRotationAmount += wheelRotation;

    // AWT interprets wheel rotation differently than win32, so we need to
    // decode wheel amount.
    jint roundedWheelRotation = m_wheelRotationAmount / (-1 * WHEEL_DELTA);
    jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA);

    MSG msg;
    result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
                                    &platformLines, 0);
    InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation),
                MAKELPARAM(x, y));

    if (result) {
        if (platformLines == WHEEL_PAGESCROLL) {
            scrollType = java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL;
            scrollLines = 1;
        }
        else {
            scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
            scrollLines = platformLines;
        }
    }

    DTRACE_PRINTLN("calling SendMouseWheelEvent");

    SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, ::JVM_CurrentTimeMillis(NULL, 0),
                        eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
                        scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);

    m_wheelRotationAmount %= WHEEL_DELTA;
    // this message could be propagated up to the parent chain
    // by the mouse message post processors
    return mrConsume;
}

jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) {
    // Rector+Newcomer page 413
    // The extended keys are the Alt and Control on the right of
    // the space bar, the non-Numpad arrow keys, the non-Numpad
    // Insert, PageUp, etc. keys, and the Numpad Divide and Enter keys.
    // Note that neither Shift key is extended.
    // Although not listed in Rector+Newcomer, both Windows keys
    // (91 and 92) are extended keys, the Context Menu key
    // (property key or application key - 93) is extended,
    // and so is the NumLock key.

    // wkey is the wParam, flags is the HIWORD of the lParam

    // "Extended" bit is 24th in lParam, so it's 8th in flags = HIWORD(lParam)
    BOOL extended = ((1<<8) & flags);

    if (IsNumPadKey(wkey, extended)) {
        return java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
    }

    switch (wkey) {
      case VK_SHIFT:
        return AwtComponent::GetShiftKeyLocation(wkey, flags);
      case VK_CONTROL: // fall through
      case VK_MENU:
        if (extended) {
            return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
        } else {
            return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
        }
      case VK_LWIN:
        return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
      case VK_RWIN:
        return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
      default:
        break;
    }

    // REMIND: if we add keycodes for the windows keys, we'll have to
    // include left/right discrimination code for them.

    return java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
}

jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags)
{
    // init scancodes to safe values
    UINT leftShiftScancode = 0;
    UINT rightShiftScancode = 0;

    // First 8 bits of flags is the scancode
    UINT keyScanCode = flags & 0xFF;

    DTRACE_PRINTLN3(
      "AwtComponent::GetShiftKeyLocation  vkey = %d = 0x%x  scan = %d",
      vkey, vkey, keyScanCode);

    leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0);
    rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0);

    if (keyScanCode == leftShiftScancode) {
        return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
    }
    if (keyScanCode == rightShiftScancode) {
        return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
    }

    DASSERT(false);
    // Note: the above should not fail on NT (or 2000)

    // default value
    return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
}

/* Returns Java ActionEvent modifieres.
 * When creating ActionEvent, modifiers provided by ActionEvent
 * class should be set.
 */
jint
AwtComponent::GetActionModifiers()
{
    jint modifiers = GetJavaModifiers();

    if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
        modifiers |= java_awt_event_ActionEvent_CTRL_MASK;
    }
    if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
        modifiers |= java_awt_event_ActionEvent_SHIFT_MASK;
    }
    if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) {
        modifiers |= java_awt_event_ActionEvent_ALT_MASK;
    }
    return modifiers;
}

/* Returns Java extended InputEvent modifieres.
 * Since ::GetKeyState returns current state and Java modifiers represent
 * state before event, modifier on changed key are inverted.
 */
jint
AwtComponent::GetJavaModifiers()
{
    jint modifiers = 0;

    if (HIBYTE(::GetKeyState(VK_CONTROL)) != 0) {
        modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_SHIFT)) != 0) {
        modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_MENU)) != 0) {
        modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_RMENU)) != 0) {
        modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) {
       modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) {
        modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
    }
    if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) {
        modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
    }

    if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) {
        modifiers |= masks[3];
    }
    if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) {
        modifiers |= masks[4];
    }
    return modifiers;
}

jint
AwtComponent::GetButton(int mouseButton)
{
    /* Mouse buttons are already set correctly for left/right handedness */
    switch(mouseButton) {
    case LEFT_BUTTON:
        return java_awt_event_MouseEvent_BUTTON1;
    case MIDDLE_BUTTON:
        return java_awt_event_MouseEvent_BUTTON2;
    case RIGHT_BUTTON:
        return java_awt_event_MouseEvent_BUTTON3;
    case X1_BUTTON: //16 :
        //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now
        return 4;
    case X2_BUTTON: //32
        return 5;
    }
    return java_awt_event_MouseEvent_NOBUTTON;
}

UINT
AwtComponent::GetButtonMK(int mouseButton)
{
    switch(mouseButton) {
    case LEFT_BUTTON:
        return MK_LBUTTON;
    case MIDDLE_BUTTON:
        return MK_MBUTTON;
    case RIGHT_BUTTON:
        return MK_RBUTTON;
    case X1_BUTTON:
        return MK_XBUTTON1;
    case X2_BUTTON:
        return MK_XBUTTON2;
    }
    return 0;
}

// FIXME: Keyboard related stuff has grown so big and hairy that we
// really need to move it into a class of its own.  And, since
// keyboard is a shared resource, AwtComponent is a bad place for it.

// These constants are defined in the Japanese version of VC++5.0,
// but not the US version
#ifndef VK_CONVERT
#define VK_KANA           0x15
#define VK_KANJI          0x19
#define VK_CONVERT        0x1C
#define VK_NONCONVERT     0x1D
#endif

#ifndef VK_XBUTTON1
#define VK_XBUTTON1      0x05
#endif

#ifndef VK_XBUTTON2
#define VK_XBUTTON2      0x06
#endif

typedef struct {
    UINT javaKey;
    UINT windowsKey;
} KeyMapEntry;

// Static table, arranged more or less spatially.
KeyMapEntry keyMapTable[] = {
    // Modifier keys
    {java_awt_event_KeyEvent_VK_CAPS_LOCK,        VK_CAPITAL},
    {java_awt_event_KeyEvent_VK_SHIFT,            VK_SHIFT},
    {java_awt_event_KeyEvent_VK_CONTROL,          VK_CONTROL},
    {java_awt_event_KeyEvent_VK_ALT,              VK_MENU},
    {java_awt_event_KeyEvent_VK_ALT_GRAPH,        VK_RMENU},
    {java_awt_event_KeyEvent_VK_NUM_LOCK,         VK_NUMLOCK},

    // Miscellaneous Windows keys
    {java_awt_event_KeyEvent_VK_WINDOWS,          VK_LWIN},
    {java_awt_event_KeyEvent_VK_WINDOWS,          VK_RWIN},
    {java_awt_event_KeyEvent_VK_CONTEXT_MENU,     VK_APPS},

    // Alphabet
    {java_awt_event_KeyEvent_VK_A,                'A'},
    {java_awt_event_KeyEvent_VK_B,                'B'},
    {java_awt_event_KeyEvent_VK_C,                'C'},
    {java_awt_event_KeyEvent_VK_D,                'D'},
    {java_awt_event_KeyEvent_VK_E,                'E'},
    {java_awt_event_KeyEvent_VK_F,                'F'},
    {java_awt_event_KeyEvent_VK_G,                'G'},
    {java_awt_event_KeyEvent_VK_H,                'H'},
    {java_awt_event_KeyEvent_VK_I,                'I'},
    {java_awt_event_KeyEvent_VK_J,                'J'},
    {java_awt_event_KeyEvent_VK_K,                'K'},
    {java_awt_event_KeyEvent_VK_L,                'L'},
    {java_awt_event_KeyEvent_VK_M,                'M'},
    {java_awt_event_KeyEvent_VK_N,                'N'},
    {java_awt_event_KeyEvent_VK_O,                'O'},
    {java_awt_event_KeyEvent_VK_P,                'P'},
    {java_awt_event_KeyEvent_VK_Q,                'Q'},
    {java_awt_event_KeyEvent_VK_R,                'R'},
    {java_awt_event_KeyEvent_VK_S,                'S'},
    {java_awt_event_KeyEvent_VK_T,                'T'},
    {java_awt_event_KeyEvent_VK_U,                'U'},
    {java_awt_event_KeyEvent_VK_V,                'V'},
    {java_awt_event_KeyEvent_VK_W,                'W'},
    {java_awt_event_KeyEvent_VK_X,                'X'},
    {java_awt_event_KeyEvent_VK_Y,                'Y'},
    {java_awt_event_KeyEvent_VK_Z,                'Z'},

    // Standard numeric row
    {java_awt_event_KeyEvent_VK_0,                '0'},
    {java_awt_event_KeyEvent_VK_1,                '1'},
    {java_awt_event_KeyEvent_VK_2,                '2'},
    {java_awt_event_KeyEvent_VK_3,                '3'},
    {java_awt_event_KeyEvent_VK_4,                '4'},
    {java_awt_event_KeyEvent_VK_5,                '5'},
    {java_awt_event_KeyEvent_VK_6,                '6'},
    {java_awt_event_KeyEvent_VK_7,                '7'},
    {java_awt_event_KeyEvent_VK_8,                '8'},
    {java_awt_event_KeyEvent_VK_9,                '9'},

    // Misc key from main block
    {java_awt_event_KeyEvent_VK_ENTER,            VK_RETURN},
    {java_awt_event_KeyEvent_VK_SPACE,            VK_SPACE},
    {java_awt_event_KeyEvent_VK_BACK_SPACE,       VK_BACK},
    {java_awt_event_KeyEvent_VK_TAB,              VK_TAB},
    {java_awt_event_KeyEvent_VK_ESCAPE,           VK_ESCAPE},

    // NumPad with NumLock off & extended block (rectangular)
    {java_awt_event_KeyEvent_VK_INSERT,           VK_INSERT},
    {java_awt_event_KeyEvent_VK_DELETE,           VK_DELETE},
    {java_awt_event_KeyEvent_VK_HOME,             VK_HOME},
    {java_awt_event_KeyEvent_VK_END,              VK_END},
    {java_awt_event_KeyEvent_VK_PAGE_UP,          VK_PRIOR},
    {java_awt_event_KeyEvent_VK_PAGE_DOWN,        VK_NEXT},
    {java_awt_event_KeyEvent_VK_CLEAR,            VK_CLEAR}, // NumPad 5

    // NumPad with NumLock off & extended arrows block (triangular)
    {java_awt_event_KeyEvent_VK_LEFT,             VK_LEFT},
    {java_awt_event_KeyEvent_VK_RIGHT,            VK_RIGHT},
    {java_awt_event_KeyEvent_VK_UP,               VK_UP},
    {java_awt_event_KeyEvent_VK_DOWN,             VK_DOWN},

    // NumPad with NumLock on: numbers
    {java_awt_event_KeyEvent_VK_NUMPAD0,          VK_NUMPAD0},
    {java_awt_event_KeyEvent_VK_NUMPAD1,          VK_NUMPAD1},
    {java_awt_event_KeyEvent_VK_NUMPAD2,          VK_NUMPAD2},
    {java_awt_event_KeyEvent_VK_NUMPAD3,          VK_NUMPAD3},
    {java_awt_event_KeyEvent_VK_NUMPAD4,          VK_NUMPAD4},
    {java_awt_event_KeyEvent_VK_NUMPAD5,          VK_NUMPAD5},
    {java_awt_event_KeyEvent_VK_NUMPAD6,          VK_NUMPAD6},
    {java_awt_event_KeyEvent_VK_NUMPAD7,          VK_NUMPAD7},
    {java_awt_event_KeyEvent_VK_NUMPAD8,          VK_NUMPAD8},
    {java_awt_event_KeyEvent_VK_NUMPAD9,          VK_NUMPAD9},

    // NumPad with NumLock on
    {java_awt_event_KeyEvent_VK_MULTIPLY,         VK_MULTIPLY},
    {java_awt_event_KeyEvent_VK_ADD,              VK_ADD},
    {java_awt_event_KeyEvent_VK_SEPARATOR,        VK_SEPARATOR},
    {java_awt_event_KeyEvent_VK_SUBTRACT,         VK_SUBTRACT},
    {java_awt_event_KeyEvent_VK_DECIMAL,          VK_DECIMAL},
    {java_awt_event_KeyEvent_VK_DIVIDE,           VK_DIVIDE},

    // Functional keys
    {java_awt_event_KeyEvent_VK_F1,               VK_F1},
    {java_awt_event_KeyEvent_VK_F2,               VK_F2},
    {java_awt_event_KeyEvent_VK_F3,               VK_F3},
    {java_awt_event_KeyEvent_VK_F4,               VK_F4},
    {java_awt_event_KeyEvent_VK_F5,               VK_F5},
    {java_awt_event_KeyEvent_VK_F6,               VK_F6},
    {java_awt_event_KeyEvent_VK_F7,               VK_F7},
    {java_awt_event_KeyEvent_VK_F8,               VK_F8},
    {java_awt_event_KeyEvent_VK_F9,               VK_F9},
    {java_awt_event_KeyEvent_VK_F10,              VK_F10},
    {java_awt_event_KeyEvent_VK_F11,              VK_F11},
    {java_awt_event_KeyEvent_VK_F12,              VK_F12},
    {java_awt_event_KeyEvent_VK_F13,              VK_F13},
    {java_awt_event_KeyEvent_VK_F14,              VK_F14},
    {java_awt_event_KeyEvent_VK_F15,              VK_F15},
    {java_awt_event_KeyEvent_VK_F16,              VK_F16},
    {java_awt_event_KeyEvent_VK_F17,              VK_F17},
    {java_awt_event_KeyEvent_VK_F18,              VK_F18},
    {java_awt_event_KeyEvent_VK_F19,              VK_F19},
    {java_awt_event_KeyEvent_VK_F20,              VK_F20},
    {java_awt_event_KeyEvent_VK_F21,              VK_F21},
    {java_awt_event_KeyEvent_VK_F22,              VK_F22},
    {java_awt_event_KeyEvent_VK_F23,              VK_F23},
    {java_awt_event_KeyEvent_VK_F24,              VK_F24},

    {java_awt_event_KeyEvent_VK_PRINTSCREEN,      VK_SNAPSHOT},
    {java_awt_event_KeyEvent_VK_SCROLL_LOCK,      VK_SCROLL},
    {java_awt_event_KeyEvent_VK_PAUSE,            VK_PAUSE},
    {java_awt_event_KeyEvent_VK_CANCEL,           VK_CANCEL},
    {java_awt_event_KeyEvent_VK_HELP,             VK_HELP},

    // Japanese
    {java_awt_event_KeyEvent_VK_CONVERT,          VK_CONVERT},
    {java_awt_event_KeyEvent_VK_NONCONVERT,       VK_NONCONVERT},
    {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
    {java_awt_event_KeyEvent_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
    {java_awt_event_KeyEvent_VK_KATAKANA,         VK_DBE_KATAKANA},
    {java_awt_event_KeyEvent_VK_HIRAGANA,         VK_DBE_HIRAGANA},
    {java_awt_event_KeyEvent_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
    {java_awt_event_KeyEvent_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
    {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},

    {java_awt_event_KeyEvent_VK_UNDEFINED,        0}
};


// Dynamic mapping table for OEM VK codes.  This table is refilled
// by BuildDynamicKeyMapTable when keyboard layout is switched.
// (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
struct DynamicKeyMapEntry {
    UINT windowsKey;            // OEM VK codes known in advance
    UINT javaKey;               // depends on input langauge (kbd layout)
};

static DynamicKeyMapEntry dynamicKeyMapTable[] = {
    {0x00BA,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_1
    {0x00BB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PLUS
    {0x00BC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_COMMA
    {0x00BD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_MINUS
    {0x00BE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PERIOD
    {0x00BF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_2
    {0x00C0,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_3
    {0x00DB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_4
    {0x00DC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_5
    {0x00DD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_6
    {0x00DE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_7
    {0x00DF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_8
    {0x00E2,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_102
    {0, 0}
};



// Auxiliary tables used to fill the above dynamic table.  We first
// find the character for the OEM VK code using ::MapVirtualKey and
// then go through these auxiliary tables to map it to Java VK code.

struct CharToVKEntry {
    WCHAR c;
    UINT  javaKey;
};

static const CharToVKEntry charToVKTable[] = {
    {L'!',   java_awt_event_KeyEvent_VK_EXCLAMATION_MARK},
    {L'"',   java_awt_event_KeyEvent_VK_QUOTEDBL},
    {L'#',   java_awt_event_KeyEvent_VK_NUMBER_SIGN},
    {L'$',   java_awt_event_KeyEvent_VK_DOLLAR},
    {L'&',   java_awt_event_KeyEvent_VK_AMPERSAND},
    {L'\'',  java_awt_event_KeyEvent_VK_QUOTE},
    {L'(',   java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS},
    {L')',   java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS},
    {L'*',   java_awt_event_KeyEvent_VK_ASTERISK},
    {L'+',   java_awt_event_KeyEvent_VK_PLUS},
    {L',',   java_awt_event_KeyEvent_VK_COMMA},
    {L'-',   java_awt_event_KeyEvent_VK_MINUS},
    {L'.',   java_awt_event_KeyEvent_VK_PERIOD},
    {L'/',   java_awt_event_KeyEvent_VK_SLASH},
    {L':',   java_awt_event_KeyEvent_VK_COLON},
    {L';',   java_awt_event_KeyEvent_VK_SEMICOLON},
    {L'<',   java_awt_event_KeyEvent_VK_LESS},
    {L'=',   java_awt_event_KeyEvent_VK_EQUALS},
    {L'>',   java_awt_event_KeyEvent_VK_GREATER},
    {L'@',   java_awt_event_KeyEvent_VK_AT},
    {L'[',   java_awt_event_KeyEvent_VK_OPEN_BRACKET},
    {L'\\',  java_awt_event_KeyEvent_VK_BACK_SLASH},
    {L']',   java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
    {L'^',   java_awt_event_KeyEvent_VK_CIRCUMFLEX},
    {L'_',   java_awt_event_KeyEvent_VK_UNDERSCORE},
    {L'`',   java_awt_event_KeyEvent_VK_BACK_QUOTE},
    {L'{',   java_awt_event_KeyEvent_VK_BRACELEFT},
    {L'}',   java_awt_event_KeyEvent_VK_BRACERIGHT},
    {0x00A1, java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK},
    {0x20A0, java_awt_event_KeyEvent_VK_EURO_SIGN}, // ????
    {0,0}
};

// For dead accents some layouts return ASCII punctuation, while some
// return spacing accent chars, so both should be listed.  NB: MS docs
// say that conversion routings return spacing accent character, not
// combining.
static const CharToVKEntry charToDeadVKTable[] = {
    {L'`',   java_awt_event_KeyEvent_VK_DEAD_GRAVE},
    {L'\'',  java_awt_event_KeyEvent_VK_DEAD_ACUTE},
    {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
    {L'^',   java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
    {L'~',   java_awt_event_KeyEvent_VK_DEAD_TILDE},
    {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE},
    {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
    {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
    {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
    {L'"',   java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
    {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
    {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
    {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
    {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},            // aka hacek
    {L',',   java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
    {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
    {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
    {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},             // ASCII ???
    {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
    {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
    {0,0}
};

// The full map of the current keyboard state including
// windows virtual key, scancode, java virtual key, and unicode
// for this key sans modifiers.
// All but first element may be 0.
// XXX in the update releases this is an addition to the unchanged existing code
struct DynPrimaryKeymapEntry {
    UINT wkey;
    UINT scancode;
    UINT jkey;
    WCHAR unicode;
};

static DynPrimaryKeymapEntry dynPrimaryKeymap[256];

void
AwtComponent::InitDynamicKeyMapTable()
{
    static BOOL kbdinited = FALSE;

    if (!kbdinited) {
        AwtComponent::BuildDynamicKeyMapTable();
        // We cannot build it here since JNI is not available yet:
        //AwtComponent::BuildPrimaryDynamicTable();
        kbdinited = TRUE;
    }
}

void
AwtComponent::BuildDynamicKeyMapTable()
{
    HKL hkl = GetKeyboardLayout();

    DTRACE_PRINTLN2("Building dynamic VK mapping tables: HKL = %08X (CP%d)",
                    hkl, AwtComponent::GetCodePage());

    // Will need this to reset layout after dead keys.
    UINT spaceScanCode = ::MapVirtualKeyEx(VK_SPACE, 0, hkl);

    // Entries in dynamic table that maps between Java VK and Windows
    // VK are built in three steps:
    //   1. Map windows VK to ANSI character (cannot map to unicode
    //      directly, since ::ToUnicode is not implemented on win9x)
    //   2. Convert ANSI char to Unicode char
    //   3. Map Unicode char to Java VK via two auxilary tables.

    for (DynamicKeyMapEntry *dynamic = dynamicKeyMapTable;
         dynamic->windowsKey != 0;
         ++dynamic)
    {
        // Defaults to VK_UNDEFINED
        dynamic->javaKey = java_awt_event_KeyEvent_VK_UNDEFINED;

        BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
        AwtToolkit::GetKeyboardState(kbdState);

        kbdState[dynamic->windowsKey] |=  0x80; // Press the key.

        // Unpress modifiers, since they are most likely pressed as
        // part of the keyboard switching shortcut.
        kbdState[VK_CONTROL] &= ~0x80;
        kbdState[VK_SHIFT]   &= ~0x80;
        kbdState[VK_MENU]    &= ~0x80;

        char cbuf[2] = { '\0', '\0'};
        UINT scancode = ::MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
        int nchars = ::ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
                                 (WORD*)cbuf, 0, hkl);

        // Auxiliary table used to map Unicode character to Java VK.
        // Will assign a different table for dead keys (below).
        const CharToVKEntry *charMap = charToVKTable;

        if (nchars < 0) { // Dead key
            // Use a different table for dead chars since different layouts
            // return different characters for the same dead key.
            charMap = charToDeadVKTable;

            // We also need to reset layout so that next translation
            // is unaffected by the dead status.  We do this by
            // translating <SPACE> key.
            kbdState[dynamic->windowsKey] &= ~0x80;
            kbdState[VK_SPACE] |= 0x80;

            char junkbuf[2] = { '\0', '\0'};
            ::ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
                        (WORD*)junkbuf, 0, hkl);
        }

#ifdef DEBUG
        if (nchars == 0) {
            DTRACE_PRINTLN1("VK 0x%02X -> cannot convert to ANSI char",
                            dynamic->windowsKey);
            continue;
        }
        else if (nchars > 1) {  // can't happen, see reset code below
            DTRACE_PRINTLN3("VK 0x%02X -> converted to <0x%02X,0x%02X>",
                            dynamic->windowsKey,
                            (UCHAR)cbuf[0], (UCHAR)cbuf[1]);
            continue;
        }
#endif

        WCHAR ucbuf[2] = { L'\0', L'\0' };
        int nconverted = ::MultiByteToWideChar(AwtComponent::GetCodePage(), 0,
                                               cbuf, 1, ucbuf, 2);
#ifdef DEBUG
        if (nconverted < 0) {
            DTRACE_PRINTLN3("VK 0x%02X -> ANSI 0x%02X -> MultiByteToWideChar failed (0x%X)",
                            dynamic->windowsKey, (UCHAR)cbuf[0],
                            ::GetLastError());
            continue;
        }
#endif

        WCHAR uc = ucbuf[0];
        for (const CharToVKEntry *map = charMap;  map->c != 0;  ++map) {
            if (uc == map->c) {
                dynamic->javaKey = map->javaKey;
                break;
            }
        }

        DTRACE_PRINTLN4("VK 0x%02X -> ANSI 0x%02X -> U+%04X -> Java VK 0x%X",
                        dynamic->windowsKey, (UCHAR)cbuf[0], (UINT)ucbuf[0],
                        dynamic->javaKey);
    } // for each VK_OEM_*
}


static BOOL isKanaLockAvailable()
{
    // This method is to determine whether the Kana Lock feature is
    // available on the attached keyboard.  Kana Lock feature does not
    // necessarily require that the real KANA keytop is available on
    // keyboard, so using MapVirtualKey(VK_KANA) is not sufficient for testing.
    // Instead of that we regard it as Japanese keyboard (w/ Kana Lock) if :-
    //
    // - the keyboard layout is Japanese (VK_KANA has the same value as VK_HANGUL)
    // - the keyboard is Japanese keyboard (keyboard type == 7).
    return (LOWORD(GetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
        && (GetKeyboardType(0) == 7);
}

void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
                                       UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey)
{
    // Handle the few cases where a Java VK code corresponds to a Windows
    // key/modifier combination or applies only to specific keyboard layouts
    switch (javaKey) {
        case java_awt_event_KeyEvent_VK_ALL_CANDIDATES:
            *windowsKey = VK_CONVERT;
            *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
            return;
        case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE:
            *windowsKey = VK_CONVERT;
            *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK;
            return;
        case java_awt_event_KeyEvent_VK_CODE_INPUT:
            *windowsKey = VK_DBE_ALPHANUMERIC;
            *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
            return;
        case java_awt_event_KeyEvent_VK_KANA_LOCK:
            if (isKanaLockAvailable()) {
                *windowsKey = VK_KANA;
                *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK;
                return;
            }
    }

    // for the general case, use a bi-directional table
    for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
        if (keyMapTable[i].javaKey == javaKey) {
            *windowsKey = keyMapTable[i].windowsKey;
            *modifiers = 0;
            return;
        }
    }

    // Bug 4766655
    // Two Windows keys could map to the same Java key, so
    // give preference to the originalWindowsKey if it is
    // specified (not IGNORE_KEY).
    if (originalWindowsKey == IGNORE_KEY) {
        for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
            if (dynamicKeyMapTable[j].javaKey == javaKey) {
                *windowsKey = dynamicKeyMapTable[j].windowsKey;
                *modifiers = 0;
                return;
            }
        }
    } else {
        BOOL found = false;
        for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
            if (dynamicKeyMapTable[j].javaKey == javaKey) {
                *windowsKey = dynamicKeyMapTable[j].windowsKey;
                *modifiers = 0;
                found = true;
                if (*windowsKey == originalWindowsKey) {
                    return;   /* if ideal case found return, else keep looking */
                }
            }
        }
        if (found) {
            return;
        }
    }

    *windowsKey = 0;
    *modifiers = 0;
    return;
}

UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey)

{
    // Handle the few cases where we need to take the modifier into
    // consideration for the Java VK code or where we have to take the keyboard
    // layout into consideration so that function keys can get
    // recognized in a platform-independent way.
    switch (windowsKey) {
        case VK_CONVERT:
            if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
                return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
            }
            if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
                return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
            }
            break;
        case VK_DBE_ALPHANUMERIC:
            if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
                return java_awt_event_KeyEvent_VK_CODE_INPUT;
            }
            break;
        case VK_KANA:
            if (isKanaLockAvailable()) {
                return java_awt_event_KeyEvent_VK_KANA_LOCK;
            }
            break;
    };

    // check dead key
    if (isDeadKey) {
      for (int i = 0; charToDeadVKTable[i].c != 0; i++) {
        if (charToDeadVKTable[i].c == character) {
            return charToDeadVKTable[i].javaKey;
        }
      }
    }

    // for the general case, use a bi-directional table
    for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
        if (keyMapTable[i].windowsKey == windowsKey) {
            return keyMapTable[i].javaKey;
        }
    }

    for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
        if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
            if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
                return dynamicKeyMapTable[j].javaKey;
            }else{
                break;
            }
        }
    }

    return java_awt_event_KeyEvent_VK_UNDEFINED;
}

BOOL AwtComponent::IsNavigationKey(UINT wkey) {
    switch (wkey) {
      case VK_END:
      case VK_PRIOR:  // PageUp
      case VK_NEXT:  // PageDown
      case VK_HOME:
      case VK_LEFT:
      case VK_UP:
      case VK_RIGHT:
      case VK_DOWN:
          return TRUE;
    }
    return FALSE;
}

// determine if a key is a numpad key (distinguishes the numpad
// arrow keys from the non-numpad arrow keys, for example).
BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended)
{
    // Note: scancodes are the same for the numpad arrow keys and
    // the non-numpad arrow keys (also for PageUp, etc.).
    // The scancodes for the numpad divide and the non-numpad slash
    // are the same, but the wparams are different

    DTRACE_PRINTLN3("AwtComponent::IsNumPadKey  vkey = %d = 0x%x  extended = %d",
      vkey, vkey, extended);

    switch (vkey) {
      case VK_CLEAR:  // numpad 5 with numlock off
      case VK_NUMPAD0:
      case VK_NUMPAD1:
      case VK_NUMPAD2:
      case VK_NUMPAD3:
      case VK_NUMPAD4:
      case VK_NUMPAD5:
      case VK_NUMPAD6:
      case VK_NUMPAD7:
      case VK_NUMPAD8:
      case VK_NUMPAD9:
      case VK_MULTIPLY:
      case VK_ADD:
      case VK_SEPARATOR:  // numpad ,  not on US kbds
      case VK_SUBTRACT:
      case VK_DECIMAL:
      case VK_DIVIDE:
      case VK_NUMLOCK:
        return TRUE;
        break;
      case VK_END:
      case VK_PRIOR:  // PageUp
      case VK_NEXT:  // PageDown
      case VK_HOME:
      case VK_LEFT:
      case VK_UP:
      case VK_RIGHT:
      case VK_DOWN:
      case VK_INSERT:
      case VK_DELETE:
        // extended if non-numpad
        return (!extended);
        break;
      case VK_RETURN:  // extended if on numpad
        return (extended);
        break;
      default:
        break;
    }

    return FALSE;
}
static void
resetKbdState( BYTE kstate[256]) {
    BYTE tmpState[256];
    WCHAR wc[2];
    memmove(tmpState, kstate, sizeof(kstate));
    tmpState[VK_SHIFT] = 0;
    tmpState[VK_CONTROL] = 0;
    tmpState[VK_MENU] = 0;

    ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0,  GetKeyboardLayout(0));
}

// XXX in the update releases this is an addition to the unchanged existing code
// After the call, a table will have a unicode associated with a windows virtual keycode
// sans modifiers. With some further simplification, one can
// derive java keycode from it, and anyway we will pass this unicode value
// all the way up in a comment to a KeyEvent.
void
AwtComponent::BuildPrimaryDynamicTable() {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    // XXX: how about that?
    //CriticalSection::Lock l(GetLock());
    //if (GetPeer(env) == NULL) {
    //    /* event received during termination. */
    //    return;
    //}

    HKL hkl = GetKeyboardLayout();
    UINT sc = 0;
    BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
    memset(kbdState, 0, sizeof (kbdState));

    // Use JNI call to obtain java key code. We should keep a list
    // of currently available keycodes in a single place.
    static jclass extKeyCodesCls;
    if( extKeyCodesCls == NULL) {
        jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
        DASSERT(extKeyCodesClsLocal);
        CHECK_NULL(extKeyCodesClsLocal);
        extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
        env->DeleteLocalRef(extKeyCodesClsLocal);
    }
    static jmethodID getExtendedKeyCodeForChar;
    if (getExtendedKeyCodeForChar == NULL) {
        getExtendedKeyCodeForChar =
                  env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
        DASSERT(getExtendedKeyCodeForChar);
        CHECK_NULL(getExtendedKeyCodeForChar);
    }
    jint extJKC; //extended Java key code

    for (UINT i = 0; i < 256; i++) {
        dynPrimaryKeymap[i].wkey = i;
        dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED;
        dynPrimaryKeymap[i].unicode = 0;

        if ((sc = MapVirtualKey (i, 0)) == 0) {
            dynPrimaryKeymap[i].scancode = 0;
            continue;
        }
        dynPrimaryKeymap[i].scancode = sc;

        // XXX process cases like VK_SHIFT etc.
        kbdState[i] = 0x80; // "key pressed".
        WCHAR wc[16];
        int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl);
        if (k == 1) {
            // unicode
            dynPrimaryKeymap[i].unicode = wc[0];
            if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) {
            // Convert unicode to java keycode.
                //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000);
                //
                //XXX If this key in on the keypad, we should force a special value equal to
                //XXX an old java keycode: but how to say if it is a keypad key?
                //XXX We'll do it in WmKeyUp/Down.
                extJKC = env->CallStaticIntMethod(extKeyCodesCls,
                                                  getExtendedKeyCodeForChar, (jint)(wc[0]));
                dynPrimaryKeymap[i].jkey = extJKC;
            }
        }else if (k == -1) {
            // dead key: use charToDeadVKTable
            dynPrimaryKeymap[i].unicode = wc[0];
            resetKbdState( kbdState );
            for (const CharToVKEntry *map = charToDeadVKTable;  map->c != 0;  ++map) {
                if (wc[0] == map->c) {
                    dynPrimaryKeymap[i].jkey = map->javaKey;
                    break;
                }
            }
        } else if (k == 0) {
            // reset
            resetKbdState( kbdState );
        }else {
            // k > 1: this key does generate multiple characters. Ignore it.
            // An example: Arabic Lam and Alef ligature.
            // There will be no extended keycode and thus shortcuts for this  key.
            // XXX shouldn't we reset the kbd state?
#ifdef DEBUG
            DTRACE_PRINTLN2("wkey 0x%02X (%d)", i,i);
#endif
        }
        kbdState[i] = 0; // "key unpressed"
    }
}
void
AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
{
    if( wkey && wkey < 256 ) {
        if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
            // At the creation time,
            // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
            dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
        }
        if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
            // E.g. it is non-unicode key
            dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
        }
    }
}

UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey)
{
    static Hashtable transTable("VKEY translations");
    static Hashtable deadKeyFlagTable("Dead Key Flags");
    isDeadKey = FALSE;

    // Try to translate using last saved translation
    if (ops == LOAD) {
       void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
       void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
       if (value != NULL) {
           isDeadKey = static_cast<BOOL>(reinterpret_cast<INT_PTR>(deadKeyFlag));
           return static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
       }
    }

    // If the windows key is a return, wkey will equal 13 ('\r')
    // In this case, we want to return 10 ('\n')
    // Since ToAscii would convert VK_RETURN to '\r', we need
    // to have a special case here.
    if (wkey == VK_RETURN)
        return '\n';

    // high order bit in keyboardState indicates whether the key is down
    static const BYTE KEY_STATE_DOWN = 0x80;
    BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
    AwtToolkit::GetKeyboardState(keyboardState);

    // apply modifiers to keyboard state if necessary
    if (modifiers) {
        BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
        BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
        BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;

        // Windows treats AltGr as Ctrl+Alt
        if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
            altIsDown = TRUE;
            ctrlIsDown = TRUE;
        }

        if (shiftIsDown) {
            keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
        }

        // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
        // Here we try to resolve a conflict with ::ToAsciiEx's translating
        // ALT+number key combinations. kdm@sarc.spb.su
        // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
        if( IsNavigationKey(wkey) ) {
            keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
        }

        if (ctrlIsDown)
        {
            if (altIsDown) {
                // bugid 4215009: don't mess with AltGr == Ctrl + Alt
                keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
            }
            else {
                // bugid 4098210: old event model doesn't have KEY_TYPED
                // events, so try to provide a meaningful character for
                // Ctrl+<key>.  Take Ctrl into account only when we know
                // that Ctrl+<key> will be an ASCII control.  Ignore by
                // default.
                keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN;

                // Letters have Ctrl+<letter> counterparts.  According to
                // <winuser.h> VK_A through VK_Z are the same as ASCII
                // 'A' through 'Z'.
                if (wkey >= 'A' && wkey <= 'Z') {
                    keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
                }
                else {
                    // Non-letter controls 033 to 037 are:
                    // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US)

                    // Shift state bits returned by ::VkKeyScan in HIBYTE
                    static const UINT _VKS_SHIFT_MASK = 0x01;
                    static const UINT _VKS_CTRL_MASK = 0x02;
                    static const UINT _VKS_ALT_MASK = 0x04;

                    // Check to see whether there is a meaningful translation
                    TCHAR ch;
                    short vk;
                    for (ch = _T('\033'); ch < _T('\040'); ch++) {
                        vk = ::VkKeyScan(ch);
                        if (wkey == LOBYTE(vk)) {
                            UINT shiftState = HIBYTE(vk);
                            if ((shiftState & _VKS_CTRL_MASK) ||
                                (!(shiftState & _VKS_SHIFT_MASK)
                                == !shiftIsDown))
                            {
                                keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
                            }
                            break;
                        }
                    }
                }
            } // ctrlIsDown && altIsDown
        } // ctrlIsDown
    } // modifiers

    // instead of creating our own conversion tables, I'll let Win32
    // convert the character for me.
    WORD wChar[2];
    UINT scancode = ::MapVirtualKey(wkey, 0);
    int converted = ::ToUnicodeEx(wkey, scancode, keyboardState,
                                  wChar, 2, 0, GetKeyboardLayout());

    UINT translation;
    BOOL deadKeyFlag = (converted == 2);

    // Dead Key
    if (converted < 0) {
        translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
    } else
    // No translation available -- try known conversions or else punt.
    if (converted == 0) {
        if (wkey == VK_DELETE) {
            translation = '\177';
        } else
        if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
            translation = '0' + wkey - VK_NUMPAD0;
        } else {
            translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
        }
    } else
    // the caller expects a Unicode character.
    if (converted > 0) {
        translation = wChar[0];
    }
    if (ops == SAVE) {
        transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
                       reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
        if (deadKeyFlag) {
            deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
                         reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
        } else {
            deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
        }
    }

    isDeadKey = deadKeyFlag;
    return translation;
}

MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
                                   UINT flags, BOOL system)
{
    // VK_PROCESSKEY is a special value which means
    //          "Current IME wants to consume this KeyEvent"
    // Real key code is saved by IMM32.DLL and can be retrieved by
    // calling ImmGetVirtualKey();
    if (wkey == VK_PROCESSKEY) {
        return mrDoDefault;
    }
    MSG msg;
    InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
                             wkey, MAKELPARAM(repCnt, flags));

    UINT modifiers = GetJavaModifiers();
    jint keyLocation = GetKeyLocation(wkey, flags);
    BOOL isDeadKey = FALSE;
    UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey);
    UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
    UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);


    SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
                             ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
                             modifiers, keyLocation, (jlong)wkey, &msg);

    // bugid 4724007: Windows does not create a WM_CHAR for the Del key
    // for some reason, so we need to create the KEY_TYPED event on the
    // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
    // to the native window for processing (this event is synthesized
    // for Java - we don't want Windows trying to process it).
    if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
        SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
                                 ::JVM_CurrentTimeMillis(NULL, 0),
                                 java_awt_event_KeyEvent_VK_UNDEFINED,
                                 character, modifiers,
                                 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
    }

    return mrConsume;
}

MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
                                 UINT flags, BOOL system)
{

    // VK_PROCESSKEY is a special value which means
    //          "Current IME wants to consume this KeyEvent"
    // Real key code is saved by IMM32.DLL and can be retrieved by
    // calling ImmGetVirtualKey();
    if (wkey == VK_PROCESSKEY) {
        return mrDoDefault;
    }
    MSG msg;
    InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
                             wkey, MAKELPARAM(repCnt, flags));

    UINT modifiers = GetJavaModifiers();
    jint keyLocation = GetKeyLocation(wkey, flags);
    BOOL isDeadKey = FALSE;
    UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey);
    UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
    UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);

    SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
                             ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
                             modifiers, keyLocation, (jlong)wkey, &msg);
    return mrConsume;
}

MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
{
    // Normally we would be able to use charset and TranslateCharSetInfo
    // to get a code page that should be associated with this keyboard
    // layout change. However, there seems to be an NT 4.0 bug associated
    // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
    // unreliable, especially on Asian systems. Our workaround uses the
    // keyboard layout handle instead.
    m_hkl = hKeyboardLayout;
    m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
    m_CodePage = LangToCodePage(m_idLang);
    BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
    BuildPrimaryDynamicTable();
    return mrConsume;           // do not propagate to children
}

// Convert Language ID to CodePage
UINT AwtComponent::LangToCodePage(LANGID idLang)
{
    TCHAR strCodePage[MAX_ACP_STR_LEN];
    // use the LANGID to create a LCID
    LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
    // get the ANSI code page associated with this locale
    if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
        return _ttoi(strCodePage);
    else
        return GetACP();
}


MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system)
{
    // We will simply create Java events here.
    WCHAR unicodeChar = character;
    MSG msg;
    InitMessage(&msg, WM_IME_CHAR, character,
                              MAKELPARAM(repCnt, flags));

    jint modifiers = GetJavaModifiers();
    SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
                             ::JVM_CurrentTimeMillis(NULL, 0),
                             java_awt_event_KeyEvent_VK_UNDEFINED,
                             unicodeChar, modifiers,
                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
                             &msg);
    return mrConsume;
}

MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
                                BOOL system)
{
    // Will only get WmChar messages with DBCS if we create them for
    // an Edit class in the WmForwardChar method. These synthesized
    // DBCS chars are ok to pass on directly to the default window
    // procedure. They've already been filtered through the Java key
    // event queue. We will never get the trail byte since the edit
    // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR,
    // PM_REMOVE).  I would like to be able to pass this character off
    // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to
    // like that.

    // We will simply create Java events here.
    UINT message = system ? WM_SYSCHAR : WM_CHAR;

    // The Alt modifier is reported in the 29th bit of the lParam,
    // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
    bool alt_is_down = (flags & (1<<13)) != 0;

    // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu
    // We should not pass this particular combination to Java.

    if (system && alt_is_down) {
        if (character == VK_SPACE) {
            return mrDoDefault;
        }
    }

    // If this is a WM_CHAR (non-system) message, then the Alt flag
    // indicates that the character was typed using an AltGr key
    // (which Windows treats as Ctrl+Alt), so in this case we do NOT
    // pass the Ctrl and Alt modifiers to Java, but instead we
    // replace them with Java's AltGraph modifier.  Note: the AltGraph
    // modifier does not exist in 1.1.x releases.
    jint modifiers = GetJavaModifiers();
    if (!system && alt_is_down) {
        // character typed with AltGraph
        modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK
                       | java_awt_event_InputEvent_CTRL_DOWN_MASK);
        modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
    }

    WCHAR unicodeChar = character;

    // Kludge: Combine pending single byte with this char for some Chinese IMEs
    if (m_PendingLeadByte != 0) {
        character = (m_PendingLeadByte & 0x00ff) | (character << 8);
        m_PendingLeadByte = 0;
        ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2,
                          &unicodeChar, 1);
    }

    if (unicodeChar == VK_RETURN) {
        // Enter key generates \r in windows, but \n is required in java
        unicodeChar = java_awt_event_KeyEvent_VK_ENTER;
    }
    MSG msg;
    InitMessage(&msg, message, character,
                              MAKELPARAM(repCnt, flags));
    SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
                             ::JVM_CurrentTimeMillis(NULL, 0),
                             java_awt_event_KeyEvent_VK_UNDEFINED,
                             unicodeChar, modifiers,
                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
                             &msg);
    return mrConsume;
}

MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam,
                                       BOOL synthetic)
{
    // just post WM_CHAR with unicode key value
    DefWindowProc(WM_CHAR, (WPARAM)character, lParam);
    return mrConsume;
}

MsgRouting AwtComponent::WmPaste()
{
    return mrDoDefault;
}

// support IME Composition messages
void AwtComponent::SetCompositionWindow(RECT& r)
{
    HWND hwnd = ImmGetHWnd();
    HIMC hIMC = ImmGetContext(hwnd);
    if (hIMC == NULL) {
        return;
    }
    COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}};
    ImmSetCompositionWindow(hIMC, &cf);
    ImmReleaseContext(hwnd, hIMC);
}

void AwtComponent::OpenCandidateWindow(int x, int y)
{
    UINT bits = 1;
    POINT p = {0, 0}; // upper left corner of the client area
    HWND hWnd = GetHWnd();
    HWND hTop = GetTopLevelParentForWindow(hWnd);
    ::ClientToScreen(hTop, &p);
    if (!m_bitsCandType) {
        SetCandidateWindow(m_bitsCandType, x - p.x, y - p.y);
        return;
    }
    for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
        if ( m_bitsCandType & bits )
            SetCandidateWindow(iCandType, x - p.x, y - p.y);
    }
    if (m_bitsCandType != 0) {
        // REMIND: is there any chance GetProxyFocusOwner() returns NULL here?
        ::DefWindowProc(ImmGetHWnd(),
                        WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType);
    }
}

void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
{
    HWND hwnd = ImmGetHWnd();
    HIMC hIMC = ImmGetContext(hwnd);
    CANDIDATEFORM cf;
    cf.dwIndex = iCandType;
    cf.dwStyle = CFS_POINT;
    cf.ptCurrentPos.x = x;
    cf.ptCurrentPos.y = y;

    ImmSetCandidateWindow(hIMC, &cf);
    ImmReleaseContext(hwnd, hIMC);
}

MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
{
    // If the Windows input context is disabled, do not let Windows
    // display any UIs.
    HWND hwnd = ImmGetHWnd();
    HIMC hIMC = ImmGetContext(hwnd);
    if (hIMC == NULL) {
        *lplParam = 0;
        return mrDoDefault;
    }
    ImmReleaseContext(hwnd, hIMC);

    if (fSet) {
        LPARAM lParam = *lplParam;
        if (!m_useNativeCompWindow) {
            // stop to draw native composing window.
            *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
        }
    }
    return mrDoDefault;
}

MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
{
    if (!m_useNativeCompWindow) {
        if (subMsg == IMN_OPENCANDIDATE) {
            m_bitsCandType = subMsg;
        } else if (subMsg != IMN_SETCANDIDATEPOS) {
            m_bitsCandType = 0;
        }
        InquireCandidatePosition();
        return mrConsume;
    }
    return mrDoDefault;
}

MsgRouting AwtComponent::WmImeStartComposition()
{
    if (m_useNativeCompWindow) {
        RECT rc;
        ::GetClientRect(GetHWnd(), &rc);
        SetCompositionWindow(rc);
        return mrDoDefault;
    } else
        return mrConsume;
}

MsgRouting AwtComponent::WmImeEndComposition()
{
    if (m_useNativeCompWindow)   return mrDoDefault;

    SendInputMethodEvent(
        java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
        NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
    return mrConsume;
}

MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
{
    if (m_useNativeCompWindow)   return mrDoDefault;

    int*      bndClauseW = NULL;
    jstring*  readingClauseW = NULL;
    int*      bndAttrW = NULL;
    BYTE*     valAttrW = NULL;
    int       cClauseW = 0;
    AwtInputTextInfor* textInfor = NULL;

    try {
        HWND hwnd = ImmGetHWnd();
        HIMC hIMC = ImmGetContext(hwnd);
        DASSERT(hIMC!=0);

        textInfor = new AwtInputTextInfor;
        textInfor->GetContextData(hIMC, flags);
        ImmReleaseContext(hwnd, hIMC);

        jstring jtextString = textInfor->GetText();
        /* The conditions to send the input method event to AWT EDT are:
           1. Whenever there is a composition message sent regarding whether
           the composition text is NULL or not. See details at bug 6222692.
           2. When there is a committed message sent, in which case, we have to
           check whether the committed string is NULL or not. If the committed string
           is NULL, there is no need to send any input method event.
           (Minor note: 'jtextString' returned is the merged string in the case of
           partial commit.)
        */
        if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
            (flags & GCS_COMPSTR)) {
            int       cursorPosW = textInfor->GetCursorPosition();
            // In order not to delete the readingClauseW in the catch clause,
            // calling GetAttributeInfor before GetClauseInfor.
            int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
            cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);

            /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
               the event to AWT EDT.

               The last two paremeters are set to equal since we don't have recommendations for
               the visible position within the current composed text. See details at
               java.awt.event.InputMethodEvent.
            */
            SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
                                 jtextString,
                                 cClauseW, bndClauseW, readingClauseW,
                                 cAttrW, bndAttrW, valAttrW,
                                 textInfor->GetCommittedTextLength(),
                                 cursorPosW, cursorPosW);
        }
    } catch (...) {
        // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
        // the pointer here.
        delete [] bndClauseW;
        delete [] readingClauseW;
        delete [] bndAttrW;
        delete [] valAttrW;
        throw;
    }

    /* Free the storage allocated. Since jtextString won't be passed from threads
     *  to threads, we just use the local ref and it will be deleted within the destructor
     *  of AwtInputTextInfor object.
     */
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (cClauseW && readingClauseW) {
        for (int i = 0; i < cClauseW; i ++) {
            if (readingClauseW[i]) {
                env->DeleteLocalRef(readingClauseW[i]);
            }
        }
    }
    delete [] bndClauseW;
    delete [] readingClauseW;
    delete [] bndAttrW;
    delete [] valAttrW;
    delete textInfor;

    return mrConsume;
}

//
// generate and post InputMethodEvent
//
void AwtComponent::SendInputMethodEvent(jint id, jstring text,
                                        int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
                                        int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
                                        int commitedTextLength, int caretPos, int visiblePos)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    // assumption for array type casting
    DASSERT(sizeof(int)==sizeof(jint));
    DASSERT(sizeof(BYTE)==sizeof(jbyte));

    // caluse information
    jintArray clauseBoundary = NULL;
    jobjectArray clauseReading = NULL;
    if (cClause && rgClauseBoundary && rgClauseReading) {
        // convert clause boundary offset array to java array
        clauseBoundary = env->NewIntArray(cClause+1);
        DASSERT(clauseBoundary);
        CHECK_NULL(clauseBoundary);
        env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
        DASSERT(!safe_ExceptionOccurred(env));

        // convert clause reading string array to java array
        jclass stringCls = JNU_ClassString(env);
        DASSERT(stringCls);
        CHECK_NULL(stringCls);
        clauseReading = env->NewObjectArray(cClause, stringCls, NULL);
        DASSERT(clauseReading);
        CHECK_NULL(clauseReading);
        for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
        DASSERT(!safe_ExceptionOccurred(env));
    }


    // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
    DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
    DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
    DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
    DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
    DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);

    // attribute information
    jintArray attrBoundary = NULL;
    jbyteArray attrValue = NULL;
    if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
        // convert attribute boundary offset array to java array
        attrBoundary = env->NewIntArray(cAttrBlock+1);
        DASSERT(attrBoundary);
        CHECK_NULL(attrBoundary);
        env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
        DASSERT(!safe_ExceptionOccurred(env));

        // convert attribute value byte array to java array
        attrValue = env->NewByteArray(cAttrBlock);
        DASSERT(attrValue);
        CHECK_NULL(attrValue);
        env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
        DASSERT(!safe_ExceptionOccurred(env));
    }


    // get global reference of WInputMethod class (run only once)
    static jclass wInputMethodCls = NULL;
    if (wInputMethodCls == NULL) {
        jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
        DASSERT(wInputMethodClsLocal);
        CHECK_NULL(wInputMethodClsLocal);
        wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
        env->DeleteLocalRef(wInputMethodClsLocal);
    }

    // get method ID of sendInputMethodEvent() (run only once)
    static jmethodID sendIMEventMid = 0;
    if (sendIMEventMid == 0) {
        sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
                                           "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
        DASSERT(sendIMEventMid);
        CHECK_NULL(sendIMEventMid);
    }

    // call m_InputMethod.sendInputMethod()
    env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, ::JVM_CurrentTimeMillis(NULL, 0),
                        text, clauseBoundary, clauseReading, attrBoundary,
                        attrValue, commitedTextLength, caretPos, visiblePos);
    if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
    DASSERT(!safe_ExceptionOccurred(env));

}



//
// Inquires candidate position according to the composed text
//
void AwtComponent::InquireCandidatePosition()
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    // get global reference of WInputMethod class (run only once)
    static jclass wInputMethodCls = NULL;
    if (wInputMethodCls == NULL) {
        jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
        DASSERT(wInputMethodClsLocal);
        CHECK_NULL(wInputMethodClsLocal);
        wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
        env->DeleteLocalRef(wInputMethodClsLocal);
    }

    // get method ID of sendInputMethodEvent() (run only once)
    static jmethodID inqCandPosMid = 0;
    if (inqCandPosMid == 0) {
        inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V");
        DASSERT(!safe_ExceptionOccurred(env));
        DASSERT(inqCandPosMid);
        CHECK_NULL(inqCandPosMid);
    }

    // call m_InputMethod.sendInputMethod()
    jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
    DASSERT(!safe_ExceptionOccurred(env));
}

HWND AwtComponent::ImmGetHWnd()
{
    HWND proxy = GetProxyFocusOwner();
    return (proxy != NULL) ? proxy : GetHWnd();
}

HIMC AwtComponent::ImmAssociateContext(HIMC himc)
{
    return ::ImmAssociateContext(ImmGetHWnd(), himc);
}

HWND AwtComponent::GetProxyFocusOwner()
{
    AwtWindow *window = GetContainer();
    if (window != 0) {
        AwtFrame *owner = window->GetOwningFrameOrDialog();
        if (owner != 0) {
            return owner->GetProxyFocusOwner();
        } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
            return ((AwtFrame*)window)->GetProxyFocusOwner();
        }
    }
    return (HWND)NULL;
}

/* Redirects message to the focus proxy, if any */
void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
    LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
{
    if (mr != mrConsume)  {
        HWND proxy = GetProxyFocusOwner();
        if (proxy != NULL && ::IsWindowEnabled(proxy)) {
            retVal = ::DefWindowProc(proxy, message, wParam, lParam);
            mr = mrConsume;
        }
    }
}

MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
{
    /* Menu/Accelerator */
    if (hWndChild == 0) {
        AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
        if (obj == NULL) {
            return mrConsume;
        }
        DASSERT(((AwtMenuItem*)obj)->GetID() == id);
        obj->DoCommand();
        return mrConsume;
    }
    /* Child id notification */
    else {
        AwtComponent* child = AwtComponent::GetComponent(hWndChild);
        if (child) {
            child->WmNotify(notifyCode);
        }
    }
    return mrDoDefault;
}

MsgRouting AwtComponent::WmNotify(UINT notifyCode)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
                                       COMPAREITEMSTRUCT &compareInfo,
                                       LRESULT &result)
{
    AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
    if (child == this) {
        /* DoCallback("handleItemDelete", */
    }
    else if (child) {
        return child->WmCompareItem(ctrlId, compareInfo, result);
    }
    return mrConsume;
}

MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
                                      DELETEITEMSTRUCT &deleteInfo)
{
    /*
     * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
     * window, a WM_DELETEITEM message is sent to its parent with a window
     * handle of one of the list's child windows.  The property lookup
     * succeeds, but the HWNDs don't match.
     */
    if (deleteInfo.hwndItem == NULL) {
        return mrConsume;
    }
    AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);

    if (child && child->GetHWnd() != deleteInfo.hwndItem) {
        return mrConsume;
    }

    if (child == this) {
        /*DoCallback("handleItemDelete", */
    }
    else if (child) {
        return child->WmDeleteItem(ctrlId, deleteInfo);
    }
    return mrConsume;
}

MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    if (drawInfo.CtlType == ODT_MENU) {
        if (drawInfo.itemData != 0) {
            AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
            menu->DrawItem(drawInfo);
        }
    } else {
        return OwnerDrawItem(ctrlId, drawInfo);
    }
    return mrConsume;
}

MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
                                       MEASUREITEMSTRUCT &measureInfo)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    if (measureInfo.CtlType == ODT_MENU) {
        if (measureInfo.itemData != 0) {
            AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
            HDC hDC = ::GetDC(GetHWnd());
            /* menu->MeasureItem(env, hDC, measureInfo); */
            menu->MeasureItem(hDC, measureInfo);
            ::ReleaseDC(GetHWnd(), hDC);
        }
    } else {
        return OwnerMeasureItem(ctrlId, measureInfo);
    }
    return mrConsume;
}

MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
    DRAWITEMSTRUCT &drawInfo)
{
    AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
    if (child == this) {
        /* DoCallback("handleItemDelete", */
    } else if (child != NULL) {
        return child->WmDrawItem(ctrlId, drawInfo);
    }
    return mrConsume;
}

MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
    MEASUREITEMSTRUCT &measureInfo)
{
    HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
    AwtComponent* child = AwtComponent::GetComponent(hChild);
    /*
     * If the parent cannot find the child's instance from its handle,
     * maybe the child is in its creation.  So the child must be searched
     * from the list linked before the child's creation.
     */
    if (child == NULL) {
        child = SearchChild((UINT)ctrlId);
    }

    if (child == this) {
    /* DoCallback("handleItemDelete",  */
    }
    else if (child) {
        return child->WmMeasureItem(ctrlId, measureInfo);
    }
    return mrConsume;
}

/* for WmDrawItem method of Label, Button and Checkbox */
void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
                                  int x, int y)
{
    int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
    DASSERT(nOldBkMode != 0);
    AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
    VERIFY(::SetBkMode(hDC,nOldBkMode));
}

/*
 * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
 * component is disabled.  Used only for label, checkbox and button in
 * OWNER_DRAW.  It draws the text in emboss.
 */
void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
                                int x, int y)
{
    ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
    AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
    ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
    AwtComponent::DrawWindowText(hDC, font, text, x, y);
}

/* for WmMeasureItem method of List and Choice */
jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
{
    jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
                                                "(I)Ljava/lang/String;",
                                                index).l;
    DASSERT(!safe_ExceptionOccurred(env));
    return str;
}

/* for WmMeasureItem method of List and Choice */
void AwtComponent::MeasureListItem(JNIEnv *env,
                                   MEASUREITEMSTRUCT &measureInfo)
{
    if (env->EnsureLocalCapacity(1) < 0) {
        return;
    }
    jobject dimension = PreferredItemSize(env);
    DASSERT(dimension);
    measureInfo.itemWidth =
      env->GetIntField(dimension, AwtDimension::widthID);
    measureInfo.itemHeight =
      env->GetIntField(dimension, AwtDimension::heightID);
    env->DeleteLocalRef(dimension);
}

/* for WmDrawItem method of List and Choice */
void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
{
    if (env->EnsureLocalCapacity(3) < 0) {
        return;
    }
    jobject peer = GetPeer(env);
    jobject target = env->GetObjectField(peer, AwtObject::targetID);

    HDC hDC = drawInfo.hDC;
    RECT rect = drawInfo.rcItem;

    BOOL bEnabled = isEnabled();
    BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
    DWORD crBack, crText;
    if (drawInfo.itemState & ODS_SELECTED){
        /* Set background and text colors for selected item */
        crBack = ::GetSysColor (COLOR_HIGHLIGHT);
        crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
    } else {
        /* Set background and text colors for unselected item */
        crBack = GetBackgroundColor();
        crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
    }
    if (unfocusableChoice) {
        //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
        crBack = GetBackgroundColor();
        crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
    }

    /* Fill item rectangle with background color */
    HBRUSH hbrBack = ::CreateSolidBrush (crBack);
    DASSERT(hbrBack);
    /* 6190728. Shouldn't draw any kind of rectangle around selection field
     * (edit control) of an owner-drawn combo box while unfocusable
     */
    if (!unfocusableChoice){
        VERIFY(::FillRect (hDC, &rect, hbrBack));
    }
    VERIFY(::DeleteObject (hbrBack));

    /* Set current background and text colors */
    ::SetBkColor (hDC, crBack);
    ::SetTextColor (hDC, crText);

    /*draw string (with left margin of 1 point) */
    if ((int) (drawInfo.itemID) >= 0) {
            jobject font = GET_FONT(target, peer);
            jstring text = GetItemString(env, target, drawInfo.itemID);
            if (env->ExceptionCheck()) {
                env->DeleteLocalRef(font);
                env->DeleteLocalRef(target);
                return;
            }
            SIZE size = AwtFont::getMFStringSize(hDC, font, text);
            AwtFont::drawMFString(hDC, font, text,
                                  (GetRTL()) ? rect.right - size.cx - 1
                                             : rect.left + 1,
                                  (rect.top + rect.bottom - size.cy) / 2,
                                  GetCodePage());
            env->DeleteLocalRef(font);
            env->DeleteLocalRef(text);
    }
    if ((drawInfo.itemState & ODS_FOCUS)  &&
        (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
      if (!unfocusableChoice){
          if(::DrawFocusRect(hDC, &rect) == 0)
              VERIFY(::GetLastError() == 0);
      }
    }
    env->DeleteLocalRef(target);
}

/* for MeasureListItem method and WmDrawItem method of Checkbox */
jint AwtComponent::GetFontHeight(JNIEnv *env)
{
    if (env->EnsureLocalCapacity(4) < 0) {
        return NULL;
    }
    jobject self = GetPeer(env);
    jobject target = env->GetObjectField(self, AwtObject::targetID);

    jobject font = GET_FONT(target, self);
    jobject toolkit = env->CallObjectMethod(target,
                                            AwtComponent::getToolkitMID);

    DASSERT(!safe_ExceptionOccurred(env));

    jobject fontMetrics =
        env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);

    DASSERT(!safe_ExceptionOccurred(env));

    jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
    DASSERT(!safe_ExceptionOccurred(env));

    env->DeleteLocalRef(target);
    env->DeleteLocalRef(font);
    env->DeleteLocalRef(toolkit);
    env->DeleteLocalRef(fontMetrics);

    return height;
}

// If you override WmPrint, make sure to save a copy of the DC on the GDI
// stack to be restored in WmPrintClient. Windows mangles the DC in
// ::DefWindowProc.
MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
{
    /*
     * DefWindowProc for WM_PRINT changes DC parameters, so we have
     * to restore it ourselves. Otherwise it will cause problems
     * when several components are printed to the same DC.
     */
    int nOriginalDC = ::SaveDC(hDC);
    DASSERT(nOriginalDC != 0);

    if (flags & PRF_NONCLIENT) {

        VERIFY(::SaveDC(hDC));

        DefWindowProc(WM_PRINT, (WPARAM)hDC,
                      (flags & (PRF_NONCLIENT
                                | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));

        VERIFY(::RestoreDC(hDC, -1));

        // Special case for components with a sunken border. Windows does not
        // print the border correctly on PCL printers, so we have to do it ourselves.
        if (GetStyleEx() & WS_EX_CLIENTEDGE) {
            RECT r;
            VERIFY(::GetWindowRect(GetHWnd(), &r));
            VERIFY(::OffsetRect(&r, -r.left, -r.top));
            VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
        }
    }

    if (flags & PRF_CLIENT) {

        /*
         * Special case for components with a sunken border.
         * Windows prints a client area without offset to a border width.
         * We will first print the non-client area with the original offset,
         * then the client area with a corrected offset.
         */
        if (GetStyleEx() & WS_EX_CLIENTEDGE) {

            int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
            int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);

            VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));

            // Save a copy of the DC for WmPrintClient
            VERIFY(::SaveDC(hDC));

            DefWindowProc(WM_PRINT, (WPARAM) hDC,
                          (flags & (PRF_CLIENT
                                    | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));

            VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));

        } else {

            // Save a copy of the DC for WmPrintClient
            VERIFY(::SaveDC(hDC));
            DefWindowProc(WM_PRINT, (WPARAM) hDC,
                          (flags & (PRF_CLIENT
                                    | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
        }
    }

    if (flags & (PRF_CHILDREN | PRF_OWNED)) {
        DefWindowProc(WM_PRINT, (WPARAM) hDC,
                      (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
    }

    VERIFY(::RestoreDC(hDC, nOriginalDC));

    return mrConsume;
}

// If you override WmPrintClient, make sure to obtain a valid copy of
// the DC from the GDI stack. The copy of the DC should have been placed
// there by WmPrint. Windows mangles the DC in ::DefWindowProc.
MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
{
    // obtain valid DC from GDI stack
    ::RestoreDC(hDC, -1);

    return mrDoDefault;
}

MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
                                      LPNCCALCSIZE_PARAMS lpncsp,
                                      LRESULT &retVal)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
{
    return mrDoDefault;
}

MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
{
    return mrDoDefault;
}

/**
 * WmQueryNewPalette is called whenever our component is coming to
 * the foreground; this gives us an opportunity to install our
 * custom palette.  If this install actually changes entries in
 * the system palette, then we get a further call to WmPaletteChanged
 * (but note that we only need to realize our palette once).
 */
MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
{
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    m_QueryNewPaletteCalled = TRUE;
    HDC hDC = ::GetDC(GetHWnd());
    DASSERT(hDC);
    AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
    AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
    ::ReleaseDC(GetHWnd(), hDC);
    // We must realize the palettes of all of our DC's
    // There is sometimes a problem where the realization of
    // our temporary hDC here does not actually do what
    // we want.  Not clear why, but presumably fallout from
    // our use of several simultaneous hDC's.
    activeDCList.RealizePalettes(screen);
    // Do not invalidate here; if the palette
    // has not changed we will get an extra repaint
    retVal = TRUE;

    return mrDoDefault;
}

/**
 * We should not need to track this event since we handle our
 * palette management effectively in the WmQueryNewPalette and
 * WmPaletteChanged methods.  However, there seems to be a bug
 * on some win32 systems (e.g., NT4) whereby the palette
 * immediately after a displayChange is not yet updated to its
 * final post-display-change values (hence we adjust our palette
 * using the wrong system palette entries), then the palette is
 * updated, but a WM_PALETTECHANGED message is never sent.
 * By tracking the ISCHANGING message as well (and by tracking
 * displayChange events in the AwtToolkit object), we can account
 * for this error by forcing our WmPaletteChanged method to be
 * called and thereby realizing our logical palette and updating
 * our dynamic colorModel object.
 */
MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
{
    if (AwtToolkit::GetInstance().HasDisplayChanged()) {
        WmPaletteChanged(hwndPalChg);
        AwtToolkit::GetInstance().ResetDisplayChanged();
    }
    return mrDoDefault;
}

MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
{
    // We need to re-realize our palette here (unless we're the one
    // that was realizing it in the first place).  That will let us match the
    // remaining colors in the system palette as best we can.  We always
    // invalidate because the palette will have changed when we receive this
    // message.

    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    if (hwndPalChg != GetHWnd()) {
        HDC hDC = ::GetDC(GetHWnd());
        DASSERT(hDC);
        AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
        AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
        ::ReleaseDC(GetHWnd(), hDC);
        // We must realize the palettes of all of our DC's
        activeDCList.RealizePalettes(screen);
    }
    if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
        AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
    }
    Invalidate(NULL);
    return mrDoDefault;
}

MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
{
    DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
    return mrDoDefault;
}

MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
{
    DASSERT(!IsBadStringPtr(pszSection, 20));
    DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
    return mrDoDefault;
}

HDC AwtComponent::GetDCFromComponent()
{
    GetDCReturnStruct *hdcStruct =
        (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
    HDC hdc;
    if (hdcStruct) {
        if (hdcStruct->gdiLimitReached) {
            if (jvm != NULL) {
                JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
                if (env != NULL && !safe_ExceptionOccurred(env)) {
                    JNU_ThrowByName(env, "java/awt/AWTError",
                        "HDC creation failure - " \
                        "exceeded maximum GDI resources");
                }
            }
        }
        hdc = hdcStruct->hDC;
        delete hdcStruct;
    } else {
        hdc = NULL;
    }
    return hdc;
}

void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
{
    RECT eraseR = { 0, 0, size.cx, size.cy };
    VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
}

void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
{
    if (!bitmapBits) {
        return;
    }

    DWORD* dest = (DWORD*)bitmapBits;
    //XXX: might be optimized to use one loop (cy*cx -> 0)
    for (int i = 0; i < size.cy; i++ ) {
        for (int j = 0; j < size.cx; j++ ) {
            ((BYTE*)(dest++))[3] = alpha;
        }
    }
}

int AwtComponent::ScaleUpX(int x) {
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
    return device == NULL ? x : device->ScaleUpX(x);
}

int AwtComponent::ScaleUpY(int y) {
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
    return device == NULL ? y : device->ScaleUpY(y);
}

int AwtComponent::ScaleDownX(int x) {
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
    return device == NULL ? x : device->ScaleDownX(x);
}

int AwtComponent::ScaleDownY(int y) {
    int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
    return device == NULL ? y : device->ScaleDownY(y);
}

jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    if (!::IsWindowVisible(GetHWnd())) {
        return NULL;
    }

    HDC hdc = GetDCFromComponent();
    if (!hdc) {
        return NULL;
    }
    HDC hMemoryDC = ::CreateCompatibleDC(hdc);
    void *bitmapBits = NULL;
    HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
    HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
    SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);

    FillBackground(hMemoryDC, size);

    VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));

    // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
    // above.
    SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);

    // First make sure the system completed any drawing to the bitmap.
    ::GdiFlush();

    // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
    // leaving it equal to zero. Hence we need to fill it manually. Otherwise
    // the pixels will be considered transparent when interpreting the data.
    FillAlpha(bitmapBits, size, alpha);

    ::SelectObject(hMemoryDC, hOldBitmap);

    BITMAPINFO bmi;
    memset(&bmi, 0, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = size.cx;
    bmi.bmiHeader.biHeight = -size.cy;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;

    jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
    jintArray pixelArray = NULL;
    if (localPixelArray != NULL) {
        pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
        env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;

        jboolean isCopy;
        jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);

        ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
                    DIB_RGB_COLORS);

        env->ReleaseIntArrayElements(pixelArray, pixels, 0);
    }

    VERIFY(::DeleteObject(hBitmap));
    VERIFY(::DeleteDC(hMemoryDC));

    return pixelArray;
}

void* AwtComponent::SetNativeFocusOwner(void *self) {
    if (self == NULL) {
        // It means that the KFM wants to set focus to null
        sm_focusOwner = NULL;
        return NULL;
    }

    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    AwtComponent *c = NULL;
    jobject peer = (jobject)self;

    PDATA pData;
    JNI_CHECK_NULL_GOTO(peer, "peer", ret);
    pData = JNI_GET_PDATA(peer);
    if (pData == NULL) {
        goto ret;
    }
    c = (AwtComponent *)pData;

ret:
    if (c && ::IsWindow(c->GetHWnd())) {
        sm_focusOwner = c->GetHWnd();
    } else {
        sm_focusOwner = NULL;
    }
    env->DeleteGlobalRef(peer);
    return NULL;
}

void* AwtComponent::GetNativeFocusedWindow() {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    AwtComponent *comp =
        AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
    return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
}

void* AwtComponent::GetNativeFocusOwner() {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    AwtComponent *comp =
        AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
    return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
}

AwtComponent* AwtComponent::SearchChild(UINT id) {
    ChildListItem* child;
    for (child = m_childList; child != NULL;child = child->m_next) {
        if (child->m_ID == id)
            return child->m_Component;
    }
    /*
     * DASSERT(FALSE);
     * This should not be happend if all children are recorded
     */
    return NULL;        /* make compiler happy */
}

void AwtComponent::RemoveChild(UINT id) {
    ChildListItem* child = m_childList;
    ChildListItem* lastChild = NULL;
    while (child != NULL) {
        if (child->m_ID == id) {
            if (lastChild == NULL) {
                m_childList = child->m_next;
            } else {
                lastChild->m_next = child->m_next;
            }
            child->m_next = NULL;
            DASSERT(child != NULL);
            delete child;
            return;
        }
        lastChild = child;
        child = child->m_next;
    }
}

void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
                                jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    CriticalSection::Lock l(GetLock());
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass keyEventCls;
    if (keyEventCls == NULL) {
        jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
        DASSERT(keyEventClsLocal);
        if (keyEventClsLocal == NULL) {
            /* exception already thrown */
            return;
        }
        keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
        env->DeleteLocalRef(keyEventClsLocal);
    }

    static jmethodID keyEventConst;
    if (keyEventConst == NULL) {
        keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
                                          "(Ljava/awt/Component;IJIICI)V");
        DASSERT(keyEventConst);
        CHECK_NULL(keyEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
                                      id, when, modifiers, raw, cooked,
                                      keyLocation);
    if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
    DASSERT(!safe_ExceptionOccurred(env));
    DASSERT(keyEvent != NULL);
    if (keyEvent == NULL) {
        env->DeleteLocalRef(target);
        return;
    }
    env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
    if( nativeCode && nativeCode < 256 ) {
        env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
        env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
        if( nativeCode < 255 ) {
            env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
        }else if( pMsg != NULL ) {
            // unknown key with virtual keycode 0xFF.
            // Its scancode is not in the table, pickup it from the message.
            env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
        }
    }
    if (pMsg != NULL) {
        AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
    }
    SendEvent(keyEvent);

    env->DeleteLocalRef(keyEvent);
    env->DeleteLocalRef(target);
}

void
AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
                                       jint raw, jint cooked,
                                       jint modifiers, jint keyLocation,
                                       jlong nativeCode,
                                       MSG *msg)
{
    /*
     * if focus owner is null, but focused window isn't
     * we will send key event to focused window
     */
    HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());

    if (hwndTarget == GetHWnd()) {
        SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
    } else {
        AwtComponent *target = NULL;
        if (hwndTarget != NULL) {
            target = AwtComponent::GetComponent(hwndTarget);
            if (target == NULL) {
                target = this;
            }
        }
        if (target != NULL) {
            target->SendKeyEvent(id, when, raw, cooked, modifiers,
              keyLocation, nativeCode, msg);
        }
    }
}

void AwtComponent::SetDragCapture(UINT flags)
{
    // don't want to interfere with other controls
    if (::GetCapture() == NULL) {
        ::SetCapture(GetHWnd());
    }
}

void AwtComponent::ReleaseDragCapture(UINT flags)
{
    if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
        // user has released all buttons, so release the capture
        ::ReleaseCapture();
    }
}

void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
                                  jint modifiers, jint clickCount,
                                  jboolean popupTrigger, jint button,
                                  MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    CriticalSection::Lock l(GetLock());
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass mouseEventCls;
    if (mouseEventCls == NULL) {
        jclass mouseEventClsLocal =
            env->FindClass("java/awt/event/MouseEvent");
        CHECK_NULL(mouseEventClsLocal);
        mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
        env->DeleteLocalRef(mouseEventClsLocal);
    }
    RECT insets;
    GetInsets(&insets);

    static jmethodID mouseEventConst;
    if (mouseEventConst == NULL) {
        mouseEventConst =
            env->GetMethodID(mouseEventCls, "<init>",
                 "(Ljava/awt/Component;IJIIIIIIZI)V");
        DASSERT(mouseEventConst);
        CHECK_NULL(mouseEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    DWORD curMousePos = ::GetMessagePos();
    int xAbs = GET_X_LPARAM(curMousePos);
    int yAbs = GET_Y_LPARAM(curMousePos);
    jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
                                        target,
                                        id, when, modifiers,
                                        ScaleDownX(x + insets.left),
                                        ScaleDownY(y + insets.top),
                                        ScaleDownX(xAbs), ScaleDownY(yAbs),
                                        clickCount, popupTrigger, button);

    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }

    DASSERT(mouseEvent != NULL);
    CHECK_NULL(mouseEvent);
    if (pMsg != 0) {
        AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
    }
    SendEvent(mouseEvent);

    env->DeleteLocalRef(mouseEvent);
    env->DeleteLocalRef(target);
}

void
AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
                                  jint modifiers, jint clickCount,
                                  jboolean popupTrigger, jint scrollType,
                                  jint scrollAmount, jint roundedWheelRotation,
                                  jdouble preciseWheelRotation, MSG *pMsg)
{
    /* Code based not so loosely on AwtComponent::SendMouseEvent */
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    CriticalSection::Lock l(GetLock());
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass mouseWheelEventCls;
    if (mouseWheelEventCls == NULL) {
        jclass mouseWheelEventClsLocal =
            env->FindClass("java/awt/event/MouseWheelEvent");
        CHECK_NULL(mouseWheelEventClsLocal);
        mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
        env->DeleteLocalRef(mouseWheelEventClsLocal);
    }
    RECT insets;
    GetInsets(&insets);

    static jmethodID mouseWheelEventConst;
    if (mouseWheelEventConst == NULL) {
        mouseWheelEventConst =
            env->GetMethodID(mouseWheelEventCls, "<init>",
                           "(Ljava/awt/Component;IJIIIIIIZIIID)V");
        DASSERT(mouseWheelEventConst);
        CHECK_NULL(mouseWheelEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    DWORD curMousePos = ::GetMessagePos();
    int xAbs = GET_X_LPARAM(curMousePos);
    int yAbs = GET_Y_LPARAM(curMousePos);

    DTRACE_PRINTLN("creating MWE in JNI");

    jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
                                             mouseWheelEventConst,
                                             target,
                                             id, when, modifiers,
                                             ScaleDownX(x + insets.left),
                                             ScaleDownY(y + insets.top),
                                             ScaleDownX(xAbs),
                                             ScaleDownY(yAbs),
                                             clickCount, popupTrigger,
                                             scrollType, scrollAmount,
                                             roundedWheelRotation, preciseWheelRotation);

    DASSERT(mouseWheelEvent != NULL);
    if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        env->DeleteLocalRef(target);
        return;
    }
    if (pMsg != NULL) {
        AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
    }
    SendEvent(mouseWheelEvent);

    env->DeleteLocalRef(mouseWheelEvent);
    env->DeleteLocalRef(target);
}

void AwtComponent::SendFocusEvent(jint id, HWND opposite)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    CriticalSection::Lock l(GetLock());
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass focusEventCls;
    if (focusEventCls == NULL) {
        jclass focusEventClsLocal
            = env->FindClass("java/awt/event/FocusEvent");
        DASSERT(focusEventClsLocal);
        CHECK_NULL(focusEventClsLocal);
        focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
        env->DeleteLocalRef(focusEventClsLocal);
    }

    static jmethodID focusEventConst;
    if (focusEventConst == NULL) {
        focusEventConst =
            env->GetMethodID(focusEventCls, "<init>",
                             "(Ljava/awt/Component;IZLjava/awt/Component;)V");
        DASSERT(focusEventConst);
        CHECK_NULL(focusEventConst);
    }

    static jclass sequencedEventCls;
    if (sequencedEventCls == NULL) {
        jclass sequencedEventClsLocal =
            env->FindClass("java/awt/SequencedEvent");
        DASSERT(sequencedEventClsLocal);
        CHECK_NULL(sequencedEventClsLocal);
        sequencedEventCls =
            (jclass)env->NewGlobalRef(sequencedEventClsLocal);
        env->DeleteLocalRef(sequencedEventClsLocal);
    }

    static jmethodID sequencedEventConst;
    if (sequencedEventConst == NULL) {
        sequencedEventConst =
            env->GetMethodID(sequencedEventCls, "<init>",
                             "(Ljava/awt/AWTEvent;)V");
        DASSERT(sequencedEventConst);
        CHECK_NULL(sequencedEventConst);
    }

    if (env->EnsureLocalCapacity(3) < 0) {
        return;
    }

    jobject target = GetTarget(env);
    jobject jOpposite = NULL;
    if (opposite != NULL) {
        AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
        if (awtOpposite != NULL) {
            jOpposite = awtOpposite->GetTarget(env);
        }
    }
    jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
                                        target, id, JNI_FALSE, jOpposite);
    DASSERT(!safe_ExceptionOccurred(env));
    DASSERT(focusEvent != NULL);
    if (jOpposite != NULL) {
        env->DeleteLocalRef(jOpposite); jOpposite = NULL;
    }
    env->DeleteLocalRef(target); target = NULL;
    CHECK_NULL(focusEvent);

    jobject sequencedEvent = env->NewObject(sequencedEventCls,
                                            sequencedEventConst,
                                            focusEvent);
    DASSERT(!safe_ExceptionOccurred(env));
    DASSERT(sequencedEvent != NULL);
    env->DeleteLocalRef(focusEvent); focusEvent = NULL;
    CHECK_NULL(sequencedEvent);
    SendEvent(sequencedEvent);

    env->DeleteLocalRef(sequencedEvent);
}

/*
 * Forward a filtered event directly to the subclassed window.
 * This method is needed so that DefWindowProc is invoked on the
 * component's owning thread.
 */
MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
{
    DefWindowProc(msg->message, msg->wParam, msg->lParam);
    delete msg;
    return mrConsume;
}

/* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
   on the toolkit thread. This method may pre-filter the messages. */
BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    // We should cut off keyboard events to disabled components
    // to avoid the components responding visually to keystrokes when disabled.
    // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
    // but to activate menus, close windows, etc
    switch(msg->message) {
        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_CHAR:
        case WM_DEADCHAR:
            {
                if (!isRecursivelyEnabled()) {
                    goto quit;
                }
                break;
            }
    }
    if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
        (WPARAM) synthetic, (LPARAM) msg)) {
            return TRUE;
    } else {
        JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
    }
quit:
    delete msg;
    return FALSE;
}

void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
{
    jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
    UINT message;
    switch (id) {
      case java_awt_event_KeyEvent_KEY_PRESSED:
          message = WM_KEYDOWN;
          break;
      case java_awt_event_KeyEvent_KEY_RELEASED:
          message = WM_KEYUP;
          break;
      case java_awt_event_KeyEvent_KEY_TYPED:
          message = WM_CHAR;
          break;
      default:
          return;
    }

    /*
     * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
     * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
     */
    if (id == java_awt_event_KeyEvent_KEY_TYPED) {
        // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
        // (for Edit control)
        jchar keyChar = (jchar)
          (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);

        // Bugid 4724007.  If it is a Delete character, don't send the fake
        // KEY_TYPED we created back to the native window: Windows doesn't
        // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
        // character after deleting.
        if (keyChar == '\177') { // the Delete character
            return;
        }

        // Disable forwarding WM_CHAR messages to disabled components
        if (isRecursivelyEnabled()) {
            if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
                MAKEWPARAM(keyChar, TRUE), 0)) {
                JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
            }
        }
    } else {
        jint keyCode =
          (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
        UINT key, modifiers;
        AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
        MSG* msg = CreateMessage(message, key, 0);
        PostHandleEventMessage(msg, TRUE);
    }
}

void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
{
    /*    DebugBreak(); */
    jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
    jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);

    WPARAM wParam = 0;
    WORD wLow = 0;
    jint wheelAmt = 0;
    jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
    UINT message;
    switch (id) {
      case java_awt_event_MouseEvent_MOUSE_PRESSED: {
          switch (button) {
            case java_awt_event_MouseEvent_BUTTON1:
                message = WM_LBUTTONDOWN; break;
            case java_awt_event_MouseEvent_BUTTON3:
                message = WM_MBUTTONDOWN; break;
            case java_awt_event_MouseEvent_BUTTON2:
                message = WM_RBUTTONDOWN; break;
            default:
                return;
          }
          break;
      }
      case java_awt_event_MouseEvent_MOUSE_RELEASED: {
          switch (button) {
            case java_awt_event_MouseEvent_BUTTON1:
                message = WM_LBUTTONUP; break;
            case java_awt_event_MouseEvent_BUTTON3:
                message = WM_MBUTTONUP; break;
            case java_awt_event_MouseEvent_BUTTON2:
                message = WM_RBUTTONUP; break;
            default:
                return;
          }
          break;
      }
      case java_awt_event_MouseEvent_MOUSE_MOVED:
          /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
      case java_awt_event_MouseEvent_MOUSE_DRAGGED:
          message = WM_MOUSEMOVE;
          break;
      case java_awt_event_MouseEvent_MOUSE_WHEEL:
          if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
              wLow |= MK_CONTROL;
          }
          if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
              wLow |= MK_SHIFT;
          }
          if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
              wLow |= MK_LBUTTON;
          }
          if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
              wLow |= MK_RBUTTON;
          }
          if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
              wLow |= MK_MBUTTON;
          }
          if (modifiers & X1_BUTTON) {
              wLow |= GetButtonMK(X1_BUTTON);
          }
          if (modifiers & X2_BUTTON) {
              wLow |= GetButtonMK(X2_BUTTON);
          }

          wheelAmt = (jint)JNU_CallMethodByName(env,
                                               NULL,
                                               mouseEvent,
                                               "getWheelRotation",
                                               "()I").i;
          DASSERT(!safe_ExceptionOccurred(env));
          JNU_CHECK_EXCEPTION(env);
          DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);

          // convert Java wheel amount value to Win32
          wheelAmt *= -1 * WHEEL_DELTA;

          message = WM_MOUSEWHEEL;
          wParam = MAKEWPARAM(wLow, wheelAmt);

          break;
      default:
          return;
    }
    jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
    jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
    MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
    PostHandleEventMessage(msg, TRUE);
}

BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}

void AwtComponent::Invalidate(RECT* r)
{
    ::InvalidateRect(GetHWnd(), r, FALSE);
}

void AwtComponent::BeginValidate()
{
    DASSERT(m_validationNestCount >= 0 &&
           m_validationNestCount < 1000); // sanity check

    if (m_validationNestCount == 0) {
    // begin deferred window positioning if we're not inside
    // another Begin/EndValidate pair
        DASSERT(m_hdwp == NULL);
        m_hdwp = ::BeginDeferWindowPos(32);
    }

    m_validationNestCount++;
}

void AwtComponent::EndValidate()
{
    DASSERT(m_validationNestCount > 0 &&
           m_validationNestCount < 1000); // sanity check
    DASSERT(m_hdwp != NULL);

    m_validationNestCount--;
    if (m_validationNestCount == 0) {
    // if this call to EndValidate is not nested inside another
    // Begin/EndValidate pair, end deferred window positioning
        ::EndDeferWindowPos(m_hdwp);
        m_hdwp = NULL;
    }
}

/**
 * HWND, AwtComponent and Java Peer interaction
 */

/*
 *Link the C++, Java peer, and HWNDs together.
 */
void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
{
    /*
     * Bind all three objects together thru this C++ object, two-way to each:
     *     JavaPeer <-> C++ <-> HWND
     *
     * C++ -> JavaPeer
     */
    if (m_peerObject == NULL) {
        // This may have already been set up by CreateHWnd
        // And we don't want to create two references so we
        // will leave the prior one alone
        m_peerObject = env->NewGlobalRef(peer);
    }
    /* JavaPeer -> HWND */
    env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));

    /* JavaPeer -> C++ */
    JNI_SET_PDATA(peer, this);

    /* HWND -> C++ */
    SetComponentInHWND();
}

/* Cleanup above linking */
void AwtComponent::UnlinkObjects()
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (m_peerObject) {
        env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
        JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
        JNI_SET_DESTROYED(m_peerObject);
        env->DeleteGlobalRef(m_peerObject);
        m_peerObject = NULL;
    }
}

void AwtComponent::Enable(BOOL bEnable)
{
    if (bEnable && IsTopLevel()) {
        // we should not enable blocked toplevels
        bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
    }
    // Shouldn't trigger native focus change
    // (only the proxy may be the native focus owner).
    ::EnableWindow(GetHWnd(), bEnable);

    CriticalSection::Lock l(GetLock());
    VerifyState();
}

/*
 * associate an AwtDropTarget with this AwtComponent
 */

AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
    m_dropTarget = new AwtDropTarget(env, this);
    m_dropTarget->RegisterTarget(TRUE);
    return m_dropTarget;
}

/*
 * disassociate an AwtDropTarget with this AwtComponent
 */

void AwtComponent::DestroyDropTarget() {
    if (m_dropTarget != NULL) {
        m_dropTarget->RegisterTarget(FALSE);
        m_dropTarget->Release();
        m_dropTarget = NULL;
    }
}

BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
    return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
}

BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
    return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
}

void AwtComponent::_Show(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        p->SendMessage(WM_AWT_COMPONENT_SHOW);
    }
ret:
    env->DeleteGlobalRef(self);
}

void AwtComponent::_Hide(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        p->SendMessage(WM_AWT_COMPONENT_HIDE);
    }
ret:
    env->DeleteGlobalRef(self);
}

void AwtComponent::_Enable(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        p->Enable(TRUE);
    }
ret:
    env->DeleteGlobalRef(self);
}

void AwtComponent::_Disable(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        p->Enable(FALSE);
    }
ret:
    env->DeleteGlobalRef(self);
}

jobject AwtComponent::_GetLocationOnScreen(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jobject result = NULL;
    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        RECT rect;
        VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
        result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
                                     p->ScaleDownX(rect.left),
                                     p->ScaleDownY(rect.top));
    }
ret:
    env->DeleteGlobalRef(self);

    if (result != NULL)
    {
        jobject resultGlobalRef = env->NewGlobalRef(result);
        env->DeleteLocalRef(result);
        return resultGlobalRef;
    }
    else
    {
        return NULL;
    }
}

void AwtComponent::_Reshape(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    ReshapeStruct *rs = (ReshapeStruct*)param;
    jobject self = rs->component;
    jint x = rs->x;
    jint y = rs->y;
    jint w = rs->w;
    jint h = rs->h;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        RECT* r = new RECT;
        ::SetRect(r, x, y, x + w, y + h);
        p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
    }
ret:
    env->DeleteGlobalRef(self);

    delete rs;
}

void AwtComponent::_ReshapeNoCheck(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    ReshapeStruct *rs = (ReshapeStruct*)param;
    jobject self = rs->component;
    jint x = rs->x;
    jint y = rs->y;
    jint w = rs->w;
    jint h = rs->h;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        RECT* r = new RECT;
        ::SetRect(r, x, y, x + w, y + h);
        p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
    }
ret:
    env->DeleteGlobalRef(self);

    delete rs;
}

void AwtComponent::_NativeHandleEvent(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
    jobject self = nhes->component;
    jobject event = nhes->event;

    AwtComponent *p;

    PDATA pData;
    JNI_CHECK_NULL_GOTO(self, "peer", ret);
    pData = JNI_GET_PDATA(self);
    if (pData == NULL) {
        env->DeleteGlobalRef(self);
        if (event != NULL) {
            env->DeleteGlobalRef(event);
        }
        delete nhes;
        return;
    }
    JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);

    p = (AwtComponent *)pData;
    if (::IsWindow(p->GetHWnd()))
    {
        if (env->EnsureLocalCapacity(1) < 0) {
            env->DeleteGlobalRef(self);
            env->DeleteGlobalRef(event);
            delete nhes;
            return;
        }
        jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
        int id = (env)->GetIntField(event, AwtAWTEvent::idID);
        DASSERT(!safe_ExceptionOccurred(env));
        if (bdata != 0) {
            MSG msg;
            (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
            (env)->DeleteLocalRef(bdata);
            static BOOL keyDownConsumed = FALSE;
            static BOOL bCharChanged = FALSE;
            static WCHAR modifiedChar;
            WCHAR unicodeChar;

            /* Remember if a KEY_PRESSED event is consumed, as an old model
             * program won't consume a subsequent KEY_TYPED event.
             */
            jboolean consumed =
                (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
            DASSERT(!safe_ExceptionOccurred(env));

            if (consumed) {
                keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
                env->DeleteGlobalRef(self);
                env->DeleteGlobalRef(event);
                delete nhes;
                return;

            } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
                // Fix for 6637607: reset consuming
                keyDownConsumed = FALSE;
            }

            /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
             * the old model.
             */
            if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
                keyDownConsumed = FALSE;
                env->DeleteGlobalRef(self);
                env->DeleteGlobalRef(event);
                delete nhes;
                return;
            }

            /* Modify any event parameters, if necessary. */
            if (self && pData &&
                id >= java_awt_event_KeyEvent_KEY_FIRST &&
                id <= java_awt_event_KeyEvent_KEY_LAST) {

                    AwtComponent* p = (AwtComponent*)pData;

                    jint keyCode =
                      (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
                    jchar keyChar =
                      (env)->GetCharField(event, AwtKeyEvent::keyCharID);
                    jint modifiers =
                      (env)->GetIntField(event, AwtInputEvent::modifiersID);

                    DASSERT(!safe_ExceptionOccurred(env));

                /* Check to see whether the keyCode or modifiers were changed
                   on the keyPressed event, and tweak the following keyTyped
                   event (if any) accodingly.  */
                switch (id) {
                case java_awt_event_KeyEvent_KEY_PRESSED:
                {
                    UINT winKey = (UINT)msg.wParam;
                    bCharChanged = FALSE;

                    if (winKey == VK_PROCESSKEY) {
                        // Leave it up to IME
                        break;
                    }

                    if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
                        UINT newWinKey, ignored;
                        p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
                        if (newWinKey != 0) {
                            winKey = newWinKey;
                        }
                    }

                    BOOL isDeadKey = FALSE;
                    modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey);
                    bCharChanged = (keyChar != modifiedChar);
                }
                break;

                case java_awt_event_KeyEvent_KEY_RELEASED:
                {
                    keyDownConsumed = FALSE;
                    bCharChanged = FALSE;
                }
                break;

                case java_awt_event_KeyEvent_KEY_TYPED:
                {
                    if (bCharChanged)
                    {
                        unicodeChar = modifiedChar;
                    }
                    else
                    {
                        unicodeChar = keyChar;
                    }
                    bCharChanged = FALSE;

                    // Disable forwarding KEY_TYPED messages to peers of
                    // disabled components
                    if (p->isRecursivelyEnabled()) {
                        // send the character back to the native window for
                        // processing. The WM_AWT_FORWARD_CHAR handler will send
                        // this character to DefWindowProc
                        if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
                            MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
                            JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
                        }
                    }
                    env->DeleteGlobalRef(self);
                    env->DeleteGlobalRef(event);
                    delete nhes;
                    return;
                }
                break;

                default:
                    break;
                }
            }

            // ignore all InputMethodEvents
            if (self && (pData = JNI_GET_PDATA(self)) &&
                id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
                id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
                env->DeleteGlobalRef(self);
                env->DeleteGlobalRef(event);
                delete nhes;
                return;
            }

            // Create copy for local msg
            MSG* pCopiedMsg = new MSG;
            memmove(pCopiedMsg, &msg, sizeof(MSG));
            // Event handler deletes msg
            p->PostHandleEventMessage(pCopiedMsg, FALSE);

            env->DeleteGlobalRef(self);
            env->DeleteGlobalRef(event);
            delete nhes;
            return;
        }

        /* Forward any valid synthesized events.  Currently only mouse and
         * key events are supported.
         */
        if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
            env->DeleteGlobalRef(self);
            env->DeleteGlobalRef(event);
            delete nhes;
            return;
        }

        AwtComponent* p = (AwtComponent*)pData;
        if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
            id <= java_awt_event_KeyEvent_KEY_LAST) {
            p->SynthesizeKeyMessage(env, event);
        } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
                   id <= java_awt_event_MouseEvent_MOUSE_LAST) {
            p->SynthesizeMouseMessage(env, event);
        }
    }

ret:
    if (self != NULL) {
        env->DeleteGlobalRef(self);
    }
    if (event != NULL) {
        env->DeleteGlobalRef(event);
    }

    delete nhes;
}

void AwtComponent::_SetForeground(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetColorStruct *scs = (SetColorStruct *)param;
    jobject self = scs->component;
    jint rgb = scs->rgb;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        c->SetColor(PALETTERGB((rgb>>16)&0xff,
                               (rgb>>8)&0xff,
                               (rgb)&0xff));
        c->VerifyState();
    }
ret:
    env->DeleteGlobalRef(self);

    delete scs;
}

void AwtComponent::_SetBackground(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetColorStruct *scs = (SetColorStruct *)param;
    jobject self = scs->component;
    jint rgb = scs->rgb;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
                                         (rgb>>8)&0xff,
                                         (rgb)&0xff));
        c->VerifyState();
    }
ret:
    env->DeleteGlobalRef(self);

    delete scs;
}

void AwtComponent::_SetFont(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetFontStruct *sfs = (SetFontStruct *)param;
    jobject self = sfs->component;
    jobject font = sfs->font;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    JNI_CHECK_NULL_GOTO(font, "null font", ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
        if (awtFont == NULL) {
            /*arguments of AwtFont::Create are changed for multifont component */
            awtFont = AwtFont::Create(env, font);
        }
        env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);

        c->SetFont(awtFont);
    }
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(font);

    delete sfs;
}

// Sets or kills focus for a component.
void AwtComponent::_SetFocus(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetFocusStruct *sfs = (SetFocusStruct *)param;
    jobject self = sfs->component;
    jboolean doSetFocus = sfs->doSetFocus;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_NULL_GOTO(self, "peer", ret);
    pData = JNI_GET_PDATA(self);
    if (pData == NULL) {
        // do nothing just return false
        goto ret;
    }

    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd())) {
        c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
    }
ret:
    env->DeleteGlobalRef(self);

    delete sfs;
}

void AwtComponent::_Start(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        jobject target = c->GetTarget(env);

        /* Disable window if specified -- windows are enabled by default. */
        jboolean enabled = (jboolean)env->GetBooleanField(target,
                                                          AwtComponent::enabledID);
        if (!enabled) {
            ::EnableWindow(c->GetHWnd(), FALSE);
        }

        /* The peer is now ready for callbacks, since this is the last
         * initialization call
         */
        c->EnableCallbacks(TRUE);

        // Fix 4745222: we need to invalidate region since we validated it before initialization.
        ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);

        // Fix 4530093: WM_PAINT after EnableCallbacks
        ::UpdateWindow(c->GetHWnd());

        env->DeleteLocalRef(target);
    }
ret:
    env->DeleteGlobalRef(self);
}

void AwtComponent::_BeginValidate(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (AwtToolkit::IsMainThread()) {
        jobject self = (jobject)param;
        if (self != NULL) {
            PDATA pData = JNI_GET_PDATA(self);
            if (pData) {
                AwtComponent *c = (AwtComponent *)pData;
                if (::IsWindow(c->GetHWnd())) {
                    c->SendMessage(WM_AWT_BEGIN_VALIDATE);
                }
            }
            env->DeleteGlobalRef(self);
        }
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
    }
}

void AwtComponent::_EndValidate(void *param)
{
    if (AwtToolkit::IsMainThread()) {
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        jobject self = (jobject)param;
        if (self != NULL) {
            PDATA pData = JNI_GET_PDATA(self);
            if (pData) {
                AwtComponent *c = (AwtComponent *)pData;
                if (::IsWindow(c->GetHWnd())) {
                    c->SendMessage(WM_AWT_END_VALIDATE);
                }
            }
            env->DeleteGlobalRef(self);
        }
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
    }
}

void AwtComponent::_UpdateWindow(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (AwtToolkit::IsMainThread()) {
        jobject self = (jobject)param;
        AwtComponent *c = NULL;
        PDATA pData;
        JNI_CHECK_PEER_GOTO(self, ret);
        c = (AwtComponent *)pData;
        if (::IsWindow(c->GetHWnd())) {
            ::UpdateWindow(c->GetHWnd());
        }
ret:
        env->DeleteGlobalRef(self);
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
    }
}

jlong AwtComponent::_AddNativeDropTarget(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jlong result = 0;
    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        result = (jlong)(c->CreateDropTarget(env));
    }
ret:
    env->DeleteGlobalRef(self);

    return result;
}

void AwtComponent::_RemoveNativeDropTarget(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        c->DestroyDropTarget();
    }
ret:
    env->DeleteGlobalRef(self);
}

jintArray AwtComponent::_CreatePrintedPixels(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
    jobject self = cpps->component;

    jintArray result = NULL;
    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
    }
ret:
    env->DeleteGlobalRef(self);

    delete cpps;
    return result; // this reference is global
}

jboolean AwtComponent::_IsObscured(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jboolean result = JNI_FALSE;
    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);

    c = (AwtComponent *)pData;

    if (::IsWindow(c->GetHWnd()))
    {
        HWND hWnd = c->GetHWnd();
        HDC hDC = ::GetDC(hWnd);
        RECT clipbox;
        int callresult = ::GetClipBox(hDC, &clipbox);
        switch(callresult) {
            case NULLREGION :
                result = JNI_FALSE;
                break;
            case SIMPLEREGION : {
                RECT windowRect;
                if (!::GetClientRect(hWnd, &windowRect)) {
                    result = JNI_TRUE;
                } else {
                    result  = (jboolean)((clipbox.bottom != windowRect.bottom)
                        || (clipbox.left != windowRect.left)
                        || (clipbox.right != windowRect.right)
                        || (clipbox.top != windowRect.top));
                }
                break;
            }
            case COMPLEXREGION :
            default :
                result = JNI_TRUE;
                break;
        }
        ::ReleaseDC(hWnd, hDC);
    }
ret:
    env->DeleteGlobalRef(self);

    return result;
}

jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jboolean result = JNI_FALSE;
    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd()))
    {
        result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior());
    }
ret:
    env->DeleteGlobalRef(self);

    return result;
}

void AwtComponent::SetParent(void * param) {
    if (AwtToolkit::IsMainThread()) {
        AwtComponent** comps = (AwtComponent**)param;
        if ((comps[0] != NULL) && (comps[1] != NULL)) {
            HWND selfWnd = comps[0]->GetHWnd();
            HWND parentWnd = comps[1]->GetHWnd();
            if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
                // Shouldn't trigger native focus change
                // (only the proxy may be the native focus owner).
                ::SetParent(selfWnd, parentWnd);
            }
        }
        delete[] comps;
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param);
    }
}

void AwtComponent::_SetRectangularShape(void *param)
{
    if (!AwtToolkit::IsMainThread()) {
        AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
    } else {
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

        SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
        jobject self = data->component;
        jint x1 = data->x1;
        jint x2 = data->x2;
        jint y1 = data->y1;
        jint y2 = data->y2;
        jobject region = data->region;

        AwtComponent *c = NULL;

        PDATA pData;
        JNI_CHECK_PEER_GOTO(self, ret);

        c = (AwtComponent *)pData;
        if (::IsWindow(c->GetHWnd())) {
            HRGN hRgn = NULL;

            // If all the params are zeros, the shape must be simply reset.
            // Otherwise, convert it into a region.
            if (region || x1 || x2 || y1 || y2) {
                RECT_T rects[256];
                RECT_T *pRect = rects;

                const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2,
                        region, &pRect, sizeof(rects)/sizeof(rects[0]));
                if (!pRect) {
                    // RegionToYXBandedRectangles doesn't use safe_Malloc(),
                    // so throw the exception explicitly
                    throw std::bad_alloc();
                }

                RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
                        sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects);
                memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects);
                if (pRect != rects) {
                    free(pRect);
                }
                pRect = NULL;

                RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData;
                pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
                pRgnHdr->iType = RDH_RECTANGLES;
                pRgnHdr->nRgnSize = 0;
                pRgnHdr->rcBound.top = 0;
                pRgnHdr->rcBound.left = 0;
                pRgnHdr->rcBound.bottom = LONG(y2 - y1);
                pRgnHdr->rcBound.right = LONG(x2 - x1);
                pRgnHdr->nCount = numrects;

                hRgn = ::ExtCreateRegion(NULL,
                        sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);

                free(pRgnData);
            }

            ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
        }

ret:
        env->DeleteGlobalRef(self);
        if (region) {
            env->DeleteGlobalRef(region);
        }

        delete data;
    }
}

void AwtComponent::_SetZOrder(void *param) {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetZOrderStruct *data = (SetZOrderStruct *)param;
    jobject self = data->component;
    HWND above = HWND_TOP;
    if (data->above != 0) {
        above = reinterpret_cast<HWND>(data->above);
    }

    AwtComponent *c = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);

    c = (AwtComponent *)pData;
    if (::IsWindow(c->GetHWnd())) {
        ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
    }

ret:
    env->DeleteGlobalRef(self);

    delete data;
}

void AwtComponent::PostUngrabEvent() {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject target = GetTarget(env);
    jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
                                        target);
    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
    env->DeleteLocalRef(target);
    if (event != NULL) {
        SendEvent(event);
        env->DeleteLocalRef(event);
    }
}

void AwtComponent::SetFocusedWindow(HWND window)
{
    HWND old = sm_focusedWindow;
    sm_focusedWindow = window;

    AwtWindow::FocusedWindowChanged(old, window);
}

/************************************************************************
 * Component native methods
 */

extern "C" {

/**
 * This method is called from the WGL pipeline when it needs to retrieve
 * the HWND associated with a ComponentPeer's C++ level object.
 */
HWND
AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
{
    AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
    if (p == NULL) {
        return (HWND)0;
    }
    return p->GetHWnd();
}

static void _GetInsets(void* param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    GetInsetsStruct *gis = (GetInsetsStruct *)param;
    jobject self = gis->window;

    gis->insets->left = gis->insets->top =
        gis->insets->right = gis->insets->bottom = 0;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    AwtComponent *component = (AwtComponent *)pData;

    component->GetInsets(gis->insets);

  ret:
    env->DeleteGlobalRef(self);
    delete gis;
}

/**
 * This method is called from the WGL pipeline when it needs to retrieve
 * the insets associated with a ComponentPeer's C++ level object.
 */
void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
{
    TRY;

    GetInsetsStruct *gis = new GetInsetsStruct;
    gis->window = env->NewGlobalRef(peer);
    gis->insets = insets;

    AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
    // global refs and mds are deleted in _UpdateWindow

    CATCH_BAD_ALLOC;

}

JNIEXPORT void JNICALL
Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
{
    TRY;
    jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
    CHECK_NULL(inputEventClazz);
    jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
    CHECK_NULL(getButtonDownMasksID);
    jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
    jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
    CHECK_NULL(tmp);
    jsize len = env->GetArrayLength(obj);
    AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
    for (int i = 0; i < len; i++) {
        AwtComponent::masks[i] = tmp[i];
    }
    env->ReleaseIntArrayElements(obj, tmp, 0);
    env->DeleteLocalRef(obj);

    /* class ids */
    jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");

    DASSERT(peerCls);
    CHECK_NULL(peerCls);

    /* field ids */
    AwtComponent::peerID =
      env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
    DASSERT(AwtComponent::peerID);
    CHECK_NULL(AwtComponent::peerID);

    AwtComponent::xID = env->GetFieldID(cls, "x", "I");
    DASSERT(AwtComponent::xID);
    CHECK_NULL(AwtComponent::xID);

    AwtComponent::yID = env->GetFieldID(cls, "y", "I");
    DASSERT(AwtComponent::yID);
    CHECK_NULL(AwtComponent::yID);

    AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
    DASSERT(AwtComponent::heightID);
    CHECK_NULL(AwtComponent::heightID);

    AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
    DASSERT(AwtComponent::widthID);
    CHECK_NULL(AwtComponent::widthID);

    AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
    DASSERT(AwtComponent::visibleID);
    CHECK_NULL(AwtComponent::visibleID);

    AwtComponent::backgroundID =
        env->GetFieldID(cls, "background", "Ljava/awt/Color;");
    DASSERT(AwtComponent::backgroundID);
    CHECK_NULL(AwtComponent::backgroundID);

    AwtComponent::foregroundID =
        env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
    DASSERT(AwtComponent::foregroundID);
    CHECK_NULL(AwtComponent::foregroundID);

    AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
    DASSERT(AwtComponent::enabledID);
    CHECK_NULL(AwtComponent::enabledID);

    AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
    DASSERT(AwtComponent::parentID);
    CHECK_NULL(AwtComponent::parentID);

    AwtComponent::graphicsConfigID =
     env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
    DASSERT(AwtComponent::graphicsConfigID);
    CHECK_NULL(AwtComponent::graphicsConfigID);

    AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
    DASSERT(AwtComponent::focusableID);
    CHECK_NULL(AwtComponent::focusableID);

    AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
                                                 "Lsun/awt/AppContext;");
    DASSERT(AwtComponent::appContextID);
    CHECK_NULL(AwtComponent::appContextID);

    AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
                                        "Lsun/awt/Win32GraphicsConfig;");
    DASSERT(AwtComponent::peerGCID);
    CHECK_NULL(AwtComponent::peerGCID);

    AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
    DASSERT(AwtComponent::hwndID);
    CHECK_NULL(AwtComponent::hwndID);

    AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
    DASSERT(AwtComponent::cursorID);
    CHECK_NULL(AwtComponent::cursorID);

    /* method ids */
    AwtComponent::getFontMID =
        env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
    DASSERT(AwtComponent::getFontMID);
    CHECK_NULL(AwtComponent::getFontMID);

    AwtComponent::getToolkitMID =
        env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
    DASSERT(AwtComponent::getToolkitMID);
    CHECK_NULL(AwtComponent::getToolkitMID);

    AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
    DASSERT(AwtComponent::isEnabledMID);
    CHECK_NULL(AwtComponent::isEnabledMID);

    AwtComponent::getLocationOnScreenMID =
        env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
    DASSERT(AwtComponent::getLocationOnScreenMID);
    CHECK_NULL(AwtComponent::getLocationOnScreenMID);

    AwtComponent::replaceSurfaceDataMID =
        env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
    DASSERT(AwtComponent::replaceSurfaceDataMID);
    CHECK_NULL(AwtComponent::replaceSurfaceDataMID);

    AwtComponent::replaceSurfaceDataLaterMID =
        env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
    DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
    CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID);

    AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
    DASSERT(AwtComponent::disposeLaterMID);
    CHECK_NULL(AwtComponent::disposeLaterMID);

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/************************************************************************
 * ComponentPeer native methods
 */

extern "C" {

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    pShow
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _Show

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    hide
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _Hide

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    enable
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _Enable

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    disable
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _Disable

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    getLocationOnScreen
 * Signature: ()Ljava/awt/Point;
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _GetLocationOnScreen
    if (resultGlobalRef != NULL)
    {
        jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
        env->DeleteGlobalRef(resultGlobalRef);
        return resultLocalRef;
    }

    return NULL;

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    reshape
 * Signature: (IIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
                                            jint x, jint y, jint w, jint h)
{
    TRY;

    ReshapeStruct *rs = new ReshapeStruct;
    rs->component = env->NewGlobalRef(self);
    rs->x = x;
    rs->y = y;
    rs->w = w;
    rs->h = h;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
    // global ref and rs are deleted in _Reshape

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    reshape
 * Signature: (IIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
                                            jint x, jint y, jint w, jint h)
{
    TRY;

    ReshapeStruct *rs = new ReshapeStruct;
    rs->component = env->NewGlobalRef(self);
    rs->x = x;
    rs->y = y;
    rs->w = w;
    rs->h = h;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
    // global ref and rs are deleted in _ReshapeNoCheck

    CATCH_BAD_ALLOC;
}


/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    nativeHandleEvent
 * Signature: (Ljava/awt/AWTEvent;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
                                                      jobject self,
                                                      jobject event)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);
    jobject eventGlobalRef = env->NewGlobalRef(event);

    NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
    nhes->component = selfGlobalRef;
    nhes->event = eventGlobalRef;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
    // global refs and nhes are deleted in _NativeHandleEvent

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    _dispose
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
{
    TRY_NO_HANG;

    AwtObject::_Dispose(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    _setForeground
 * Signature: (I)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
                                                    jint rgb)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    SetColorStruct *scs = new SetColorStruct;
    scs->component = selfGlobalRef;
    scs->rgb = rgb;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
    // selfGlobalRef and scs are deleted in _SetForeground()

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    _setBackground
 * Signature: (I)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
                                                    jint rgb)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    SetColorStruct *scs = new SetColorStruct;
    scs->component = selfGlobalRef;
    scs->rgb = rgb;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
    // selfGlobalRef and scs are deleted in _SetBackground()

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    _setFont
 * Signature: (Ljava/awt/Font;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
                        jobject font)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);
    jobject fontGlobalRef = env->NewGlobalRef(font);

    SetFontStruct *sfs = new SetFontStruct;
    sfs->component = selfGlobalRef;
    sfs->font = fontGlobalRef;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
    // global refs and sfs are deleted in _SetFont()

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    focusGained
 * Signature: (Z)
 */
JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
    (JNIEnv *env, jobject self, jboolean doSetFocus)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    SetFocusStruct *sfs = new SetFocusStruct;
    sfs->component = selfGlobalRef;
    sfs->doSetFocus = doSetFocus;

    AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtComponent::_SetFocus, sfs);
    // global refs and self are deleted in _SetFocus

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    start
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _Start

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    beginValidate
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _BeginValidate

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    endValidate
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _EndValidate

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _UpdateWindow

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    addNativeDropTarget
 * Signature: ()L
 */

JNIEXPORT jlong JNICALL
Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
                                                        jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
        (void *)selfGlobalRef));
    // selfGlobalRef is deleted in _AddNativeDropTarget

    CATCH_BAD_ALLOC_RET(0);
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    removeNativeDropTarget
 * Signature: ()V
 */

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
                                                           jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(
        AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _RemoveNativeDropTarget

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    getTargetGC
 * Signature: ()Ljava/awt/GraphicsConfiguration;
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
{
    TRY;

    jobject targetObj;
    jobject gc = 0;

    targetObj = env->GetObjectField(theThis, AwtObject::targetID);
    DASSERT(targetObj);

    gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
    return gc;

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    createPrintedPixels
 * Signature: (IIIIII)I[
 */
JNIEXPORT jintArray JNICALL
Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
    jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
    cpps->component = selfGlobalRef;
    cpps->srcx = srcX;
    cpps->srcy = srcY;
    cpps->srcw = srcW;
    cpps->srch = srcH;
    cpps->alpha = alpha;

    jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
    // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
    if (globalRef != NULL)
    {
        jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
        env->DeleteGlobalRef(globalRef);
        return localRef;
    }
    else
    {
        return NULL;
    }

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    nativeHandlesWheelScrolling
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
    jobject self)
{
    TRY;

    return (jboolean)AwtToolkit::GetInstance().SyncCall(
        (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
        env->NewGlobalRef(self));
    // global ref is deleted in _NativeHandlesWheelScrolling

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_windows_WComponentPeer
 * Method:    isObscured
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
    jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    return (jboolean)AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtComponent::_IsObscured,
        (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _IsObscured

    CATCH_BAD_ALLOC_RET(NULL);
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
    TRY;

    typedef AwtComponent* PComponent;
    AwtComponent** comps = new PComponent[2];
    AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self);
    AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent);
    comps[0] = comp;
    comps[1] = parentComp;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps);
    // comps is deleted in SetParent

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
        jint x1, jint y1, jint x2, jint y2, jobject region)
{
    TRY;

    SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
    data->component = env->NewGlobalRef(self);
    data->x1 = x1;
    data->x2 = x2;
    data->y1 = y1;
    data->y2 = y2;
    if (region) {
        data->region = env->NewGlobalRef(region);
    } else {
        data->region = NULL;
    }

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
    // global refs and data are deleted in _SetRectangularShape

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
{
    TRY;

    SetZOrderStruct * data = new SetZOrderStruct;
    data->component = env->NewGlobalRef(self);
    data->above = above;

    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
    // global refs and data are deleted in _SetLower

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/************************************************************************
 * Diagnostic routines
 */

#ifdef DEBUG

void AwtComponent::VerifyState()
{
    if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
        return;
    }

    if (m_callbacksEnabled == FALSE) {
        /* Component is not fully setup yet. */
        return;
    }

    /* Get target bounds. */
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (env->PushLocalFrame(10) < 0)
        return;

    jobject target = GetTarget(env);

    jint x = env->GetIntField(target, AwtComponent::xID);
    jint y = env->GetIntField(target, AwtComponent::yID);
    jint width = env->GetIntField(target, AwtComponent::widthID);
    jint height = env->GetIntField(target, AwtComponent::heightID);

    /* Convert target origin to absolute coordinates */
    while (TRUE) {

        jobject parent = env->GetObjectField(target, AwtComponent::parentID);
        if (parent == NULL) {
            break;
        }
        x += env->GetIntField(parent, AwtComponent::xID);
        y += env->GetIntField(parent, AwtComponent::yID);

        /* If this component has insets, factor them in, but ignore
         * top-level windows.
         */
        jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
        if (parent2 != NULL) {
            jobject peer = GetPeerForTarget(env, parent);
            if (peer != NULL &&
                JNU_IsInstanceOfByName(env, peer,
                                       "sun/awt/windows/WPanelPeer") > 0) {
                jobject insets =
                    JNU_CallMethodByName(env, NULL, peer,"insets",
                                         "()Ljava/awt/Insets;").l;
                x += (env)->GetIntField(insets, AwtInsets::leftID);
                y += (env)->GetIntField(insets, AwtInsets::topID);
            }
        }
        env->DeleteLocalRef(target);
        target = parent;
    }

    x = ScaleUpX(x);
    y = ScaleUpY(y);
    width = ScaleUpX(width);
    height = ScaleUpY(height);

    // Test whether component's bounds match the native window's
    RECT rect;
    VERIFY(::GetWindowRect(GetHWnd(), &rect));
#if 0
    DASSERT( (x == rect.left) &&
            (y == rect.top) &&
            (width == (rect.right-rect.left)) &&
            (height == (rect.bottom-rect.top)) );
#else
    BOOL fSizeValid = ( (x == rect.left) &&
            (y == rect.top) &&
            (width == (rect.right-rect.left)) &&
            (height == (rect.bottom-rect.top)) );
#endif

    // See if visible state matches
    BOOL wndVisible = ::IsWindowVisible(GetHWnd());
    jboolean targetVisible;
    // To avoid possibly running client code on the toolkit thread, don't
    // do the following check if we're running on the toolkit thread.
    if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
        targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
                                                  "isShowing", "()Z").z;
        DASSERT(!safe_ExceptionOccurred(env));
    } else {
        targetVisible = wndVisible ? 1 : 0;
    }
#if 0
    DASSERT( (targetVisible && wndVisible) ||
            (!targetVisible && !wndVisible) );
#else
    BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
            (!targetVisible && !wndVisible) );
#endif

    // Check enabled state
    BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
    jboolean enabled = (jboolean)env->GetBooleanField(target,
                                                      AwtComponent::enabledID);
#if 0
    DASSERT( (enabled && wndEnabled) ||
            (!enabled && !wndEnabled) );
#else
    BOOL fEnabledValid = ((enabled && wndEnabled) ||
                          (!(enabled && !wndEnabled) ));

    if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
        printf("AwtComponent::ValidateState() failed:\n");
        // To avoid possibly running client code on the toolkit thread, don't
        // do the following call if we're running on the toolkit thread.
        if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
            jstring targetStr =
                (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
                                              "getName",
                                              "()Ljava/lang/String;").l;
            DASSERT(!safe_ExceptionOccurred(env));
            LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
            printf("\t%S\n", targetStrW);
            JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
        }
        printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
        if (!fSizeValid) {
            printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
                   rect.right-rect.left, rect.bottom-rect.top);
        }
        if (!fVisibleValid) {
            printf("\tshould be: %s\n",
                   (targetVisible) ? "visible" : "hidden");
        }
        if (!fEnabledValid) {
            printf("\tshould be: %s\n",
                   enabled ? "enabled" : "disabled");
        }
    }
#endif
    env->PopLocalFrame(0);
}
#endif //DEBUG

// Methods for globally managed DC list

/**
 * Add a new DC to the DC list for this component.
 */
void DCList::AddDC(HDC hDC, HWND hWnd)
{
    DCItem *newItem = new DCItem;
    newItem->hDC = hDC;
    newItem->hWnd = hWnd;
    AddDCItem(newItem);
}

void DCList::AddDCItem(DCItem *newItem)
{
    listLock.Enter();
    newItem->next = head;
    head = newItem;
    listLock.Leave();
}

/**
 * Given a DC and window handle, remove the DC from the DC list
 * and return TRUE if it exists on the current list.  Otherwise
 * return FALSE.
 * A DC may not exist on the list because it has already
 * been released elsewhere (for example, the window
 * destruction process may release a DC while a rendering
 * thread may also want to release a DC when it notices that
 * its DC is obsolete for the current window).
 */
DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd)
{
    listLock.Enter();
    DCItem **prevPtrPtr = &head;
    DCItem *listPtr = head;
    while (listPtr) {
        DCItem *nextPtr = listPtr->next;
        if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) {
            *prevPtrPtr = nextPtr;
            break;
        }
        prevPtrPtr = &listPtr->next;
        listPtr = nextPtr;
    }
    listLock.Leave();
    return listPtr;
}

/**
 * Remove all DCs from the DC list which are associated with
 * the same window as hWnd.  Return the list of those
 * DC's to the caller (which will then probably want to
 * call ReleaseDC() for the returned DCs).
 */
DCItem *DCList::RemoveAllDCs(HWND hWnd)
{
    listLock.Enter();
    DCItem **prevPtrPtr = &head;
    DCItem *listPtr = head;
    DCItem *newListPtr = NULL;
    BOOL ret = FALSE;
    while (listPtr) {
        DCItem *nextPtr = listPtr->next;
        if (listPtr->hWnd == hWnd) {
            *prevPtrPtr = nextPtr;
            listPtr->next = newListPtr;
            newListPtr = listPtr;
        } else {
            prevPtrPtr = &listPtr->next;
        }
        listPtr = nextPtr;
    }
    listLock.Leave();
    return newListPtr;
}


/**
 * Realize palettes of all existing HDC objects
 */
void DCList::RealizePalettes(int screen)
{
    listLock.Enter();
    DCItem *listPtr = head;
    while (listPtr) {
        AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
        listPtr = listPtr->next;
    }
    listLock.Leave();
}

void MoveDCToPassiveList(HDC hDC, HWND hWnd) {
    DCItem *removedDC;
    if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) {
        passiveDCList.AddDCItem(removedDC);
    }
}

void ReleaseDCList(HWND hwnd, DCList &list) {
    DCItem *removedDCs = list.RemoveAllDCs(hwnd);
    while (removedDCs) {
        DCItem *tmpDCList = removedDCs;
        DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
        int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
        VERIFY(retValue != 0);
        if (retValue != 0) {
            // Valid ReleaseDC call; need to decrement GDI object counter
            AwtGDIObject::Decrement();
        }
        removedDCs = removedDCs->next;
        delete tmpDCList;
    }
}
