/*
 * Copyright (c) 1996, 2009, 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.
 */

#ifndef AWT_COMPONENT_H
#define AWT_COMPONENT_H

#include "awtmsg.h"
#include "awt_Object.h"
#include "awt_Font.h"
#include "awt_Brush.h"
#include "awt_Pen.h"
#include "awt_Win32GraphicsDevice.h"
#include "GDIWindowSurfaceData.h"

#include "java_awt_Component.h"
#include "sun_awt_windows_WComponentPeer.h"
#include "java_awt_event_KeyEvent.h"
#include "java_awt_event_FocusEvent.h"
#include "java_awt_event_MouseEvent.h"
#include "java_awt_event_WindowEvent.h"
#include "java_awt_Dimension.h"

extern LPCTSTR szAwtComponentClassName;

static LPCTSTR DrawingStateProp = TEXT("SunAwtDrawingStateProp");

const UINT IGNORE_KEY = (UINT)-1;
const UINT MAX_ACP_STR_LEN = 7; // ANSI CP identifiers are no longer than this

#define LEFT_BUTTON 1
#define MIDDLE_BUTTON 2
#define RIGHT_BUTTON 4
#define DBL_CLICK 8
#define X1_BUTTON 16
#define X2_BUTTON 32

#ifndef MK_XBUTTON1
#define MK_XBUTTON1         0x0020
#endif

#ifndef MK_XBUTTON2
#define MK_XBUTTON2         0x0040
#endif

// combination of standard mouse button flags
const int ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON;
const int X_BUTTONS = MK_XBUTTON1|MK_XBUTTON2;



// Whether to check for embedded frame and adjust location
#define CHECK_EMBEDDED 0
#define DONT_CHECK_EMBEDDED 1

class AwtPopupMenu;

class AwtDropTarget;

/*
 * Message routing codes
 */
enum MsgRouting {
    mrPassAlong,    /* pass along to next in chain */
    mrDoDefault,    /* skip right to underlying default behavior */
    mrConsume,      /* consume msg & terminate routing immediatly,
                     * don't pass anywhere
                     */
};

/************************************************************************
 * AwtComponent class
 */

class AwtComponent : public AwtObject {
public:
    /* java.awt.Component fields and method IDs */
    static jfieldID peerID;
    static jfieldID xID;
    static jfieldID yID;
    static jfieldID widthID;
    static jfieldID heightID;
    static jfieldID visibleID;
    static jfieldID backgroundID;
    static jfieldID foregroundID;
    static jfieldID enabledID;
    static jfieldID parentID;
    static jfieldID cursorID;
    static jfieldID graphicsConfigID;
    static jfieldID peerGCID;
    static jfieldID focusableID;
    static jfieldID appContextID;
    static jfieldID hwndID;

    static jmethodID getFontMID;
    static jmethodID getToolkitMID;
    static jmethodID isEnabledMID;
    static jmethodID getLocationOnScreenMID;
    static jmethodID replaceSurfaceDataMID;
    static jmethodID replaceSurfaceDataLaterMID;
    static jmethodID disposeLaterMID;

    static const UINT WmAwtIsComponent;
    static jint * masks; //InputEvent mask array
    AwtComponent();
    virtual ~AwtComponent();

    /*
     * Dynamic class registration & creation
     */
    virtual LPCTSTR GetClassName() = 0;
    /*
     * Fix for 4964237: Win XP: Changing theme changes java dialogs title icon
     * WNDCLASS structure has been superseded by the WNDCLASSEX in Win32
     */
    virtual void FillClassInfo(WNDCLASSEX *lpwc);
    virtual void RegisterClass();
    virtual void UnregisterClass();

