diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKit/s60/webview/WebFepTextEditor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKit/s60/webview/WebFepTextEditor.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,1266 @@ +/* +* 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 +#include +#include +#include +#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(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(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(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 box + TUint caps = TCoeInputCapabilities::ENavigation; + + if ( sc->isInPasswordField() ) { + caps |= TCoeInputCapabilities::ESecretText; + } + else { + + CAknEdwinState* state = static_cast(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(frame->document()->focusedNode()); + length = ie->value().length(); + } + else if (frame->document()->focusedNode()->hasTagName(HTMLNames::textareaTag)) { + HTMLTextAreaElement* ie = static_cast(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(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(frame->document()->focusedNode()); + aEditorContent = ie->value().substring(aDocumentPosition, aLengthToRetrieve); + } + else if (frame->document()->focusedNode()->hasTagName(HTMLNames::textareaTag)) { + HTMLTextAreaElement* ie = static_cast(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(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(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(numericKeyMap)); + + state->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate); + +} + +// ----------------------------------------------------------------------------- +// UpdateCaseState +// +// +// ----------------------------------------------------------------------------- +void CWebFepTextEditor::UpdateCaseState(TUint currentCase, TUint permittedCase) +{ + CAknEdwinState* state = static_cast(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(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(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 oldStyle; + if (textSecurity) { + oldStyle = frame->typingStyle(); + RefPtr 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(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; +}