webengine/osswebengine/WebKit/s60/webview/WebFepTextEditor.cpp
author Kiiskinen Klaus (Nokia-D-MSW/Tampere) <klaus.kiiskinen@nokia.com>
Mon, 30 Mar 2009 12:54:55 +0300
changeset 0 dd21522fd290
child 8 7c90e6132015
permissions -rw-r--r--
Revision: 200911 Kit: 200912

/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   WebFepTextEditor.cpp
*
*/



#include "config.h"
#include "../../bidi.h"

#include "WebFepTextEditor.h"
#include "WebEditorClient.h"
#include "WebTextFormatMask.h"
#include "WebView.h"
#include "WebFrame.h"
#include "Page.h"
#include "FocusController.h"

#include "Frame.h"
#include "Editor.h"
#include "HtmlNames.h"
#include "EventHandler.h"
#include "HtmlInputElement.h"
#include "HtmlTextAreaElement.h"
#include "PlatformKeyboardEvent.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"

#include <coemain.h>
#include <eikpanic.h>
#include <aknedsts.h>
#include <aknutils.h>
#include "Text.h"

using namespace WebCore;

static const int kInfinite = -1;
_LIT(KBlankDesC," ");

GLDEF_C void Panic(TEikPanic aPanic)
    {
    _LIT(KPanicCat,"WEBKIT-FEP");
    User::Panic(KPanicCat,aPanic);
    }

// -----------------------------------------------------------------------------
// CWebFepTextEditor
// 
// 
// -----------------------------------------------------------------------------
CWebFepTextEditor::CWebFepTextEditor(WebView* aView)
    : m_webView(aView),
      m_textFormatMask(NULL),
      m_inlineEditText(NULL)
{
    // Set up the extended capabilities
    TRAP_IGNORE(
        m_ExtendedInputCapabilities = CAknExtendedInputCapabilities::NewL();
        );

    // Set alignment on m_ExtendedInputCapabilities, yes it checks if NULL
    // The EInputEditorAlignXXX flags are defined for 5.0+ platforms
#if defined(BRDO_BROWSER_50_FF)
    SetAlignment( CAknExtendedInputCapabilities::EInputEditorAlignBidi );
#endif
	EnableCcpu(ETrue);
}

// -----------------------------------------------------------------------------
// ~CWebFepTextEditor
// 
// 
// -----------------------------------------------------------------------------
CWebFepTextEditor::~CWebFepTextEditor()
    {
    delete m_state;
    delete m_inlineEditText;
    delete m_textFormatMask;
    }

// -----------------------------------------------------------------------------
// CreateTextFormatMask
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CreateTextFormatMask()
{
    if (!m_textFormatMask) {        
        Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
        if (frame &&
            frame->document() &&
            frame->document()->focusedNode()) {                
            RenderStyle* s = frame->document()->focusedNode()->renderStyle();      
            if (s && 
            	(!s->wapInputFormat().isEmpty() || s->wapInputRequired())){            
                m_textFormatMask = new WebTextFormatMask(s->wapInputFormat(), s->wapInputRequired());
            }
        }
    }
}              

// -----------------------------------------------------------------------------
// UpdateEditingMode
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateEditingMode()
{        
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame) {
        SelectionController* sc = frame->selectionController();
        if (sc && sc->isContentEditable() && sc->isInPasswordField()) {       
            
            // Set the state as if it was the CEikSecretEditor
            CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));  
            if (state) {
                state->SetFlags( EAknEditorFlagNoLRNavigation |
                                        EAknEditorFlagLatinInputModesOnly |
                                        EAknEditorFlagNoT9 |
                                        EAknEditorFlagUseSCTNumericCharmap );

                state->SetDefaultInputMode(EAknEditorSecretAlphaInputMode);
                state->SetCurrentInputMode(EAknEditorSecretAlphaInputMode);
                state->SetPermittedCases(EAknEditorLowerCase|EAknEditorUpperCase);
                state->SetCurrentCase(EAknEditorLowerCase);    
                state->SetPermittedInputModes(EAknEditorSecretAlphaInputMode | EAknEditorNumericInputMode);
                state->SetDefaultCase(EAknEditorLowerCase);
                state->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG_LATIN_ONLY);    
                state->SetNumericKeymap(EAknEditorPlainNumberModeKeymap);
            }
            
        }
        else {       
            
            CreateTextFormatMask();
            
            TUint currentCase ( EAknEditorLowerCase ) ;
            TUint permittedCase ( EAknEditorAllCaseModes ) ;
            TUint inputMode( EAknEditorNullInputMode );
            TUint permittedInputModes( EAknEditorAllInputModes );            
            TUint flags( EAknEditorFlagDefault ); 
            TUint numericKeyMap( EAknEditorStandardNumberModeKeymap ); 

            if (GetStateFromFormatMask(currentCase, permittedCase, inputMode, permittedInputModes, flags, numericKeyMap)) {             
                UpdateFlagsState(flags);
                UpdateInputModeState(inputMode, permittedInputModes, numericKeyMap);
                UpdateCaseState(currentCase, permittedCase);                 
            }
            else {
                CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));  
                if (state) {
                    state->SetPermittedInputModes(EAknEditorAllInputModes);
                    state->SetPermittedCases(EAknEditorAllCaseModes);//allow everything
                }
            }
        }
    }   // End of if (frame)
}
    