    virtual void 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);
    virtual void DestroyHWnd();
    void InitPeerGraphicsConfig(JNIEnv *env, jobject peer);

    virtual void Dispose();

    void UpdateBackground(JNIEnv *env, jobject target);

    virtual void SubclassHWND();
    virtual void UnsubclassHWND();

    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
        WPARAM wParam, LPARAM lParam);

    /*
     * Access to the various objects of this aggregate component
     */
    INLINE HWND GetHWnd() { return m_hwnd; }
    INLINE void SetHWnd(HWND hwnd) { m_hwnd = hwnd; }

    static AwtComponent* GetComponent(HWND hWnd);

    /*
     * Access to the properties of the component
     */
    INLINE COLORREF GetColor() { return m_colorForeground; }
    virtual void SetColor(COLORREF c);
    HPEN GetForegroundPen();

    COLORREF GetBackgroundColor();
    virtual void SetBackgroundColor(COLORREF c);
    HBRUSH GetBackgroundBrush();
    INLINE BOOL IsBackgroundColorSet() { return m_backgroundColorSet; }

    virtual void SetFont(AwtFont *pFont);

    INLINE void SetText(LPCTSTR text) { ::SetWindowText(GetHWnd(), text); }
    INLINE int GetText(LPTSTR buffer, int size) {
        return ::GetWindowText(GetHWnd(), buffer, size);
    }
    INLINE int GetTextLength() { return ::GetWindowTextLength(GetHWnd()); }

    virtual void GetInsets(RECT* rect) {
        VERIFY(::SetRectEmpty(rect));
    }

    BOOL IsVisible() { return m_visible;};

    HDC GetDCFromComponent();

    /*
     * Enable/disable component
     */
    virtual void Enable(BOOL bEnable);

    /*
     * Validate and call handleExpose on rects of UpdateRgn
     */
    void PaintUpdateRgn(const RECT *insets);

    static HWND GetTopLevelParentForWindow(HWND hwndDescendant);

    static jobject FindHeavyweightUnderCursor(BOOL useCache);

    /*
     * Returns the parent component.  If no parent window, or the
     * parent window isn't an AwtComponent, returns NULL.
     */
    AwtComponent* GetParent();

    /* Get the component's immediate container. Note: may return NULL while
       the component is being reparented in full-screen mode by Direct3D */
    class AwtWindow* GetContainer();

    /* Is a component a container? Used by above method */
    virtual BOOL IsContainer() { return FALSE;} // Plain components can't

    /**
     * Returns TRUE if this message will trigger native focus change, FALSE otherwise.
     */
    virtual BOOL IsFocusingKeyMessage(MSG *pMsg);
    virtual BOOL IsFocusingMouseMessage(MSG *pMsg);

    BOOL IsFocusable();

    /*
     * Returns an increasing unsigned value used for child control IDs.
     * There is no attempt to reclaim command ID's.
     */
    INLINE UINT CreateControlID() { return m_nextControlID++; }

    // returns the current keyboard layout
    INLINE static HKL GetKeyboardLayout() {
        return m_hkl;
    }

    // returns the current code page that should be used in
    // all MultiByteToWideChar and WideCharToMultiByte calls.
    // This code page should also be use in IsDBCSLeadByteEx.
    INLINE static UINT GetCodePage()
    {
        return m_CodePage;
    }

// Added by waleed for BIDI Support
    // returns the right to left status
    INLINE static BOOL GetRTLReadingOrder() {
        return sm_rtlReadingOrder;
    }
    // returns the right to left status
    INLINE static BOOL GetRTL() {
        return sm_rtl;
    }
    // returns the current sub language
    INLINE static LANGID GetSubLanguage() {
        return SUBLANGID(m_idLang);
    }
