Milán Major

netscape-revival

1 branch
Code

sun-java/awt/win/awt_textcomponent.cpp

#include "awt_textcomponent.h"
#include "awt_defs.h"
#ifdef INTLUNICODE
#include "awt_i18n.h"
#endif // INTLUNICODE


// All java header files are extern "C"
extern "C" {
#include "java_awt_Component.h"

#include "sun_awt_windows_WComponentPeer.h"
#include "sun_awt_windows_WTextComponentPeer.h"
};


// -----------------------------------------------------------------------
//
// Constructor
//
// -----------------------------------------------------------------------
AwtTextComponent::AwtTextComponent(JHandle *peer) : AwtWindow(peer)
{
    DEFINE_AWT_SENTINAL("TXC");
    hinst = (HINSTANCE) NULL;
}


// -----------------------------------------------------------------------
//
// Destructor
//
// -----------------------------------------------------------------------
AwtTextComponent::~AwtTextComponent()
{
#if 0
    //
    // REMIND:
    // If we free the Edit Control's buffer here, Windows crashes...
    // It must be freed when the EDIT control has been deleted
    //
#if !defined(_WIN32)
    if (hinst != (HINSTANCE) NULL) {
        ::GlobalFree(hinst);
        hinst = NULL;
    }
#endif  // !_WIN32
#endif // 0
}


// -----------------------------------------------------------------------
//
// Return the window ex-style used to create an AwtListbox window
//
// -----------------------------------------------------------------------
DWORD AwtTextComponent::WindowExStyle()
{
#ifdef _WIN32
    return WS_EX_CLIENTEDGE;
#else
    return 0;
#endif
}


// -----------------------------------------------------------------------
//
// Special hInst parameter to ::CreateWindow  
//
// -----------------------------------------------------------------------
HINSTANCE AwtTextComponent::WindowHInst()
{
#ifdef _WIN32
    return ::GetModuleHandle(__awt_dllName);
#else
    // REMIND: The size should be different for TextAreas & TextFields
    //         Maybe the GlobalAlloc should be done in the constructor ??
    if (hinst == (HINSTANCE) NULL) {
        hinst = (HINSTANCE) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, 8192L);
    }
    return hinst;
#endif
}

// -----------------------------------------------------------------------
//
// Toggle whether the TextArea is Read-Only
//
// -----------------------------------------------------------------------
void AwtTextComponent::SetEditable(BOOL bState)
{
    ASSERT( ::IsWindow(m_hWnd) );
    VERIFY( ::SendMessage(m_hWnd, EM_SETREADONLY, (WPARAM) !bState, 0L) );
}


// -----------------------------------------------------------------------
//
// Return a copy of the contents of the edit control.
//
// -----------------------------------------------------------------------
Hjava_lang_String* AwtTextComponent::GetText(void)
{
    int len;
    char *buffer = NULL;
    Hjava_lang_String *string = NULL;

    ASSERT( ::IsWindow(m_hWnd) );

    //
    // Lock the object to prevent other threads from changing the
    // contents of the Edit control..
    //
    Lock();

    len = ::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0);
    buffer = (char *)malloc(len+1);
    if (buffer) {
        ::SendMessage(m_hWnd, WM_GETTEXT, len+1, (LPARAM)buffer);
#ifdef INTLUNICODE
		string = (Hjava_lang_String*)libi18n::intl_makeJavaString(GetPrimaryEncoding(), buffer, len);
#else	// INTLUNICODE
		string = makeJavaString(buffer, len);
#endif	// INTLUNICODE
	}

    Unlock();
    return string;
}


// -----------------------------------------------------------------------
//
// Set the edit buffer to the contents of a Java String.
//
// This method does not require locking because no member variables
// are accessed and SendMessage is synchronized already 
//
//
// -----------------------------------------------------------------------
void AwtTextComponent::SetText(Hjava_lang_String *string)
{
    char *buffer;
#ifdef INTLUNICODE
	buffer = libi18n::intl_allocCString(this->GetPrimaryEncoding() , string);
	if(buffer) {
		::SendMessage(m_hWnd, WM_SETTEXT, 0, (LPARAM)buffer);
		free(buffer);
	}
#else	// INTLUNICODE
    long len;

    len    = javaStringLength(string);
    buffer = (char *)malloc(len+1);

    if (buffer) {
        javaString2CString(string, buffer, len+1);

		::SendMessage(m_hWnd, WM_SETTEXT, 0, (LPARAM)buffer);

		free(buffer);
	}
#endif	// INTLUNICODE
}