// -----------------------------------------------------------------------------
// CancelEditingMode
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CancelEditingMode()
    {        
    delete m_textFormatMask;
    m_textFormatMask = NULL;

    delete m_inlineEditText;    
    m_inlineEditText = NULL;    

    UpdateFlagsState(EAknEditorFlagDefault);
    UpdateInputModeState(EAknEditorNullInputMode, EAknEditorAllInputModes,EAknEditorStandardNumberModeKeymap);
    UpdateCaseState(EAknEditorLowerCase, EAknEditorAllCaseModes);            
    
    CancelFepInlineEdit();
    }
    
// -----------------------------------------------------------------------------
// ActivatePenInputRequest
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::ActivatePenInputRequest()
{ 
    CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));                
    if ( state ) {                    
        TRAP_IGNORE( state->ReportAknEdStateEventL(MAknEdStateObserver::EAknActivatePenInputRequest ) );
    }    
}

// -----------------------------------------------------------------------------
// DeactivatePenInputRequest
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::DeactivatePenInputRequest()
    {        
    }

// -----------------------------------------------------------------------------
// InputCapabilities
// 
// 
// -----------------------------------------------------------------------------
TCoeInputCapabilities CWebFepTextEditor::InputCapabilities()    
{
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame) {
        SelectionController* sc = frame->selectionController();
        if (sc && sc->isContentEditable()) {       

            // Set up the input capabilities, based on the <input> box
            TUint caps = TCoeInputCapabilities::ENavigation;                
            
            if ( sc->isInPasswordField() ) {           
                caps |= TCoeInputCapabilities::ESecretText;                            
            }
            else {
             
                CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));                
                if ( state ) {                    
                    if ( state->PermittedInputModes() == EAknEditorNumericInputMode ) {
                        caps |= (TCoeInputCapabilities::EWesternNumericIntegerPositive |
                                 TCoeInputCapabilities::EWesternNumericIntegerNegative)| 
                                 TCoeInputCapabilities::EAllText;
                    }        
                    else if (  state->PermittedInputModes() == EAknEditorTextInputMode ) {            
                        caps |= TCoeInputCapabilities::EWesternAlphabetic;
                    }
                    else if (  state->PermittedInputModes() == (EAknEditorTextInputMode | EAknEditorNumericInputMode) ) {            
                        caps |= (TCoeInputCapabilities::EWesternNumericIntegerPositive |
                                 TCoeInputCapabilities::EWesternNumericIntegerNegative |
                                 TCoeInputCapabilities::EWesternAlphabetic);
                    }
                    else {
                        caps |=  TCoeInputCapabilities::EAllText;         
                    }            
                }
            }

            // Set up the extended input capabilities, based on dir="rtl".
            // EInputEditorAlignXXX flags are only valid for 5.0+ platform.
#if defined(BRDO_BROWSER_50_FF)
            if ( IsDirectionRTL() ) {
                SetAlignment(CAknExtendedInputCapabilities::EInputEditorAlignRight );
            }
            else {
                SetAlignment(CAknExtendedInputCapabilities::EInputEditorAlignBidi );
            }
#endif
            // Set up the ObjectProvider, so ExtendedInputCapablities can be called by FEP.
            // MObjectProvider callback method MopSupplyObject().
            TCoeInputCapabilities inputCaps( caps, this, NULL, TUid::Uid(0x100056de), this );
            inputCaps.SetObjectProvider( this );
            
            return inputCaps;
        }
    }

    // Empty input capabilities
    TCoeInputCapabilities emptyCaps(TCoeInputCapabilities::ENone);
    emptyCaps.SetObjectProvider( this );

    return emptyCaps;
}


////////////////////////////////////////////////////////////////////////////////
// from MCoeFepAwareTextEditor  
//

// -----------------------------------------------------------------------------
// StartFepInlineEditL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::StartFepInlineEditL(
      const TDesC& aInitialInlineText,
      TInt /*aPositionOfInsertionPointInInlineText*/,
      TBool /*aCursorVisibility*/,
      const MFormCustomDraw*,
      MFepInlineTextFormatRetriever&,
      MFepPointerEventHandlerDuringInlineEdit& /*aPointerEventHandlerDuringInlineEdit*/)
{    
    CCoeEnv::Static()->ForEachFepObserverCall(FepObserverHandleStartOfTransactionL);              
    ClearInlineText();        
    UpdateInlineText(aInitialInlineText);       
}