// end waleed

    // returns the current input language
    INLINE static LANGID GetInputLanguage()
    {
        return m_idLang;
    }
    // Convert Language ID to CodePage
    static UINT LangToCodePage(LANGID idLang);

    /*
     * methods on this component
     */
    virtual void Show();
    virtual void Hide();
    virtual void Reshape(int x, int y, int w, int h);

    /*
     * Fix for 4046446.
     * Component size/position helper, for the values above the short int limit.
     */
    static BOOL SetWindowPos(HWND wnd, HWND after,
                             int x, int y, int w, int h, UINT flags);

    /*
     * Sets the scrollbar values.  'bar' can be either SB_VERT or
     * SB_HORZ.  'min', 'value', and 'max' can have the value INT_MAX
     * which means that the value should not be changed.
     */
    void SetScrollValues(UINT bar, int min, int value, int max);

    INLINE LRESULT SendMessage(UINT msg, WPARAM wParam=0, LPARAM lParam=0) {
        DASSERT(GetHWnd());
        return ::SendMessage(GetHWnd(), msg, wParam, lParam);
    }

    void PostUngrabEvent();

    INLINE virtual LONG GetStyle() {
        DASSERT(GetHWnd());
        return ::GetWindowLong(GetHWnd(), GWL_STYLE);
    }
    INLINE virtual void SetStyle(LONG style) {
        DASSERT(GetHWnd());
        // SetWindowLong() error handling as recommended by Win32 API doc.
        ::SetLastError(0);
        DWORD ret = ::SetWindowLong(GetHWnd(), GWL_STYLE, style);
        DASSERT(ret != 0 || ::GetLastError() == 0);
    }
    INLINE virtual LONG GetStyleEx() {
        DASSERT(GetHWnd());
        return ::GetWindowLong(GetHWnd(), GWL_EXSTYLE);
    }
    INLINE virtual void SetStyleEx(LONG style) {
        DASSERT(GetHWnd());
        // SetWindowLong() error handling as recommended by Win32 API doc.
        ::SetLastError(0);
        DWORD ret = ::SetWindowLong(GetHWnd(), GWL_EXSTYLE, style);
        DASSERT(ret != 0 || ::GetLastError() == 0);
    }

    virtual BOOL NeedDblClick() { return FALSE; }

    /* for multifont component */
    static void DrawWindowText(HDC hDC, jobject font, jstring text,
                               int x, int y);
    static void DrawGrayText(HDC hDC, jobject font, jstring text,
                             int x, int y);

    void DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo);

    void MeasureListItem(JNIEnv *env, MEASUREITEMSTRUCT &measureInfo);

    jstring GetItemString(JNIEnv *env, jobject target, jint index);

    jint GetFontHeight(JNIEnv *env);

    virtual jobject PreferredItemSize(JNIEnv *env) {DASSERT(FALSE); return NULL; }

    INLINE BOOL isEnabled() {
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        if (env->EnsureLocalCapacity(2) < 0) {
            return NULL;
        }
        jobject self = GetPeer(env);
        jobject target = env->GetObjectField(self, AwtObject::targetID);
        BOOL e = env->CallBooleanMethod(target, AwtComponent::isEnabledMID);
        DASSERT(!safe_ExceptionOccurred(env));

        env->DeleteLocalRef(target);

        return e;
    }

    INLINE BOOL isRecursivelyEnabled() {
        AwtComponent* p = this;
        do {
            if (!p->isEnabled()) {
                return FALSE;
            }
        } while (!p->IsTopLevel() &&
            (p = p->GetParent()) != NULL);
        return TRUE;
    }

    void SendKeyEventToFocusOwner(jint id, jlong when, jint raw, jint cooked,
                                  jint modifiers, jint keyLocation, jlong nativeCode,
                                  MSG *msg = NULL);
    /*
     * Allocate and initialize a new java.awt.event.KeyEvent, and
     * post it to the peer's target object.  No response is expected
     * from the target.
     */
    void SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
                      jint modifiers, jint keyLocation, jlong nativeCode,
                      MSG *msg = NULL);

    /*
     * Allocate and initialize a new java.awt.event.MouseEvent, and
     * post it to the peer's target object.  No response is expected
     * from the target.
     */
    void SendMouseEvent(jint id, jlong when, jint x, jint y,
                        jint modifiers, jint clickCount,
                        jboolean popupTrigger, jint button = 0,
                        MSG *msg = NULL);

    /*
     * Allocate and initialize a new java.awt.event.MouseWheelEvent, and
     * post it to the peer's target object.  No response is expected
     * from the target.
     */
    void SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
                             jint modifiers, jint clickCount,
                             jboolean popupTrigger, jint scrollType,
                             jint scrollAmount, jint wheelRotation,
                             jdouble preciseWheelRotation, MSG *msg = NULL);

    /*
     * Allocate and initialize a new java.awt.event.FocusEvent, and
     * post it to the peer's target object.  No response is expected
     * from the target.
     */
    void SendFocusEvent(jint id, HWND opposite);

    /* Forward a filtered event directly to the subclassed window.
       synthetic should be TRUE iff the message was generated because
       of a synthetic Java event, rather than a native event. */
    virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic);

    /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
       on the toolkit thread. This method may pre-filter the messages. */
    virtual BOOL PostHandleEventMessage(MSG *msg, BOOL synthetic);

    /* Event->message synthesizer methods. */
    void SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent);
    void SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent);

    /* Components which inherit native mouse wheel behavior will
     * return TRUE.  These are TextArea, Choice, FileDialog, and
     * List.  All other Components return FALSE.
     */
    virtual BOOL InheritsNativeMouseWheelBehavior();

    /* Determines whether the component is obscured by another window */
    // Called on Toolkit thread
    static jboolean _IsObscured(void *param);

    /* Invalidate the specified rectangle. */
    virtual void Invalidate(RECT* r);

    /* Begin and end deferred window positioning. */
    virtual void BeginValidate();
    virtual void EndValidate();

    /* Keyboard conversion routines. */
    static void InitDynamicKeyMapTable();
    static void BuildDynamicKeyMapTable();
    static jint GetJavaModifiers();
    static jint GetButton(int mouseButton);
    static UINT GetButtonMK(int mouseButton);
    static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey);
    static void JavaKeyToWindowsKey(UINT javaKey, UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey);
    static void UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers);

    INLINE static void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
                                       UINT *windowsKey, UINT *modifiers)
    {
        JavaKeyToWindowsKey(javaKey, windowsKey, modifiers, IGNORE_KEY);
    }

    enum TransOps {NONE, LOAD, SAVE};

    UINT WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey);

    /* routines used for input method support */
    void SetInputMethod(jobject im, BOOL useNativeCompWindow);
    void SendInputMethodEvent(jint id, jstring text, int cClause,
                              int *rgClauseBoundary, jstring *rgClauseReading,
                              int cAttrBlock, int *rgAttrBoundary,
                              BYTE *rgAttrValue, int commitedTextLength,
                              int caretPos, int visiblePos);
    void InquireCandidatePosition();
    INLINE LPARAM GetCandidateType() { return m_bitsCandType; }
    HWND ImmGetHWnd();
    HIMC ImmAssociateContext(HIMC himc);
    HWND GetProxyFocusOwner();

    INLINE HWND GetProxyToplevelContainer() {
        HWND proxyHWnd = GetProxyFocusOwner();
        return ::GetAncestor(proxyHWnd, GA_ROOT); // a browser in case of EmbeddedFrame
    }

    void CallProxyDefWindowProc(UINT message,
                                WPARAM wParam,
                                LPARAM lParam,
                                LRESULT &retVal,
                                MsgRouting &mr);

    /*
     * Windows message handler functions
     */
    virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
    virtual LRESULT DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam);

    /* return true if msg is processed */
    virtual MsgRouting PreProcessMsg(MSG& msg);

    virtual MsgRouting WmCreate() {return mrDoDefault;}
    virtual MsgRouting WmClose() {return mrDoDefault;}
    virtual MsgRouting WmDestroy();
    virtual MsgRouting WmNcDestroy();

    virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
    {
        return mrDoDefault;
    }

    virtual MsgRouting WmEraseBkgnd(HDC hDC, BOOL& didErase)
    {
        return mrDoDefault;
    }

    virtual MsgRouting WmPaint(HDC hDC);
    virtual MsgRouting WmGetMinMaxInfo(LPMINMAXINFO lpmmi);
    virtual MsgRouting WmMove(int x, int y);
    virtual MsgRouting WmSize(UINT type, int w, int h);
    virtual MsgRouting WmSizing();
    virtual MsgRouting WmShowWindow(BOOL show, UINT status);
    virtual MsgRouting WmSetFocus(HWND hWndLost);
    virtual MsgRouting WmKillFocus(HWND hWndGot);
    virtual MsgRouting WmCtlColor(HDC hDC, HWND hCtrl,
                                  UINT ctlColor, HBRUSH& retBrush);
    virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar);
    virtual MsgRouting WmVScroll(UINT scrollCode, UINT pos, HWND hScrollBar);

    virtual MsgRouting WmMouseEnter(UINT flags, int x, int y);
    virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button);
    virtual MsgRouting WmMouseUp(UINT flags, int x, int y, int button);
    virtual MsgRouting WmMouseMove(UINT flags, int x, int y);
    virtual MsgRouting WmMouseExit(UINT flags, int x, int y);
    virtual MsgRouting WmMouseWheel(UINT flags, int x, int y,
                                    int wheelRotation);
    virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
    virtual MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
    virtual MsgRouting WmWindowPosChanging(LPARAM windowPos);
    virtual MsgRouting WmWindowPosChanged(LPARAM windowPos);

    // NB: 64-bit: vkey is wParam of the message, but other API's take
    // vkey parameters of type UINT, so we do the cast before dispatching.
    virtual MsgRouting WmKeyDown(UINT vkey, UINT repCnt, UINT flags, BOOL system);
    virtual MsgRouting WmKeyUp(UINT vkey, UINT repCnt, UINT flags, BOOL system);

    virtual MsgRouting WmChar(UINT character, UINT repCnt, UINT flags, BOOL system);
    virtual MsgRouting WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system);
    virtual MsgRouting WmInputLangChange(UINT charset, HKL hKeyBoardLayout);
    virtual MsgRouting WmForwardChar(WCHAR character, LPARAM lParam,
                                     BOOL synthethic);
    virtual MsgRouting WmPaste();

    virtual void SetCompositionWindow(RECT &r);
    virtual void OpenCandidateWindow(int x, int y);
    virtual void SetCandidateWindow(int iCandType, int x, int y);
    virtual MsgRouting WmImeSetContext(BOOL fSet, LPARAM *lplParam);
    virtual MsgRouting WmImeNotify(WPARAM subMsg, LPARAM bitsCandType);
    virtual MsgRouting WmImeStartComposition();
    virtual MsgRouting WmImeEndComposition();
    virtual MsgRouting WmImeComposition(WORD wChar, LPARAM flags);

    virtual MsgRouting WmTimer(UINT_PTR timerID) {return mrDoDefault;}

    virtual MsgRouting WmCommand(UINT id, HWND hWndCtrl, UINT notifyCode);

    /* reflected WmCommand from parent */
    virtual MsgRouting WmNotify(UINT notifyCode);

    virtual MsgRouting WmCompareItem(UINT /*ctrlId*/,
                                     COMPAREITEMSTRUCT &compareInfo,
                                     LRESULT &result);
    virtual MsgRouting WmDeleteItem(UINT /*ctrlId*/,
                                    DELETEITEMSTRUCT &deleteInfo);
    virtual MsgRouting WmDrawItem(UINT ctrlId,
                                  DRAWITEMSTRUCT &drawInfo);
    virtual MsgRouting WmMeasureItem(UINT ctrlId,
                                     MEASUREITEMSTRUCT &measureInfo);
    /* Fix 4181790 & 4223341 : These functions get overridden in owner-drawn
     * components instead of the Wm... versions.
     */
    virtual MsgRouting OwnerDrawItem(UINT ctrlId,
                                     DRAWITEMSTRUCT &drawInfo);
    virtual MsgRouting OwnerMeasureItem(UINT ctrlId,
                                        MEASUREITEMSTRUCT &measureInfo);

    virtual MsgRouting WmPrint(HDC hDC, LPARAM flags);
    virtual MsgRouting WmPrintClient(HDC hDC, LPARAM flags);

    virtual MsgRouting WmNcCalcSize(BOOL fCalcValidRects,
                                    LPNCCALCSIZE_PARAMS lpncsp,
                                    LRESULT &retVal);
    virtual MsgRouting WmNcPaint(HRGN hrgn);
    virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal);
    virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos);
    virtual MsgRouting WmExitSizeMove();
    virtual MsgRouting WmEnterMenuLoop(BOOL isTrackPopupMenu);
    virtual MsgRouting WmExitMenuLoop(BOOL isTrackPopupMenu);

    virtual MsgRouting WmQueryNewPalette(LRESULT &retVal);
    virtual MsgRouting WmPaletteChanged(HWND hwndPalChg);
    virtual MsgRouting WmPaletteIsChanging(HWND hwndPalChg);
    virtual MsgRouting WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss);
    virtual MsgRouting WmSettingChange(UINT wFlag, LPCTSTR pszSection);

    virtual MsgRouting WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
        return mrDoDefault;
    }

    void UpdateColorModel();

    jintArray CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha);

    /*
     * HWND, AwtComponent and Java Peer interaction
     *
     * Link the C++, Java peer, and HWNDs together.
     */
    void LinkObjects(JNIEnv *env, jobject peer);

    void UnlinkObjects();

    static BOOL QueryNewPaletteCalled() { return m_QueryNewPaletteCalled; }