// -----------------------------------------------------------------------
//
// Return the starting position of the selected text in the Edit buffer...
//
// This method does not require locking because no member variables
// are accessed!.  The SendMessage(...) synchronizes the access to the 
// edit buffer.
//
// -----------------------------------------------------------------------
long AwtTextComponent::GetSelectionStart(void)
{
    long selStart;

    ASSERT( ::IsWindow(m_hWnd) );

#ifdef INTLUNICODE
    Lock();
#endif

#ifdef _WIN32
    /*selStart =*/ ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&selStart, NULL);
#else
    selStart = ::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
    selStart = LOWORD(selStart);
#endif

#ifdef INTLUNICODE
//
//	For Unicode support, we need to convert the selStart which EM_GETSEL return from
//	byte count to character length
//
	if(selStart > 0)
	{
		int len = ::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0);
		unsigned char *buffer = NULL;
		if(len > 0)
			buffer = (unsigned char *)malloc(len+1);
		if (buffer) {
			::SendMessage(m_hWnd, WM_GETTEXT, len+1, (LPARAM)buffer);
			selStart = libi18n::INTL_TextByteCountToCharLen(this->GetPrimaryEncoding(), 
						buffer, selStart);
			free(buffer);
		}
	}
    Unlock();
#endif

    return selStart;
}


// -----------------------------------------------------------------------
//
// Return the ending position of the selected text in the Edit buffer...
//
// This method does not require locking because no member variables
// are accessed!.  The SendMessage(...) synchronizes the access to the 
// edit buffer.
//
// -----------------------------------------------------------------------
long AwtTextComponent::GetSelectionEnd(void)
{
    long selEnd;

    ASSERT( ::IsWindow(m_hWnd) );

#ifdef INTLUNICODE
    Lock();
#endif

#ifdef _WIN32
    /*selEnd =*/ ::SendMessage(m_hWnd, EM_GETSEL, NULL, (LPARAM)&selEnd);
#else
    selEnd = ::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
    selEnd = HIWORD(selEnd);
#endif

#ifdef INTLUNICODE
//
//	For Unicode support, we need to convert the selEnd which EM_GETSEL return from
//	byte count to character length
//
	if(selEnd > 0)
	{
		int len = ::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0);
		unsigned char* buffer = NULL;
		if(len > 0)
			buffer = (unsigned char *)malloc(len+1);
		if (buffer) {
			::SendMessage(m_hWnd, WM_GETTEXT, len+1, (LPARAM)buffer);
			selEnd = libi18n::INTL_TextByteCountToCharLen(this->GetPrimaryEncoding(), 
						buffer, selEnd);
			free(buffer);
		}
	}
    Unlock();
#endif

    return selEnd;
}


// -----------------------------------------------------------------------
//
// Select the specified range of text in the edit control...
//
// -----------------------------------------------------------------------
void AwtTextComponent::SelectText(long start, long end)
{
    ASSERT( ::IsWindow(m_hWnd) );

#ifdef INTLUNICODE
//
//	For Unicode support, we need to convert the selEnd which EM_GETSEL return from
//	byte count to character length
//
	Lock();
    int len = ::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0);
    unsigned char * buffer = NULL;
	if(len > 0)
		buffer = (unsigned char *)malloc(len+1);
    if (buffer) {
        ::SendMessage(m_hWnd, WM_GETTEXT, len+1, (LPARAM)buffer);
		int charLen = libi18n::INTL_TextByteCountToCharLen(this->GetPrimaryEncoding(), 
					buffer, len);
		if((start > 0) && (start <= charLen))
		{
			start = libi18n::INTL_TextCharLenToByteCount(this->GetPrimaryEncoding(), 
					buffer, start);
		}
		if((end > 0) && (end <= charLen))
		{
			end = libi18n::INTL_TextCharLenToByteCount(this->GetPrimaryEncoding(), 
					buffer, end);
		}
		free(buffer);
	}

    Unlock();
#endif


    //
    // Select the specified range of text in the Edit control
    //
#ifdef _WIN32
    ::SendMessage(m_hWnd, EM_SETSEL, (WPARAM)start, (LPARAM)end);
#else
    ::SendMessage(m_hWnd, EM_SETSEL, (WPARAM)1, MAKELONG((int)start, (int)end));
#endif
}