// -----------------------------------------------------------------------------
// UpdateFepInlineTextL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateFepInlineTextL( const TDesC& aNewInlineText,
								TInt /*aPositionOfInsertionPointInInlineText*/ )
{        
    ClearInlineText();        
    UpdateInlineText(aNewInlineText);       
}

// -----------------------------------------------------------------------------
// SetInlineEditingCursorVisibilityL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::SetInlineEditingCursorVisibilityL(TBool /*aCursorVisibility*/)
{
}

// -----------------------------------------------------------------------------
// CancelFepInlineEdit
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CancelFepInlineEdit()
{
}

// -----------------------------------------------------------------------------
// DocumentLengthForFep
// 
// 
// -----------------------------------------------------------------------------
TInt CWebFepTextEditor::DocumentLengthForFep() const
{
    TInt length = 0;
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame &&
        frame->document() &&
        frame->document()->focusedNode()) {

        if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
            HTMLInputElement* ie = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
            length = ie->value().length();
        }
        else if (frame->document()->focusedNode()->hasTagName(HTMLNames::textareaTag)) {
            HTMLTextAreaElement* ie = static_cast<HTMLTextAreaElement*>(frame->document()->focusedNode());
            length = ie->value().length();
        }
    }

    return length;    
}

// -----------------------------------------------------------------------------
// DocumentMaximumLengthForFep
// 
// 
// -----------------------------------------------------------------------------
TInt CWebFepTextEditor::DocumentMaximumLengthForFep() const
{       
    TInt length = KMaxTInt;       

    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame &&
        frame->document() &&
        frame->document()->focusedNode() &&
        frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag) ) {                   
        length = static_cast<HTMLInputElement*>(frame->document()->focusedNode())->maxLength();
    }

	// Override the length if a text format mask is set
	if ( m_textFormatMask && m_textFormatMask->getMultitude() > 0 )
        length = m_textFormatMask->getMultitude();

    // TextArea node has no member function maxLength(), so return KMaxTInt
    return length;
}

// -----------------------------------------------------------------------------
// SetCursorSelectionForFepL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
{    
    // The other part of the rather hackish way to check if we are at the end of the editing field
    // see WebEditorClient::handleKeypress
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if ( frame ) {           
        SelectionController* sc = frame->selectionController();
        Node* editNode = sc->base().node();
        if ( IsTextAreaFocused() ) {
			TInt position( aCursorSelection.iAnchorPos );
			TInt offset( 0 );
			if ( editNode ) {
				editNode = findTextNodeForCurPos( editNode, position );
				if ( aCursorSelection.iAnchorPos > position ) {
					offset = aCursorSelection.iAnchorPos - position;
				}
				Position base( editNode, offset );
				Position extent( editNode, offset );
				sc->moveTo( base, extent, DOWNSTREAM );
			}
		}
		else if ( editNode && editNode->isTextNode() ) { 
			Position base( sc->baseNode(), aCursorSelection.iAnchorPos );
			Position extent( sc->baseNode(), aCursorSelection.iCursorPos );
			sc->moveTo( base, extent, DOWNSTREAM );   
		}
		HandleUpdateCursor();
    }
}

// -----------------------------------------------------------------------------
// GetCursorSelectionForFep
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const
{
    aCursorSelection.SetSelection(0,0);
    
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if ( frame ) {           
        SelectionController* sc = frame->selectionController();
        Node* editNode = sc->base().node();
		if ( frame && frame->document()->focusedNode() ) {
			if ( IsTextAreaFocused() ) {
				TInt len( 0 );
				if ( editNode ) {
					findPrevSiblingTextLen( editNode, len );  
				}
				aCursorSelection.SetSelection( sc->baseOffset() + len,
											   sc->extentOffset() + len );
			}
			else {
				aCursorSelection.SetSelection(sc->baseOffset(), sc->extentOffset());       
			}
		}
	}
}

// -----------------------------------------------------------------------------
// GetEditorContentForFep
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::GetEditorContentForFep( TDes& aEditorContent,
												TInt aDocumentPosition,
												TInt aLengthToRetrieve ) const
{    
    aEditorContent = KNullDesC;   	   // KNullDesC has length 0

    if (aLengthToRetrieve == 0) {
        return;
    }
        
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame &&
        frame->document() &&
        frame->document()->focusedNode()) {

        if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
            HTMLInputElement* ie = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
            aEditorContent = ie->value().substring(aDocumentPosition, aLengthToRetrieve);
        }
        else if (frame->document()->focusedNode()->hasTagName(HTMLNames::textareaTag)) {
            HTMLTextAreaElement* ie = static_cast<HTMLTextAreaElement*>(frame->document()->focusedNode());
            // Convert the newline to paragraph separator, because the FEP
            // input editors (vkb, etc) ignore newline
            String str(ie->value().substring(aDocumentPosition, aLengthToRetrieve));
            str.replace(EKeyLineFeed, CEditableText::EParagraphDelimiter);  
            aEditorContent = str;        
        }
    }
}