#ifdef DEBUG
    virtual void VerifyState(); /* verify component and peer are in sync. */
#else
    void VerifyState() {}       /* no-op */
#endif

    virtual AwtDropTarget* CreateDropTarget(JNIEnv* env);
    virtual void DestroyDropTarget();

    INLINE virtual HWND GetDBCSEditHandle() { return NULL; }
    // State for native drawing API
    INLINE jint GetDrawState() { return GetDrawState(m_hwnd); }
    INLINE void SetDrawState(jint state) { SetDrawState(m_hwnd, state); }    // State for native drawing API

    INLINE virtual BOOL IsTopLevel() { return FALSE; }
    INLINE virtual BOOL IsEmbeddedFrame() { return FALSE; }
    INLINE virtual BOOL IsScrollbar() { return FALSE; }

    static INLINE BOOL IsTopLevelHWnd(HWND hwnd) {
        AwtComponent *comp = AwtComponent::GetComponent(hwnd);
        return (comp != NULL && comp->IsTopLevel());
    }
    static INLINE BOOL IsEmbeddedFrameHWnd(HWND hwnd) {
        AwtComponent *comp = AwtComponent::GetComponent(hwnd);
        return (comp != NULL && comp->IsEmbeddedFrame());
    }

    static jint GetDrawState(HWND hwnd);
    static void SetDrawState(HWND hwnd, jint state);

    static HWND GetHWnd(JNIEnv* env, jobject target);

    static MSG* CreateMessage(UINT message, WPARAM wParam, LPARAM lParam, int x, int y);
    static void InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam, int x, int y);

    // Some methods to be called on Toolkit thread via Toolkit.InvokeFunction()
    static void _Show(void *param);
    static void _Hide(void *param);
    static void _Enable(void *param);
    static void _Disable(void *param);
    static jobject _GetLocationOnScreen(void *param);
    static void _Reshape(void *param);
    static void _ReshapeNoCheck(void *param);
    static void _NativeHandleEvent(void *param);
    static void _SetForeground(void *param);
    static void _SetBackground(void *param);
    static void _SetFont(void *param);
    static void _Start(void *param);
    static void _BeginValidate(void *param);
    static void _EndValidate(void *param);
    static void _UpdateWindow(void *param);
    static jlong _AddNativeDropTarget(void *param);
    static void _RemoveNativeDropTarget(void *param);
    static jintArray _CreatePrintedPixels(void *param);
    static jboolean _NativeHandlesWheelScrolling(void *param);
    static void _SetRectangularShape(void *param);
    static void _SetZOrder(void *param);

    static HWND sm_focusOwner;