BOOL AwtTextComponent::OnPaint( HDC hdc, int x, int y, int w, int h )
{                                                                
    return AwtComponent::OnPaint(hdc, x, y, w, h);
}
    

BOOL AwtTextComponent::OnEraseBackground( HDC hdc )
{
    //return TRUE;
    return FALSE;
}


//-------------------------------------------------------------------------
//
// Capture the mouse (if it's not the left button) so that mouse events 
// get re-direct to the proper component. 
// This allow MouseDrag to work correctly and MouseUp to be sent to the 
// component which received the mouse down.
// Left down is a special case becouse windows needs to do that.
//
//-------------------------------------------------------------------------
void AwtTextComponent::CaptureMouse(AwtButtonType button, UINT metakeys)
{
    // capture the mouse if it was not captured already.
    // This may happen because of a previous call to CaptureMouse
    // or because the left mouse was clicked and windows captured
    // the mouse for us.
    // Here we use m_nCaptured with a different semantic.
    // It's setted to 1 if SetCapture gets called, otherwise is 0
    if (button == AwtLeftButton)
        m_nCaptured = 0;
    else if (!(metakeys & MK_LBUTTON) && !m_nCaptured) {
        ::SetCapture(m_hWnd);
        m_nCaptured = 1;
    }
}


//-------------------------------------------------------------------------
//
// Release the mouse if the counter reaches zero. We need a counter so
// that if a second button get pressed while the other is pressed already
// we are still able to send MouseUp to the right component
//
//-------------------------------------------------------------------------
BOOL AwtTextComponent::ReleaseMouse(AwtButtonType button, UINT metakeys, int x, int y)
{
    // if at least the left button is pressed don't bother...
    if (!(metakeys & MK_LBUTTON)) {

        // check if no button is pressed and if we called SetCapture release it
        if (!(metakeys & MK_RBUTTON) && !(metakeys & MK_MBUTTON)) {
            if (m_nCaptured) {
                ::ReleaseCapture();
                m_nCaptured = 0;
            }
        }

        // the left button has just been released...
        else if (button == AwtLeftButton) {
            // ...see if there is any other button pressed...
            if ((metakeys & MK_RBUTTON) || (metakeys & MK_MBUTTON)) {
                    // Windows is giving up the mouse capture, it's time to take it. 
                    // Let the defproc do MouseUp first so it will release the mouse 
                    // before we capture otherwise WM_LBUTTONUP will release our capture
                    ::CallWindowProc(m_PrevWndProc, 
                                        m_hWnd, 
                                        WM_LBUTTONUP, 
                                        (WPARAM)metakeys, 
                                        MAKELPARAM(x, y));
                    ::SetCapture(m_hWnd);
                    m_nCaptured = 1;
                    return TRUE;
            }
        }

    }

    return FALSE;
}


//-------------------------------------------------------------------------
//
// Native method implementations for sun.awt.WTextAreaPeer
//
//-------------------------------------------------------------------------

extern "C" {

void
sun_awt_windows_WTextComponentPeer_widget_setEditable(HWTextComponentPeer *self, 
													long flag)
{
    CHECK_PEER(self);

    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);

    obj->SetEditable((BOOL)flag);
}


void
sun_awt_windows_WTextComponentPeer_select(HWTextComponentPeer *self, 
										long start, long end)
{
    CHECK_PEER(self);

    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);
    
    obj->SelectText(start, end);
}


long
sun_awt_windows_WTextComponentPeer_getSelectionStart(HWTextComponentPeer *self)
{
    CHECK_PEER_AND_RETURN(self, 0);

    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);
    
    return obj->GetSelectionStart();
}


long
sun_awt_windows_WTextComponentPeer_getSelectionEnd(HWTextComponentPeer *self)
{
    CHECK_PEER_AND_RETURN(self, 0);

    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);

    return obj->GetSelectionEnd();
}


void
sun_awt_windows_WTextComponentPeer_setText(HWTextComponentPeer *self, 
                                      Hjava_lang_String *string)
{
    CHECK_PEER(self);
    CHECK_NULL(string, "null text");

    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);

    obj->SetText(string);
}


Hjava_lang_String *
sun_awt_windows_WTextComponentPeer_getText(HWTextComponentPeer *self)
{
    CHECK_PEER_AND_RETURN(self, NULL);

    Hjava_lang_String *string;
    AwtTextComponent *obj = GET_OBJ_FROM_PEER(AwtTextComponent, self);

    string = obj->GetText();
    return string;
}

}; // end of extern "C"