// -----------------------------------------------------------------------------
// GetFormatForFep
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::GetFormatForFep(TCharFormat& /*aFormat*/,TInt /*aDocumentPosition*/) const
{         
}

// -----------------------------------------------------------------------------
// GetScreenCoordinatesForFepL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::GetScreenCoordinatesForFepL(TPoint& /*aLeftSideOfBaseLine*/,
                                                    TInt& /*aHeight*/,
                                                    TInt& /*aAscent*/,
                                                    TInt /*aDocumentPosition*/) const
{    
}

// -----------------------------------------------------------------------------
// DoCommitFepInlineEditL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::DoCommitFepInlineEditL()
{                    
    ClearInlineText();     

    if (m_inlineEditText && DocumentLengthForFep() < DocumentMaximumLengthForFep()) {
        Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
        if (frame){
            frame->editor()->insertTextWithoutSendingTextEvent(String(*m_inlineEditText), false);
        }
    }
    
    //delete the m_inlineEditText since text is commited
    delete m_inlineEditText;    
    m_inlineEditText = NULL;    

    HandleUpdateCursor();
    UpdateEditingMode();
}

// -----------------------------------------------------------------------------
// Extension1
// 
// 
// -----------------------------------------------------------------------------
MCoeFepAwareTextEditor_Extension1* CWebFepTextEditor::Extension1(TBool& aSetToTrue)
{
    aSetToTrue=ETrue;
    return STATIC_CAST(MCoeFepAwareTextEditor_Extension1*, this);
}

// -----------------------------------------------------------------------------
// MCoeFepAwareTextEditor_Reserved_2
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::MCoeFepAwareTextEditor_Reserved_2()
{
}
           
////////////////////////////////////////////////////////////////////////////////
// from MCoeFepAwareTextEditor_Extension1

// -----------------------------------------------------------------------------
// SetStateTransferingOwnershipL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::SetStateTransferingOwnershipL(CState* aState, TUid /*aTypeSafetyUid*/)
{
    delete m_state;
    m_state = aState;    
}

// -----------------------------------------------------------------------------
// State
// 
// 
// -----------------------------------------------------------------------------
MCoeFepAwareTextEditor_Extension1::CState* CWebFepTextEditor::State(TUid /*aTypeSafetyUid*/)
{
    if (!m_state) {
        CAknEdwinState* state = new CAknEdwinState();
        state->SetObjectProvider(m_webView);
        m_state = state;
        }
    return m_state;
}

// -----------------------------------------------------------------------------
// StartFepInlineEditL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::StartFepInlineEditL(
        TBool& aSetToTrue, 
        const TCursorSelection& aCursorSelection, 
        const TDesC& aInitialInlineText, 
        TInt aPositionOfInsertionPointInInlineText, 
        TBool aCursorVisibility, 
        const MFormCustomDraw* aCustomDraw, 
        MFepInlineTextFormatRetriever& aInlineTextFormatRetriever, 
        MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit)
{
    aSetToTrue=ETrue;
    SetCursorSelectionForFepL(aCursorSelection);
    StartFepInlineEditL(aInitialInlineText, aPositionOfInsertionPointInInlineText, aCursorVisibility, aCustomDraw, aInlineTextFormatRetriever, aPointerEventHandlerDuringInlineEdit);
}

// -----------------------------------------------------------------------------
// SetCursorType
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::SetCursorType(TBool& /*aSetToTrue*/, const TTextCursor& /*aTextCursor*/)
{
}

////////////////////////////////////////////////////////////////////////////////
// from TCoeInputCapabilities::MCoeFepSpecificExtensions

// -----------------------------------------------------------------------------
// IsValidCharacter
// 
// 
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::IsValidCharacter(TInt aChar)
{
     return ETrue;
}
 
////////////////////////////////////////////////////////////////////////////////
// from MObjectProvider

// -----------------------------------------------------------------------------
// MopSupplyObject
// Fep Manager will call us to get pointers to our bits. We currently support
// returning our ExtendedInputCapabilities.
// -----------------------------------------------------------------------------
TTypeUid::Ptr CWebFepTextEditor::MopSupplyObject(TTypeUid aId)
{
    if ( aId.iUid == CAknExtendedInputCapabilities::ETypeId )
    {
        return aId.MakePtr( m_ExtendedInputCapabilities );
    }

    return aId.Null();
}
 

////////////////////////////////////////////////////////////////////////////////
// New public methods
//