private:
    static HWND sm_focusedWindow;

public:
    static inline HWND GetFocusedWindow() { return sm_focusedWindow; }
    static void SetFocusedWindow(HWND window);

    static void _SetFocus(void *param);

    static void *SetNativeFocusOwner(void *self);
    static void *GetNativeFocusedWindow();
    static void *GetNativeFocusOwner();

    static BOOL sm_inSynthesizeFocus;

    // Execute on Toolkit only.
    INLINE static LRESULT SynthesizeWmSetFocus(HWND targetHWnd, HWND oppositeHWnd) {
        sm_inSynthesizeFocus = TRUE;
        LRESULT res = ::SendMessage(targetHWnd, WM_SETFOCUS, (WPARAM)oppositeHWnd, 0);
        sm_inSynthesizeFocus = FALSE;
        return res;
    }
    // Execute on Toolkit only.
    INLINE static LRESULT SynthesizeWmKillFocus(HWND targetHWnd, HWND oppositeHWnd) {
        sm_inSynthesizeFocus = TRUE;
        LRESULT res = ::SendMessage(targetHWnd, WM_KILLFOCUS, (WPARAM)oppositeHWnd, 0);
        sm_inSynthesizeFocus = FALSE;
        return res;
    }

    static BOOL sm_bMenuLoop;
    static INLINE BOOL isMenuLoopActive() {
        return sm_bMenuLoop;
    }

    // when this component is being destroyed, this method is called
    // to find out if there are any messages being processed, and if
    // there are some then disposal of this component is postponed
    virtual BOOL CanBeDeleted() {
        return m_MessagesProcessing == 0;
    }

    BOOL IsDestroyPaused() const {
        return m_bPauseDestroy;
    }