// -----------------------------------------------------------------------------
// UpdateFlagsState
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateFlagsState(TUint flags)
{    
    CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));        
    
    if ( IsTextAreaFocused() ) {
    	// If in a TextArea, allow "enter" key presses to be newline/paragraph
    	state->SetFlags( flags | EAknEditorFlagUseSCTNumericCharmap 
    					 | EAknEditorFlagAllowEntersWithScrollDown );
    	}
    else {
        state->SetFlags(flags | EAknEditorFlagUseSCTNumericCharmap);
    	}
    
    state->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateFlagsUpdate);
}

// -----------------------------------------------------------------------------
// UpdateInputModeState
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateInputModeState(TUint inputMode, TUint permittedInputModes, TUint numericKeyMap)
{  

    CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));        
    
    if (permittedInputModes != EAknEditorNumericInputMode) {
        EVariantFlag variant = AknLayoutUtils::Variant();
        if (variant == EApacVariant) {
              permittedInputModes |= EAknEditorTextInputMode |
              EAknEditorHalfWidthTextInputMode | EAknEditorFullWidthTextInputMode |
              EAknEditorKatakanaInputMode | EAknEditorFullWidthKatakanaInputMode |
              EAknEditorHiraganaKanjiInputMode | EAknEditorHiraganaInputMode;
            
        }
    }
    
    state->SetDefaultInputMode(inputMode);             
    state->SetCurrentInputMode(inputMode);    
    state->SetPermittedInputModes(permittedInputModes);                 
    state->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(numericKeyMap));

    state->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate);        

}

// -----------------------------------------------------------------------------
// UpdateCaseState
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateCaseState(TUint currentCase, TUint permittedCase)
{    
    CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));        

    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame){

        if (frame->editor()->canEditRichly()) {
            state->SetDefaultCase(EAknEditorTextCase);                    
        }
        else {
            state->SetDefaultCase(currentCase);
            state->SetCurrentCase(currentCase);
            state->SetPermittedCases(permittedCase);        
        }    
    }
    
    state->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate);        
}

// -----------------------------------------------------------------------------
// HandleUpdateCursor
//
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::HandleUpdateCursor()
{
    // ReportAknEdStateEventL, for events see aknedstsobs.h
    // MAknEdStateObserver::EAknCursorPositionChanged 
    
    CAknEdwinState* state = static_cast<CAknEdwinState*>(State(KNullUid));                
    if ( state ) {                    
        TRAP_IGNORE( state->ReportAknEdStateEventL( MAknEdStateObserver::EAknCursorPositionChanged ) );
    }
}

// -----------------------------------------------------------------------------
// GetStateFromFormatMask
// 
// 
// -----------------------------------------------------------------------------
bool CWebFepTextEditor::GetStateFromFormatMask(TUint& currentCase,
                                                TUint& permittedCase,
                                                TUint& inputMode,
                                                TUint& permittedInputModes,
                                                TUint& flags,
                                                TUint& numericKeyMap)
{
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();    
    if (frame && m_textFormatMask) {
    
        TInt cursorpos = DocumentLengthForFep();        
        TInputFormatMaskType fm = m_textFormatMask->getInputFormatMaskType(frame, cursorpos);        

        switch( fm ) {
            case ELeUpSymPuc:       //A any upper case letter or symbolic
                flags = EAknEditorFlagNoT9 | EAknEditorFlagFixedCase;
                currentCase = EAknEditorUpperCase; 
                permittedCase = EAknEditorUpperCase;                                    
                inputMode = EAknEditorTextInputMode;
                permittedInputModes = EAknEditorTextInputMode;
            break;
            case ELeLoSymPuc:       //a any lower case letter or symbolic
                flags = EAknEditorFlagNoT9 | EAknEditorFlagFixedCase;
                currentCase = EAknEditorLowerCase;
                permittedCase= EAknEditorLowerCase;                        
                inputMode = EAknEditorTextInputMode;
                permittedInputModes= EAknEditorTextInputMode;
            break;
            case ELeUpNumSymPuc:    //X any upper case, number or symbolic
                flags = EAknEditorFlagNoT9 | EAknEditorFlagFixedCase;
                currentCase = EAknEditorUpperCase;
                permittedCase= EAknEditorUpperCase;                        
                inputMode = EAknEditorTextInputMode;
                permittedInputModes= EAknEditorTextInputMode;
            break;
            case ELeLoNumSymPuc:    //x any lower case, number or symbolic
                flags = EAknEditorFlagNoT9 | EAknEditorFlagFixedCase;
                currentCase = EAknEditorLowerCase;
                permittedCase= EAknEditorLowerCase;
                inputMode = EAknEditorTextInputMode;
                permittedInputModes= EAknEditorTextInputMode | EAknEditorNumericInputMode;
            break;
            case EAnyLow:           //m any lower character can be changed to upper
                currentCase = EAknEditorLowerCase;
                permittedCase= EAknEditorAllCaseModes;
                inputMode = EAknEditorTextInputMode;
                permittedInputModes= EAknEditorAllInputModes;
            break;          
            case EAnyUpper:         //M any upper character can be changed to lower
                currentCase = EAknEditorUpperCase; 
                permittedCase= EAknEditorAllCaseModes;
                inputMode = EAknEditorTextInputMode;
                permittedInputModes= EAknEditorAllInputModes;
            break;
            case ENumSymPuc:        //n any number or symbolic
                flags = EAknEditorFlagNoT9;
                currentCase = EAknEditorUpperCase;
                permittedCase = EAknEditorAllCaseModes;
                inputMode = EAknEditorNumericInputMode;    
                permittedInputModes= EAknEditorAllInputModes;        
            break;
            case ENumChar:          //N any number
                flags = EAknEditorFlagNoT9;
                currentCase = EAknEditorUpperCase;
                permittedCase = EAknEditorAllCaseModes;
                inputMode = EAknEditorNumericInputMode;    
                permittedInputModes= EAknEditorNumericInputMode;   
            break;
            case EStatic:           
                return EFalse;
            break;
            case ENoFormat: 
                return EFalse;
            break;                    
            default:
            return EFalse;        
        }    
        
        return ETrue;                
    }

    return EFalse;                
}

// -----------------------------------------------------------------------------
// validateTextFormat
// 
// 
// -----------------------------------------------------------------------------
bool CWebFepTextEditor::validateTextFormat()
{
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (!frame || !frame->document()->focusedNode())
        return true;

    RenderStyle* s = frame->document()->focusedNode()->renderStyle();      
    if (!m_textFormatMask) {            
        return true;
    }
        
    Node* n = frame->document()->focusedNode();
    if (n->hasTagName(HTMLNames::inputTag)) {
        HTMLInputElement* input = static_cast<HTMLInputElement*>(n);
        WebTextFormatMask::ErrorBlock eb;
        CSSStyleDeclaration* style = input->style();
        ExceptionCode ec = 0;     
        
        String inputColor = style->getPropertyValue(CSS_PROP_COLOR); 
        if ( inputColor.lower() != "red" )
        {
            m_inputTextColor = inputColor; 
        }
        
        if (!m_textFormatMask->checkText(input->value(), eb)) {
            style->setProperty(CSS_PROP_COLOR, "red", false, ec);
            return false;
        }
        else 
        {
            style->setProperty(CSS_PROP_COLOR, m_inputTextColor, false, ec);
            CancelEditingMode();
            return true; 
        }
    }
    else if ( n->hasTagName(HTMLNames::textareaTag)) {
        CancelEditingMode();
    }
    
    return true;
}

// -----------------------------------------------------------------------------
// IsDirectionRTL
// Walk through the DOM and find if the focus node or a parent (table, html,
// body, etc) has dir attribute set to RTL.
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::IsDirectionRTL()
{
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if ( frame &&
         frame->document() &&
         frame->document()->focusedNode() ) {

        Node* node = frame->document()->focusedNode();
        RenderStyle* renderStyle = node->renderStyle();
        if ( renderStyle ) {
            TextDirection txtDir = renderStyle->direction();
            if ( txtDir == RTL ) {
                return ETrue;
            }
        }
    }

    return EFalse;
}

#if defined(BRDO_BROWSER_50_FF)
// -----------------------------------------------------------------------------
// SetAlignment
// The EInputEditorAlignXXX flags are only supported in 5.0+ platforms
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::SetAlignment(CAknExtendedInputCapabilities::TInputCapabilities aAlignment)
{
    if ( !m_ExtendedInputCapabilities ) {
        return;
    }
    
    // Clear the old alignment
    TUint capabilities = m_ExtendedInputCapabilities->Capabilities();
    capabilities &= ~( CAknExtendedInputCapabilities::KAknEditorAlignMask );

    // Set the new alignment
    capabilities |= aAlignment;
    m_ExtendedInputCapabilities->SetCapabilities( capabilities );
}
#endif