protected:
    static AwtComponent* GetComponentImpl(HWND hWnd);

    static int GetClickCount();

    HWND     m_hwnd;
    UINT     m_myControlID;     /* its own ID from the view point of parent */
    BOOL     m_backgroundColorSet;
    BOOL     m_visible;         /* copy of Component.visible */

    static BOOL sm_suppressFocusAndActivation;
    static BOOL sm_restoreFocusAndActivation;

    /*
     * The function sets the focus-restore flag ON/OFF.
     * When the flag is ON, focus is restored immidiately after the proxy loses it.
     * All focus messages are suppressed. It's also assumed that sm_focusedWindow and
     * sm_focusOwner don't change after the flag is set ON and before it's set OFF.
     */
    static INLINE void SetRestoreFocus(BOOL doSet) {
        sm_suppressFocusAndActivation = doSet;
        sm_restoreFocusAndActivation = doSet;
    }

    virtual void SetDragCapture(UINT flags);
    virtual void ReleaseDragCapture(UINT flags);

    virtual void FillBackground(HDC hMemoryDC, SIZE &size);
    virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);

private:
    /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
     * which are allowed to
     * generate the CLICK event after the RELEASE has happened.
     * There are conditions that must be true for that sending CLICK event:
     * 1) button was initially PRESSED
     * 2) no movement or drag has happened until RELEASE
    */
    UINT m_mouseButtonClickAllowed;

    BOOL m_bSubclassed;
    BOOL m_bPauseDestroy;

    COLORREF m_colorForeground;
    COLORREF m_colorBackground;

    AwtPen*  m_penForeground;
    AwtBrush* m_brushBackground;

    WNDPROC  m_DefWindowProc;
    // counter for messages being processed by this component
    UINT     m_MessagesProcessing;

    // provides a unique ID for child controls
    UINT     m_nextControlID;

    // DeferWindowPos handle for batched-up window positioning
    HDWP     m_hdwp;
    // Counter to handle nested calls to Begin/EndValidate
    UINT     m_validationNestCount;

    AwtDropTarget* m_dropTarget; // associated DropTarget object

    // When we process WM_INPUTLANGCHANGE we remember the keyboard
    // layout handle and associated input language and codepage.
    // We also invalidate VK translation table for VK_OEM_* codes
    static HKL    m_hkl;
    static UINT   m_CodePage;
    static LANGID m_idLang;

    static BOOL sm_rtl;
    static BOOL sm_rtlReadingOrder;

    static BOOL sm_PrimaryDynamicTableBuilt;

    jobject m_InputMethod;
    BOOL    m_useNativeCompWindow;
    LPARAM  m_bitsCandType;
    UINT    m_PendingLeadByte;

    void SetComponentInHWND();

    // Determines whether a given virtual key is on the numpad
    static BOOL IsNumPadKey(UINT vkey, BOOL extended);

    // Determines the keyLocation of a given key
    static jint GetKeyLocation(UINT wkey, UINT flags);
    static jint GetShiftKeyLocation(UINT wkey, UINT flags);

    // Cache for FindComponent
    static HWND sm_cursorOn;

    static BOOL m_QueryNewPaletteCalled;

    static AwtComponent* sm_getComponentCache; // a cache for the GetComponent(..) method.

    int windowMoveLockPosX;
    int windowMoveLockPosY;
    int windowMoveLockPosCX;
    int windowMoveLockPosCY;

    // 6524352: support finer-resolution
    int m_wheelRotationAmount;

    /*
     * The association list of children's IDs and corresponding components.
     * Some components like Choice or List are required their sizes while
     * the creations of themselfs are in progress.
     */
    class ChildListItem {
    public:
        ChildListItem(UINT id, AwtComponent* component) {
            m_ID = id;
            m_Component = component;
            m_next = NULL;
        }
        ~ChildListItem() {
            if (m_next != NULL)
                delete m_next;
        }

        UINT m_ID;
        AwtComponent* m_Component;
        ChildListItem* m_next;
    };