// -----------------------------------------------------------------------------
// UpdateInlineText
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::UpdateInlineText(const TDesC& aText)
{                
    delete m_inlineEditText;    
    m_inlineEditText = NULL;    
    
    if (DocumentLengthForFep() >= DocumentMaximumLengthForFep()) 
        return;

    m_inlineEditText = aText.Alloc();      
    
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    
    if (!frame)
        return;
    
    
    RenderStyle* r = NULL;
    if ( Node *n  = frame->selectionController()->selection().start().node() ) {
        r = n->renderStyle();
    }
      
    bool textSecurity = r && r->textSecurity() != TSNONE;

    RefPtr<CSSMutableStyleDeclaration> oldStyle;
    if (textSecurity) {    
        oldStyle = frame->typingStyle();
        RefPtr<CSSMutableStyleDeclaration> style = new CSSMutableStyleDeclaration;
        style->setProperty(CSS_PROP__WEBKIT_TEXT_SECURITY, CSS_VAL_NONE);
        frame->computeAndSetTypingStyle(style.get(), EditActionTyping);
    }
        
    frame->editor()->insertTextWithoutSendingTextEvent(String(*m_inlineEditText), false);
        
    if (textSecurity) {
        if (oldStyle)
            frame->setTypingStyle(oldStyle.get());
        else
            frame->clearTypingStyle();
    }
}

// -----------------------------------------------------------------------------
// ClearInlineText
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::ClearInlineText()
{
    TInt oldlen = m_inlineEditText ? m_inlineEditText->Length() : 0;

    TKeyEvent keyEvent = { EKeyBackspace, EKeyBackspace, 0, 0 };    
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    if (frame) {    
        while ( oldlen-- ) {
            frame->editor()->deleteWithDirection(SelectionController::BACKWARD,
                                                 CharacterGranularity, false, true);
        }
    }
}

// -----------------------------------------------------------------------------
// IsTextAreaFocused
// 
// 
// -----------------------------------------------------------------------------
bool CWebFepTextEditor::IsTextAreaFocused() const
{
    Frame* frame = m_webView->page()->focusController()->focusedOrMainFrame();
    return ( frame && frame->document()->focusedNode() &&
    		 frame->document()->focusedNode()->hasTagName(HTMLNames::textareaTag));
}

// -----------------------------------------------------------------------------
// CcpuIsFocused
// 
// 
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::CcpuIsFocused() const
{
    return ETrue;
}
    
// -----------------------------------------------------------------------------
// CcpuCanCut
// 
// 
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::CcpuCanCut() const
{
    TCursorSelection selection;
    GetCursorSelectionForFep(selection);    
    return selection.Length();
}

// -----------------------------------------------------------------------------
// CcpuCutL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CcpuCutL()
{
    PlaceDataOnClipboardL();
    TCursorSelection selection;
    GetCursorSelectionForFep(selection);    
}
    
// -----------------------------------------------------------------------------
// CcpuCanCopy
// 
// 
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::CcpuCanCopy() const
{
    TCursorSelection selection;
    GetCursorSelectionForFep(selection);    
    return selection.Length();
}
    
// -----------------------------------------------------------------------------
// CcpuCopyL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CcpuCopyL()
{
    PlaceDataOnClipboardL();
}
    
// -----------------------------------------------------------------------------
// CcpuCanPaste
// 
// 
// -----------------------------------------------------------------------------
TBool CWebFepTextEditor::CcpuCanPaste() const
{
    TRAPD(err, DoCcpuCanPasteL());
    return err == KErrNone;
}
    
// -----------------------------------------------------------------------------
// CcpuPasteL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CcpuPasteL() 
{
    RetrieveDataFromClipboardL();   
}
        
// -----------------------------------------------------------------------------
// DoCcpuCanPasteL
// 
// 
// -----------------------------------------------------------------------------
void  CWebFepTextEditor::DoCcpuCanPasteL() const
{
    CClipboard* cb=CClipboard::NewForReadingL(CCoeEnv::Static()->FsSession());
    CleanupStack::PushL(cb);
    TStreamId streamId=cb->StreamDictionary().At(KClipboardUidTypePlainText);
    if (streamId==KNullStreamId)
        User::Leave(KErrNotFound);
    CleanupStack::PopAndDestroy(); // allowedChars, cb
}    
    
// -----------------------------------------------------------------------------
// PlaceDataOnClipboardL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::PlaceDataOnClipboardL()
{
    CancelFepInlineEdit();
    CClipboard* cb=CClipboard::NewForWritingLC(CCoeEnv::Static()->FsSession());
    CopyToStoreL(cb->Store(),cb->StreamDictionary());
    cb->CommitL();
    CleanupStack::PopAndDestroy();
}

// -----------------------------------------------------------------------------
// CopyToStoreL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::CopyToStoreL(CStreamStore& aStore,CStreamDictionary& aDict)
{
	if ( DocumentLengthForFep()== 0)
		return ;
    TCursorSelection selection;
    GetCursorSelectionForFep(selection);
	
	HBufC* buf = HBufC::NewLC(512);
	TPtr ptr(buf->Des());
			
    GetEditorContentForFep(ptr,0,DocumentLengthForFep());
    CPlainText* text = CPlainText::NewL(CPlainText::EFlatStorage);	
	
	text->InsertL(0,*buf);	
	text->CopyToStoreL(aStore, aDict, selection.LowerPos(), selection.Length());
	
	delete text;
    CleanupStack::PopAndDestroy();	
}