public:
    INLINE void PushChild(UINT id, AwtComponent* component) {
        ChildListItem* child = new ChildListItem(id, component);
        child->m_next = m_childList;
        m_childList = child;
    }

    static void SetParent(void * param);
private:
    AwtComponent* SearchChild(UINT id);
    void RemoveChild(UINT id) ;
    static BOOL IsNavigationKey(UINT wkey);
    static void BuildPrimaryDynamicTable();

    ChildListItem* m_childList;

    HCURSOR m_hCursorCache; // the latest cursor which has been active within the heavyweight component
public:
    inline void setCursorCache(HCURSOR hCursor) {
        m_hCursorCache = hCursor;
    }
    inline HCURSOR getCursorCache() {
        return m_hCursorCache;
    }
};

class CounterHelper {
private:
    UINT *m_counter;
public:
    explicit CounterHelper(UINT *counter) {
        m_counter = counter;
        (*m_counter)++;
    }
    ~CounterHelper() {
        (*m_counter)--;
        m_counter = NULL;
    }
};

// DC management objects; these classes are used to track the list of
// DC's associated with a given Component.  Then DC's can be released
// appropriately on demand or on window destruction to avoid resource
// leakage.
class DCItem {
public:
    HDC             hDC;
    HWND            hWnd;
    DCItem          *next;
};
class DCList {
    DCItem          *head;
    CriticalSection listLock;
public:
    DCList() { head = NULL; }

    void            AddDC(HDC hDC, HWND hWnd);
    void            AddDCItem(DCItem *newItem);
    DCItem          *RemoveDC(HDC hDC);
    DCItem          *RemoveAllDCs(HWND hWnd);
    void            RealizePalettes(int screen);
};

void ReleaseDCList(HWND hwnd, DCList &list);
void MoveDCToPassiveList(HDC hDC);

namespace TimeHelper{
    jlong getMessageTimeUTC();
    jlong windowsToUTC(DWORD event_offset);
}

#include "ObjectList.h"

#endif /* AWT_COMPONENT_H */