// -----------------------------------------------------------------------------
// RetrieveDataFromClipboardL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::RetrieveDataFromClipboardL()
{
    m_webView->fepTextEditor()->CancelFepInlineEdit();
    CClipboard* cb=NULL;
    TRAPD(err,cb=CClipboard::NewForReadingL(CCoeEnv::Static()->FsSession()));
    CleanupStack::PushL(cb);
    User::LeaveIfError(err);
    TStreamId streamId=cb->StreamDictionary().At(KClipboardUidTypePlainText);
    PasteFromStoreL(cb->Store(), cb->StreamDictionary());
    CleanupStack::PopAndDestroy();  // cb    
}
        
// -----------------------------------------------------------------------------
// PasteFromStoreL
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::PasteFromStoreL(CStreamStore& aStore,CStreamDictionary& aDict)
{
    //Read the content into Text
    CancelFepInlineEdit();
    TStreamId streamId=aDict.At(KClipboardUidTypePlainText);
    TCursorSelection selection;
    GetCursorSelectionForFep(selection);
    const TInt cursorPos=selection.LowerPos();
    
	HBufC* buf1 = HBufC::NewLC(512);
	TPtr ptr1(buf1->Des());
	
	CPlainText* text = CPlainText::NewL(CPlainText::EFlatStorage);	
	
    GetEditorContentForFep(ptr1,0,DocumentLengthForFep());    
    
    text->InsertL(0,*buf1);
        
    TInt charPasted = text->PasteFromStoreL(aStore,aDict,cursorPos);
    
    HBufC* buf = HBufC::NewLC(512);
    TPtr ptr(buf->Des());
    text->Extract(ptr,cursorPos,charPasted);      
    
    //remove Paragraph Delimiter
    TInt position = ptr.Mid(0).LocateReverse(TChar(CEditableText::EParagraphDelimiter));
    while (position != KErrNotFound ){
        ptr.Delete( position, 1 );
        position = ptr.Left(position).LocateReverse(TChar(CEditableText::EParagraphDelimiter));
        }           
    
    Frame* frame = m_webView->page()->mainFrame();
	frame = m_webView->page()->focusController()->focusedOrMainFrame();
    frame->editor()->insertTextWithoutSendingTextEvent(String(ptr), false);
    
    delete text;
    CleanupStack::PopAndDestroy(2);
}

// -----------------------------------------------------------------------------
// EnableCcpu
// 
// 
// -----------------------------------------------------------------------------
void CWebFepTextEditor::EnableCcpu(TBool aSupport)
{
    CAknEdwinState* edwinState = static_cast<CAknEdwinState*>(this->State(KNullUid));
    if(aSupport)
        {
        edwinState->SetCcpuState(this);    
        }
    else
        {
        edwinState->SetCcpuState(NULL);
        }       
}

// -----------------------------------------------------------------------------
// findPrevSiblingTextLen
// 
// Walk the previous text nodes and add up the len of each text node, so we can
// calculate the total length from first text node to current text node cursor
// position.
// NOTES:
// 1. Each "inserted" newline creates a new node.
// 2. Text area's with newline characters prepopulated (not "entered" by users,
//    but in the original html) do not create separate nodes.
// -----------------------------------------------------------------------------
void CWebFepTextEditor::findPrevSiblingTextLen(Node* aNode, TInt& aLen) const
{
	String str;
	while ( aNode ) {
		aNode = aNode->previousSibling();
		if ( aNode && aNode->isTextNode() ) {
			WebCore::Text* text = (WebCore::Text*)aNode;
			str = text->data();
			aLen +=  str.length();
		}
	}
}

// -----------------------------------------------------------------------------
// findTextNodeCurPos
//
// Returns the text node that contains the current text (cursor) position and
// returns the summed length (aPos) of all the text nodes before the current
// text node.
// NOTE: The length (aPos) doesn't include the current text node's length.
// -----------------------------------------------------------------------------
Node* CWebFepTextEditor::findTextNodeForCurPos(Node* aNode, TInt& aPos) const
{
	// Get the first text node
	Node* firstTextNode = NULL;
	Node* retNode = aNode;
	while ( aNode ) {
		firstTextNode = aNode;
		aNode = aNode->previousSibling();
	}

	TInt len( 0 );
	String str;
	aNode = firstTextNode;
	for ( ; aNode; aNode=aNode->nextSibling() ) {
		if ( aNode && aNode->isTextNode() ) {
			WebCore::Text* aText = (WebCore::Text*)aNode;
			str = aText->data();
			len +=  str.length();
			if ( len >= aPos ) {
				// We found the text node at aPos, calculate the length of all
				// previous text nodes
				retNode = aNode;
				aPos = len - str.length();
				break;
			}
		}
	}

	return retNode;
}