javauis/lcdui_akn/lcdui/src/CMIDEdwin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 21:06:50 +0300
branchRCL_3
changeset 71 d5e927d5853b
parent 66 2455ef1f5bbc
child 83 26b2b12093af
permissions -rw-r--r--
Revision: v2.2.11 Kit: 201035

/*
* Copyright (c) 2003-2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:  Base class for TextField and TextBox
*
*/


#include <eikenv.h>
#include <eikappui.h>
#include <coecntrl.h>
// macros for resources
#include <eikcoctl.rsg>

#include <AknUtils.h>
// usied for playing error sounds when text input
#include <aknsoundsystem.h>
#include <aknenv.h>
// CAknSettingCache used for obtaining input language
#include <AknSettingCache.h>
#include <AknIndicatorContainer.h>
#include <aknEditStateIndicator.h>

#include <applayout.cdl.h>              // LAF
#include <aknlayoutscalable_apps.cdl.h> // LAF
#include <aknlayoutscalable_avkon.cdl.h> // LAF
#include <AknLayoutFont.h>
// CAknExtendedInputCapabilities for extended input capabilities
#include <aknextendedinputcapabilities.h>

#include <lcdui.rsg>
// Avkon dialog for info notes
#include <aknnotewrappers.h>

// for fetching contacts from phonebook
// CPbk2StoreConfiguration for contact manager
#include <CPbk2StoreConfiguration.h>
// used in CMIDAiwPbk2Client::VPbkSingleContactOperationComplete to retrieving single contact
#include <MVPbkStoreContact.h>
// MVPbkContactLinkArray* iFetchedLinks
#include <CVPbkContactLinkArray.h>
// used in CMIDAiwPbk2Client::VPbkSingleContactOperationComplete
#include <MVPbkContactFieldTextData.h>
// used for open all contact stores
#include <MVPbkContactStoreList.h>
// API for iContactManager
#include <CVPbkContactManager.h>

// aiw used to invoke phonebook
#include <AiwContactSelectionDataTypes.h>

// phone client API classes for starting phone call
#include <AiwCommon.h>
#include <aiwdialdata.h>
// using AIWDialDataExt::KMaximumPhoneNumberLength
#include <aiwdialdataext.h>

// loading string from resource
#include <StringLoader.h>

// FEP CR
// constants for FEP
#include <AknFepInternalCRKeys.h>
#include <centralrepository.h>

#include <j2me/jdebug.h>

#include "CMIDEdwin.h"
#include "CMIDTextFieldItem.h"
#include "CMIDComponentFactory.h"
#include "CMIDUtils.h"
#include "CMIDUIManager.h"

#undef  TRAP_INSTRUMENTATION_LEAVE
#define TRAP_INSTRUMENTATION_LEAVE(aResult) DEBUG_INT2("In CMIDEdwin.cpp, trapped method was called at line %D and got exception %D", __LINE__, aResult);

// class CMIDEdwin

void CMIDEdwin::ConstructL(const TDesC& aText,TInt aMaxSize)
{

    // Set decimal separator according to the current locale.
    // Note: decimal separators other than ',' and '.' are currently not supported
    TLocale loc;
    iDecimalSeparator = loc.DecimalSeparator();
    if (iDecimalSeparator != ',')
    {
        iDecimalSeparator = '.';
    }

    iEdwinUtils = CMIDEdwinUtils::NewL(this, iDecimalSeparator);

    // if text is invalid according to constraints, throw IllegalArgumentException,
    // except for a PHONENUMBER which only has the invalid characters removed
    if ((iConstraints & MMIDTextField::EConstraintMask) != MMIDTextField::EPhoneNumber
            && !iEdwinUtils->ConstraintsValidForText(aText,iConstraints,ETrue))
    {
        User::Leave(KErrArgument);
    }

    iMaxSize = aMaxSize;
    if (iDisplayable)
    {
        iUIManager = iDisplayable->GetUIManager();
        SetContainerWindowL(*iDisplayable);
        SetAknEditorFlags(EAknEditorFlagEnableScrollBars | AknEdwinFlags());
    }
    else
    {
        iUIManager = iTextFieldItem->GetUIManager();
        // TextField does not have any displayable yet available (before Form.Append())
        // and EikEdwin needs to have a proper container window set, otherwise it may crash in singleLineEditor mode
        CCoeControl::SetContainerWindowL(*(iUIManager->OpenMenuHandlerL()->GetDisplayable()));
    }

    TBool singleLineEditor = (iConstraints & MMIDTextField::EPassword);

    AknEditUtils::ConstructEditingL(this,                           // aEdwin
                                    aMaxSize,                      // aEditingSpace
                                    (singleLineEditor ? 1 : 0),    // aEditingWindow
                                    EAknEditorCharactersLowerCase, // aCharacterCase
                                    EAknEditorAlignLeft,           // aJustification
                                    ETrue,                         // aAllowedToMoveInsertionPoint
                                    ETrue,                         // aCursorYesNo
                                    EFalse);                       // aOverflowYesNo

    if (iConstraints & MMIDTextField::EPassword)
    {
        iEdwinUserFlags |= CEikEdwin::EUserSuppliedText;
        CreatePasswordTextL();
    }

    HBufC* buf = aText.AllocLC();
    CMIDUtils::MapJavaToETextChars(buf);
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
        iEdwinUtils->RemoveNonPhoneNumberChars(buf);
    }
    CEikEdwin::SetTextL(buf);
    CreateTextViewL();
    ProcessModifiers();
    CleanupStack::PopAndDestroy(buf);
    SetFEPModeAndCharFormat();
    AddEdwinObserverL(this);    // see HandleEdwinEventL
    CreateNonMidletCommandsL();


    iUIManager->OpenNaviPaneControllerL()->AddTickerObserverL(this);

    // set the cursor position
    CEikEdwin::SetCursorPosL(TextLength(), EFalse);

    // Publish MIDP constraints via input capabilities of the CEikEdwin
    // The information is needed by chinese VKB/HWR system that adjusts its behavior
    // based on MIDP constraints (most notably by checking if the field is a PASSWORD field).
    TCoeInputCapabilities inputCapabilities = InputCapabilities();
    if (inputCapabilities != TCoeInputCapabilities::ENone)
    {
        MObjectProvider* mop = inputCapabilities.ObjectProvider();
        if (mop)
        {
            CAknExtendedInputCapabilities* extendedInputCapabilities = NULL;
            extendedInputCapabilities = mop->MopGetObject(extendedInputCapabilities);
            if (extendedInputCapabilities)
            {
                extendedInputCapabilities->SetMIDPConstraints(iConstraints);
            }
        }
    }

    iThisMultitapKey = 0;   // reset key counter
    iLastMultitapKey = 0;
}

CMIDEdwin::CMIDEdwin(
    TUint aConstraints, MMIDDisplayable* aDisplayable, CMIDTextFieldItem* aTextFieldItem)
        : iDisplayable(static_cast<CMIDDisplayable*>(aDisplayable)),
        iTextFieldItem(aTextFieldItem),
        iConstraints(aConstraints),
        iStateChanged(EFalse),
        iKeyEventsPending(EFalse),
        iInitialCurrentCase(0),
        iInitialCurrentInputMode(0),
        iInitialCurrentLanguage(ELangTest)
{
}

CMIDEdwin::~CMIDEdwin()
{
    //phonebook fetch
    delete iAiwPbkClient;
    //edwin utils
    delete iEdwinUtils;
    if (iUIManager && iUIManager->GetNaviPaneController())
    {
        iUIManager->GetNaviPaneController()->RemoveTickerObserver(this);
    }
    RemoveNonMidletCommands();
}

void CMIDEdwin::DeleteTextL(TInt aOffset,TInt aLength)
{
    // get all initial values before deletion
    TInt oldSize = Size();
    HBufC* oldText = GetTextInHBufL();
    CleanupStack::PushL(oldText);
    // get cursor position before deletion
    TInt cursorPos = CEikEdwin::CursorPos();

    if (IsReadyToDraw())
        ClearSelectionL();

    TInt withoutFEPSize = Size();
    // if size is different then FEP transaction was canceled and some letters
    // are missing - must work with original text
    if (withoutFEPSize != oldSize)
    {
        CEikEdwin::SetTextL(oldText);
    }

    //
    // Do the deletion, then roll back if it leaves invalid text
    //
    iText->DeleteL(aOffset,aLength);
    //
    TBool valid = iEdwinUtils->ConstraintsValidForText(Read(), iConstraints, ETrue);
    if (!valid)
    {
        CEikEdwin::SetTextL(oldText);
    }
    CleanupStack::PopAndDestroy(oldText);

    HandleTextChangedL();
    if (IsReadyToDraw())
        SetSelectionL(aOffset,aOffset);

    if (!valid)
    {
        User::Leave(KErrArgument);
    }

    // Handle cursor moving
    // Cursor is in the middle of delete area
    if ((cursorPos > aOffset) && (cursorPos < (aOffset + aLength)))
    {
        CEikEdwin::SetCursorPosL(aOffset, EFalse);
    }
    // cursor is on the right side of delete area
    else if (cursorPos > (aOffset + aLength))
    {
        TInt newPosition = cursorPos - aLength;
        if (newPosition < 0)
        {
            newPosition = 0;
        }
        CEikEdwin::SetCursorPosL(newPosition, EFalse);
    }
    // cursor is on the left side of delete area
    else
    {
        CEikEdwin::SetCursorPosL(cursorPos, EFalse);
    }
}

void CMIDEdwin::SetTextL(const TDesC& aText)
{
    // if text is invalid according to constraints, throw IllegalArgumentException,
    //  except for a PHONENUMBER which only has the invalid characters removed
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
    }
    else if (!iEdwinUtils->ConstraintsValidForText(aText, iConstraints, ETrue))
    {
        User::Leave(KErrArgument);
    }

    HBufC* buf = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints);

    if (IsNumberConversionNeeded())
    {
        TPtr ptr = buf->Des();
        AknTextUtils::LanguageSpecificNumberConversion(ptr);
    }

    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
        iEdwinUtils->RemoveNonPhoneNumberChars(buf);
    }
    CEikEdwin::SetTextL(buf);
    HandleTextChangedL();
    CleanupStack::PopAndDestroy(buf);

    // move cursor to end of the new text
    CEikEdwin::SetCursorPosL(TextLength(), EFalse);
}

/** The first part of this method validates existing text + new text.
Then it carries on with text insertion. */
void CMIDEdwin::InsertTextL(const TDesC& aText, TInt aPosition)
{
    //VALIDATE EXISTING TEXT
    HBufC* temp = NULL;
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)
    {
        // Convert decimal content to unlocalized form before testing validity
        // of insertion.
        temp = GetTextInHBufL();
        if (temp)
        {
            CleanupStack::PushL(temp);
            iEdwinUtils->ConvertFromLocalizedDecimal(temp);
        }
    }

    if (aPosition < 0)
        aPosition = 0;

    TInt size = TextLength();
    if (aPosition > size)
        aPosition = size;

    // if text is invalid according to constraints, throw IllegalArgumentException,
    //  except for a PHONENUMBER which only has the invalid characters removed
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
    }
    else if (!iEdwinUtils->ConstraintsValidForInsertedTextL((temp ? temp->Des() : Read()), aText, aPosition, iConstraints, ETrue))
    {
        User::Leave(KErrArgument);
    }
    if (temp)
    {
        CleanupStack::PopAndDestroy(temp);
        temp = NULL;
    }
    //
    //TEXT INSERTION STARTS HERE
    if (IsReadyToDraw())
    {
        ClearSelectionL();
    }

    temp = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints);


    if (IsNumberConversionNeeded())
    {
        TPtr ptr = temp->Des();
        AknTextUtils::LanguageSpecificNumberConversion(ptr);
    }

    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
        iEdwinUtils->RemoveNonPhoneNumberChars(temp);
    }
    iText->InsertL(aPosition, temp->Des());

    HandleTextChangedL();

    // Get the cursor position and move it forward along with inserter characters, if
    // characters were inserted on the left side of the cursor.
    TInt cursorPos = CEikEdwin::CursorPos();
    TInt numberOfAddedCharacters = TextLength() - size;

    if (cursorPos >= aPosition)
    {
        if ((cursorPos + numberOfAddedCharacters) < iMaxSize)
        {
            CEikEdwin::SetCursorPosL(cursorPos + numberOfAddedCharacters, EFalse);
        }
    }

    UpdateTextCapacityIndicatorValueL();

    CleanupStack::PopAndDestroy(temp);
}

/** Not used in current implementation; functionality
    provided in CMIDEdwinControl and CMIDTextFieldItem
   */
void CMIDEdwin::SetConstraintsL(TUint /*aConstraints*/)
{
}

void CMIDEdwin::SetTextWithNewConstraintsL(HBufC* aText)
{
    // If the current contents of the TextBox do not match the new constraints,the
    // contents are set to empty, except for a PHONENUMBER which only has the
    // invalid characters removed. Otherwise, set the text as given.
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
    {
        iEdwinUtils->RemoveNonPhoneNumberChars(aText);
        CEikEdwin::SetTextL(aText);
    }
    else if (!iEdwinUtils->ConstraintsValidForText(aText->Des(), iConstraints & MMIDTextField::EConstraintMask, ETrue))
    {
        CEikEdwin::SetTextL(&KNullDesC);
    }
    else
    {
        CEikEdwin::SetTextL(aText);
    }
    HandleTextChangedL();
}


TInt CMIDEdwin::SetMaxSizeL(TInt aMaxSize)
{
    TInt size = TextLength();
    if (aMaxSize < size)
    {
        DeleteTextL(aMaxSize,size-aMaxSize);
    }
    iMaxSize = aMaxSize;
    SetTextLimit(iMaxSize);
    return iMaxSize;
}

TInt CMIDEdwin::GetMaxSize()
{
    return iMaxSize;
}


TInt CMIDEdwin::Size()
{
    TRAP_IGNORE(ResetNumericContentL());
    return TextLength();
}

TInt CMIDEdwin::GetCaretPosition()
{
    TRAP_IGNORE(ResetNumericContentL());
    return CursorPos();
}

/** For a NUMERIC TextBox, clear the contents if the "displayed contents" are
    in a state that is not valid "actual contents" for the current constraints.
*/
void CMIDEdwin::ResetNumericContentL()
{
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENumeric)
    {
        HBufC* buf = GetTextInHBufL();
        if (buf != NULL)
        {
            CleanupStack::PushL(buf);
            if (!iEdwinUtils->ConstraintsValidForText(buf->Des(), iConstraints, ETrue))
            {
                (buf->Des()).SetLength(0);
                CEikEdwin::SetTextL(buf);
            }
            CleanupStack::PopAndDestroy(buf);
        }
    }
}

HBufC* CMIDEdwin::GetTextL()
{
    HBufC* buf = GetTextInHBufL();
    if (!buf)
    {
        buf = HBufC::NewL(0);
    }
    // convert decimal from localized to MIDlet-visible representation
    if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)
    {
        iEdwinUtils->ConvertFromLocalizedDecimal(buf);
    }

    if (IsNumberConversionNeeded())
    {
        TPtr ptr = buf->Des();
        AknTextUtils::ConvertDigitsTo(ptr, EDigitTypeWestern);
    }

    if (!iEdwinUtils->ConstraintsValidForText(buf->Des(), iConstraints, ETrue))
    {
        // The "displayed contents" of the TextBox may be in a state that is
        // not valid "actual contents" for the current constraints; in that
        // case, return an empty string and clear the TextBox contents.
        (buf->Des()).SetLength(0);
        CEikEdwin::SetTextL(buf);
    }
    else
    {
        // Otherwise, return a copy of the contents where newlines etc. are
        // mapped to their Java representations.
        CMIDUtils::MapETextToJavaChars(buf);
    }
    return buf;
}


void CMIDEdwin::CreatePasswordTextL()
{
    CGlobalText* oldGText = STATIC_CAST(CGlobalText*,iText);
    CPasswordBoxGlobalText* text=new(ELeave) CPasswordBoxGlobalText
    (oldGText->GlobalParaFormatLayer(),oldGText->GlobalCharFormatLayer(),*this);
    CleanupStack::PushL(text);
    text->ConstructL();
    CleanupStack::Pop(text);

    delete iText;
    iText = NULL;

    SetDocumentContentL(*text,CEikEdwin::EUseText);
}

/**
 * Need to recreate TextView here such that it uses the right window
 */
void CMIDEdwin::SetContainerWindowL(const CCoeControl& aContainer)
{
    SetObserver(this); //Prevent MCoeControlObserver::EEventStateChanged going to Form

    CEikEdwin::SetContainerWindowL(aContainer);
}

TKeyResponse CMIDEdwin::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
    // store the key pressed last time, used for warning beeps while reaching size limit
    if (aType == EEventKeyDown)
    {
        iLastMultitapKey = iThisMultitapKey;
        iThisMultitapKey = aKeyEvent.iScanCode;
    }

    if (aType == EEventKeyDown)
    {
        iKeyEventsPending = ETrue;
    }
    else if (aType == EEventKeyUp)
    {
        iKeyEventsPending = EFalse;
    }
    //
    // Post ItemStateChangedEvent before a command is delivered to the Form's CommandListener
    //
    TUint scanCode = aKeyEvent.iScanCode;
    TBool losingFocus = EFalse;

    CMIDMenuHandler* menuHandler = iUIManager->GetMenuHandler();
    // Enter Key
    //
    //TextFieldItem
    if (iTextFieldItem)
    {
        // QWERTY and VKB Enter Key
        if (scanCode == EStdKeyEnter && aType == EEventKeyDown && !useEnterKey)
        {
            useEnterKey=true;
        }
        if ((scanCode ==    EStdKeyEnter && aType == EEventKeyUp && useEnterKey) ||
                (aType == EEventKey && aKeyEvent.iCode == EKeyEnter))
            //TextFieldItem with NUMERIC,DECIMAL and PHONENUMBER constraint
            if (IsConstraintSet(MMIDTextField::ENumeric) ||
                    IsConstraintSet(MMIDTextField::EDecimal) ||
                    IsConstraintSet(MMIDTextField::ENumeric + MMIDTextField::EPassword))
            {
                useEnterKey=false;
                //Activate default command
                if (iTextFieldItem->DefaultCommand())
                {
                    menuHandler->ProcessCommandL(
                        iTextFieldItem->CommandList()->CommandOffset() +
                        iTextFieldItem->CommandList()->FindCommandIndex(iTextFieldItem->DefaultCommand()));
                }
                // Show ctx menu or activate command
                else
                {
                    menuHandler->ShowMenuL(CMIDMenuHandler::EOkMenu);
                    if (menuHandler->MenuItemsCount() <= 1)
                        menuHandler->ProcessCommandL(iTextFieldItem->CommandList()->CommandOffset());
                }

                return EKeyWasConsumed;

            }
            else
            {
                //TextFieldItem with PHONENUMBER constraint
                if (IsConstraintSet(MMIDTextField::EPhoneNumber) ||
                        IsConstraintSet(MMIDTextField::EPhoneNumber + MMIDTextField::EPassword))
                {
                    useEnterKey = false;
                    //Activate default command
                    if (iTextFieldItem->DefaultCommand())
                    {
                        menuHandler->ProcessCommandL(
                            iTextFieldItem->CommandList()->CommandOffset() +
                            iTextFieldItem->CommandList()->FindCommandIndex(iTextFieldItem->DefaultCommand()));
                    }
                    // Show options menu or activate command
                    else
                    {
                        menuHandler->ShowMenuL(CMIDMenuHandler::EOkMenu);
                        if (menuHandler->MenuItemsCount() == 1)
                        {
                            menuHandler->ProcessCommandL(iTextFieldItem->CommandList()->CommandOffset());
                        }
                    }
                    return EKeyWasConsumed;
                }
                else
                {
                    //TextFieldItem with ANY,PASSWORD  constraint
                    if (iConstraints == MMIDTextField::EPassword)
                    {
                        useEnterKey=false;
                        //Activate default command
                        if (iTextFieldItem->DefaultCommand())
                        {
                            menuHandler->ProcessCommandL(
                                iTextFieldItem->CommandList()->CommandOffset() +
                                iTextFieldItem->CommandList()->FindCommandIndex(iTextFieldItem->DefaultCommand()));
                        }
                        // Show options menu or activate command
                        else
                        {
                            menuHandler->ShowMenuL(CMIDMenuHandler::EOkMenu);
                            if (menuHandler->MenuItemsCount() == 1)
                            {
                                menuHandler->ProcessCommandL(
                                    iTextFieldItem->CommandList()->CommandOffset());
                            }
                        }
                        return EKeyWasConsumed;

                    }

                }
            }
        if (aKeyEvent.iCode ==  EKeyEnter && aType == EEventKey)
        {
            //TextFieldItem with EMAILADDR constraint
            if (IsConstraintSet(MMIDTextField::EMailAddr) ||
                    IsConstraintSet(MMIDTextField::EUrl))
            {
                //Show menu or activate command
                if (!iTextFieldItem->DefaultCommand())
                {
                    menuHandler->ShowMenuL(CMIDMenuHandler::EOkMenu);
                    if (menuHandler->MenuItemsCount() <= 1)
                    {
                        menuHandler->ProcessCommandL(
                            iTextFieldItem->CommandList()->CommandOffset());
                    }
                    return EKeyWasConsumed;
                }

            }
        }
    }
    // End Enter Key
    //

    //
    // keyboard menu
    //
    switch (scanCode)
    {
    case EStdKeyF1:
    case EStdKeyMenu:
        losingFocus=ETrue;
    }
    //
    // Pause the ticker for five sec if # key received
    if (aKeyEvent.iScanCode == EStdKeyHash && !IsReadOnly()) //0x7f
    {
        iUIManager->OpenNaviPaneControllerL()->PauseTickerL(TICKER_PAUSE_INTERVAL, this);
    }
    //
    // Non keyboard zoom,menu,etc.
    //
    if (scanCode>=ESpecialKeyBase && scanCode<(ESpecialKeyBase+ESpecialKeyCount))
        losingFocus=ETrue;
    //
    // CBA buttons:
    //
    if (scanCode>=EStdKeyDevice0 && scanCode<=EStdKeyDeviceF)
        losingFocus=ETrue;
    //
    if (iTextFieldItem && losingFocus && iStateChanged)
    {
        iTextFieldItem->HandleControlEventL(this,MCoeControlObserver::EEventStateChanged);
        iStateChanged=EFalse;
    }

    // ignore up and down arrows on PASSWORD TextField to avoid funny behaviour
    // with line breaks
    if (iDisplayable && (iConstraints & MMIDTextField::EPassword)
            && (aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyUpArrow))
    {
        return EKeyWasConsumed;
    }

    // when pressing the send key on a phonenumber-type box, call the number
#ifdef RD_SCALABLE_UI_V2
    if ((aType == EEventKey) && (scanCode == EStdKeyYes))
#else
    if ((aType == EEventKeyUp) && (scanCode == EStdKeyYes))
#endif // RD_SCALABLE_UI_V2
    {
        if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
        {
            CreatePhoneCallL();
            return EKeyWasConsumed;
        }
    }

#ifdef RD_SCALABLE_UI_V2
    if ((aType == EEventKey) && (iConstraints & MMIDTextField::EPassword)
#else
    if ((aType == EEventKeyDown) && (iConstraints & MMIDTextField::EPassword)
#endif // RD_SCALABLE_UI_V2
            && iTextFieldItem) // type == TextField
    {
        static_cast<CPasswordBoxGlobalText*>(iText)->RejectNextKey(scanCode == EStdKeyEnter);
    }

#ifdef RD_SCALABLE_UI_V2
    if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKey || aType == EEventKeyUp) && !IsReadOnly() &&
#else
    if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKeyUp) && !IsReadOnly() &&
#endif // RD_SCALABLE_UI_V2
            ((scanCode==EStdKeyNkpAsterisk) || (scanCode == EStdKeyMinus) || (scanCode==EStdKeyNkpMinus) || (scanCode == 0x2A) || (scanCode == 0x2D) ||
             (TChar(aKeyEvent.iCode) == TChar('-') && scanCode != EStdKeyMinus)))
    {
        HandleMinusCharEventL(EEventTextUpdate);
        CEikEdwin::ReportEdwinEventL(EEventTextUpdate);
        UpdateTextCapacityIndicatorValueL();
        return EKeyWasConsumed;
    }

    //handling of qwerty keypad "-" or "." pressing in Decimal mode
#ifdef RD_SCALABLE_UI_V2
    if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKey) && !IsReadOnly() &&
#else
    if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKeyUp) && !IsReadOnly() &&
#endif // RD_SCALABLE_UI_V2
            ((scanCode==EStdKeyMinus) || (scanCode==EStdKeyFullStop)))
    {
        CPlainText* res = CEikEdwin::Text();
        TInt textLength = CEikEdwin::TextLength();
        if (scanCode == EStdKeyMinus && textLength < iMaxSize)
        {
            res->InsertL(CEikEdwin::CursorPos(), KMinusChar);
        }
        else if (scanCode == EStdKeyFullStop && textLength < iMaxSize)
        {
            res->InsertL(CEikEdwin::CursorPos(), KFullStopChar);
        }

        HandleTextChangedL(); // notify editor about the text changes
        CEikEdwin::ReportEdwinEventL(EEventTextUpdate);
        TInt cursorPos = CEikEdwin::CursorPos();

        if (CEikEdwin::TextLength() < iMaxSize)
        {
            CEikEdwin::SetCursorPosL(cursorPos + 1, EFalse);
        }
        else if (cursorPos == (iMaxSize - 1) && cursorPos == textLength &&
                 (scanCode == EStdKeyFullStop || scanCode == EStdKeyMinus))
        {
            CEikEdwin::SetCursorPosL(iMaxSize, EFalse);
        }
    }
    //Error tone playing case1:
    //Play error tone if TextBox/TextField is read-only or maximum length has been reached.
    //Here is handling of keys 0...9 for full keyboard and itu-t, but NOT virtual keyboard.
    if (aType == EEventKeyDown
            && ((scanCode >= KKeyQwerty0 && scanCode <= KKeyQwerty9)
                || scanCode == EStdKeyHash
                || scanCode == EStdKeyNkpAsterisk
                || scanCode == KMidpKeyNkpAsteriskHW))
    {
        if ((scanCode == EStdKeyNkpAsterisk || scanCode == KMidpKeyNkpAsteriskHW)
                && !IsReadOnly() && IsConstraintSet(MMIDTextField::ENumeric))
        {
            //Do nothing here in case of minus char toggle
        }
        else if (IsReadOnly())
        {
            iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
            UpdateTextCapacityIndicatorValueL();
            return EKeyWasConsumed;
        }

        // All possible sources of warning beep are separated to be easy to read
        else if (TextLength() >= iMaxSize)
        {
            TInt ret = KErrNone;
            TInt inputModeValue = AknEditorCurrentInputMode();
            if (inputModeValue != EAknEditorTextInputMode)
            {
                iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
                UpdateTextCapacityIndicatorValueL();
                return EKeyWasConsumed;
            }

            TInt aknRepositoryValue = 0;
            CRepository* aknFepRepository = NULL;
            TRAP(ret, aknFepRepository = CRepository::NewL(KCRUidAknFep));
            if ((ret != KErrNone) || (!aknFepRepository))
            {
                // if we cannot get the repository (something is wrong), play nothing
                UpdateTextCapacityIndicatorValueL();
                return EKeyWasConsumed;
            }
            aknFepRepository->Get(KAknFepPredTxtFlag, aknRepositoryValue);

            delete aknFepRepository;
            aknFepRepository = NULL;

            if (aknRepositoryValue == 1)    // 1 means the predictive input is on
            {
                iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
                UpdateTextCapacityIndicatorValueL();
                return EKeyWasConsumed;
            }
            // now only nonpredictive textinput is left
            if (iThisMultitapKey != iLastMultitapKey) // different key tapped -> no multitap
            {
                iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
                UpdateTextCapacityIndicatorValueL();
                iThisMultitapKey = 0;
                iLastMultitapKey = 0;
                return EKeyWasConsumed;
            }
        }
    }

    if (aType != EEventKey && aKeyEvent.iScanCode != EStdKeyApplication0)
    {
        UpdateTextCapacityIndicatorValueL();
        return EKeyWasConsumed;
    }


    TKeyResponse response = EKeyWasNotConsumed;

    // Error tone playing case2:
    // Play error tone if TextBox/TextField is read-only or maximum length has been reached.
    // Here is handling of full keyboard keys(NOT 0...9) and all virtual keyboard keys
    // (camera and menu key not included).
    // (Note: Virtual keyboard sends only EEventKey type events, not up or down events)
    // (Note: Error tone is played when there is no text to be replaced i.e. no text has been painted)
    if (!iEdwinUtils->IsNavigationKey(aKeyEvent) && !iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv) && aKeyEvent.iCode != EKeyYes &&
            (!iKeyEventsPending || (scanCode < KKeyQwerty0  || scanCode > KKeyQwerty9)) &&
            (aKeyEvent.iCode != EKeyApplication0 && scanCode != EStdKeyApplication0 &&
             aKeyEvent.iCode != EKeyApplication19 && scanCode != EStdKeyApplication19))
    {
        if (IsReadOnly() || (TextLength() >= iMaxSize && aKeyEvent.iCode != EKeyBackspace))
        {
            //SelectionLength() > 0 if text has been selected/painted
            if (SelectionLength() == 0)
            {
                iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
            }
            response = CEikEdwin::OfferKeyEventL(aKeyEvent,aType);
            UpdateTextCapacityIndicatorValueL();
            return response;
        }
    }

    TBool valid = EFalse;
    //
    if (iEdwinUtils->IsNavigationKey(aKeyEvent) || iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv))
    {
        HBufC* oldText = GetTextInHBufL();
        CleanupStack::PushL(oldText);
        TCursorSelection sel = Selection();
        //
        response = CEikEdwin::OfferKeyEventL(aKeyEvent,aType);
        valid = iEdwinUtils->ConstraintsValidForText(iText?Read():TPtrC(),iConstraints,EFalse);
        //
        if (!valid)
        {
            CEikEdwin::SetTextL(oldText);
            HandleTextChangedL();
            SetSelectionL(sel.iCursorPos,sel.iAnchorPos);
            response = EKeyWasConsumed;
        }
        //
        CleanupStack::PopAndDestroy(oldText);
        UpdateTextCapacityIndicatorValueL();
        return response;
    }
    else
    {
        TBuf<1> key;
        key.Append(TChar(aKeyEvent.iCode));
        valid = iEdwinUtils->ConstraintsValidForInsertedTextL(iText?Read():TPtrC(), key, CursorPos(), iConstraints, EFalse);
        if (valid)
        {
            if (iTextFieldItem && (aKeyEvent.iCode == EKeyEnter) &&
                    (((iConstraints & MMIDTextField::EConstraintMask) !=  MMIDTextField::EAny) ||
                     (iConstraints & MMIDTextField::EPassword)))
            {//enter key for NON ANY or ANY | PASSWORD editors
                return EKeyWasNotConsumed; //must do command triggering in this case
            }

            response = CEikEdwin::OfferKeyEventL(aKeyEvent,aType);
            UpdateTextCapacityIndicatorValueL();
        }
        else
        {
            // If minus char was entered in full querty editor mode
            if (IsConstraintSet(MMIDTextField::EDecimal) &&
                    (aType == EEventKey) && !IsReadOnly() &&
                    (TChar(aKeyEvent.iCode) == TChar('-') && scanCode != EStdKeyMinus))
            {
                CPlainText* res = CEikEdwin::Text();

                if (res && TChar(aKeyEvent.iCode) == TChar('-') &&
                        TextLength() < iMaxSize)
                {
                    TInt textLength = TextLength();
                    res->InsertL(GetCaretPosition(), KMinusChar);
                    HandleTextChangedL(); // notify editor about the text changes
                    CEikEdwin::ReportEdwinEventL(EEventTextUpdate);
                    TInt cursorPos = GetCaretPosition();

                    if (TextLength() < iMaxSize)
                    {
                        CEikEdwin::SetCursorPosL(GetCaretPosition() + 1, EFalse);
                    }
                    else if (cursorPos == (iMaxSize - 1) && cursorPos == textLength)

                    {
                        CEikEdwin::SetCursorPosL(iMaxSize, EFalse);
                    }
                }
            }

        }
        return response;
    }
}

void CMIDEdwin::FocusChanged(TDrawNow aDrawNow)
{
    CEikEdwin::FocusChanged(aDrawNow);
    TBool isFocused = IsFocused();
    TInt  ret = KErrNone;

    // in case of TextFieldItem iDisplayable is not valid do not use it.
    if (!iDisplayable && iTextFieldItem->Form() == NULL)
    {
        return;
    }

    if (!IsReadOnly())
    {
        if (isFocused)
        {
            TRAP(
                ret,
                iUIManager->OpenNaviPaneControllerL()->PauseTickerL(TICKER_PAUSE_INTERVAL, this));
        }
        else
        {
            TRAP(
                ret,
                iUIManager->OpenNaviPaneControllerL()->PauseTickerL(0, this));
        }
    }
    //
    // Post ItemStateChangedEvent if focus moves away
    //
    if (iTextFieldItem && !isFocused && (iStateChanged))
    {
        TRAP(ret,iTextFieldItem->HandleControlEventL(this,MCoeControlObserver::EEventStateChanged));
        iStateChanged=EFalse;
    }

    // Show text input indicator is the last thing we want to do
    TRAP(ret,UpdateTextCapacityIndicatorValueL());
}

void CMIDEdwin::HandleControlEventL(CCoeControl* /*aControl*/,TCoeEvent aEventType)
{
    switch (aEventType)
    {
    case MCoeControlObserver::EEventStateChanged:
        iStateChanged=ETrue;
        break;
    default:
        break;
    }
}

void CMIDEdwin::ProcessModifiers()
{
    // set general edwin attributes according to TextBox constraints
    SetReadOnly(iConstraints & MMIDTextField::EUneditable);
}

void CMIDEdwin::HandleMinusCharEventL(TEdwinEvent aEventType)
{

    if ((aEventType == EEventTextUpdate) && ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENumeric))
    {
        ClearSelectionL();
        CPlainText* res = CEikEdwin::Text();
        TBuf<1> firstChar;
        if (CEikEdwin::TextLength() != 0)
        {
            res->Extract(firstChar,  0, 1);
        }
        TInt cursorPos = CEikEdwin::CursorPos();
        //toggle '-' char in the first position
        TInt pos = firstChar.Locate(TChar('-'));
        if (pos == KErrNotFound)
        {
            if (CEikEdwin::TextLength() < iMaxSize)
            {
                res->InsertL(0, KMinusChar);
                cursorPos++;
            }
            else
            {
                //play error sound if text limit is to be exceeded
                iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
            }
        }
        else
        {
            TBool deletion = res->DeleteL(0,1);
            if (cursorPos >= 1)
            {
                cursorPos--;
            }
        }
        HandleTextChangedL(); // notify editor about the text changes
        CEikEdwin::SetCursorPosL(cursorPos, EFalse);
    }
}

void CMIDEdwin::HandleEdwinEventL(CEikEdwin* aEdwin, TEdwinEvent aEventType)
{
    if (iTextFieldItem && aEventType == MEikEdwinObserver::EEventTextUpdate)
    {
        // notify Java that text has changed with itemStateChanged()
        iTextFieldItem->HandleControlEventL(aEdwin, MCoeControlObserver::EEventStateChanged);
    }

    if (aEventType == MEikEdwinObserver::EEventTextUpdate)
    {
        // handles clearing multitap counter
        if ((iLastMultitapKey != 0) && (iLastMultitapKey != iThisMultitapKey))
        {
            iLastMultitapKey = 0;
        }
        else
        {
            iThisMultitapKey = 0;
            iLastMultitapKey = 0;
        }

        TBool textChanged = EFalse;

        // in DECIMAL mode, don't allow changes that would result
        // in an illegal string;
        //  1) if there is a minus, it must be the first character
        //  2) there can be at most one decimal separator
        if ((iConstraints &
                MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)
        {
            HBufC* res = NULL;
            TRAPD(err, { res = GetTextInHBufL();});
            if (err != KErrNone || !res)
            {
                return;
            }
            CleanupStack::PushL(res);

            TInt illegalCharPos = -1;
            TPtr16 ptr = res->Des();
            TInt minusPos = ptr.LocateReverse(TChar('-'));
            TInt endCursorPos = CEikEdwin::CursorPos();

            // check if minus sign is inserted on incorrect place
            // (not at the beginning)
            if ((minusPos != KErrNotFound) && (minusPos != 0))
            {
                // check if minus sign isn't inserted twice
                if (minusPos != ptr.Locate(TChar('-')))
                {
                    illegalCharPos = minusPos;
                }
                // insert minus char at the beginning of decimal field
                else
                {
                    ptr.Delete(minusPos, 1);
                    ptr.Insert(0, KMinusChar);
                    minusPos = 0;
                    CEikEdwin::SetTextL(res);
                    textChanged = ETrue;
                }
            }

            TInt pointPosL = ptr.Locate(iDecimalSeparator);
            TInt pointPosR = ptr.LocateReverse(iDecimalSeparator);
            TInt cursorPos = CEikEdwin::CursorPos();
            if ((minusPos != KErrNotFound) && (pointPosL == 0))
            {
                illegalCharPos = pointPosL;
            }
            else if (pointPosL != pointPosR)
            {
                illegalCharPos = pointPosR;
            }

            // if minus or dot/comma char is displayed more than once
            if (illegalCharPos >= 0)
            {
                // deleting second minus or dot/comma char
                // and set cursor position on the right place
                ptr.Delete(illegalCharPos, 1);
                CEikEdwin::SetTextL(res);
                textChanged = ETrue;
                if (cursorPos >= 1)
                {
                    if (cursorPos == illegalCharPos)
                    {
                        cursorPos--;
                    }
                    endCursorPos = cursorPos;
                }
            }
            CEikEdwin::SetCursorPosL(endCursorPos, EFalse);
            CleanupStack::Pop(res);
            delete res;
        }
        else if (((iConstraints &
                   MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr)||
                 ((iConstraints &
                   MMIDTextField::EConstraintMask) == MMIDTextField::EUrl))
        {
            HBufC* res = NULL;
            TRAPD(err, { res = GetTextL();});
            if (err != KErrNone || !res)
            {
                return;
            }
            CleanupStack::PushL(res);

            // In EMAIL and URL mode, don't allow changes that would result
            // in an illegal string; if there is '/n' or '/f', and line breaks
            // are not supported, chars need to be changed to space
            // SetText function before actual text change checks if line
            // breaks are not supported
            TPtr16 text = res->Des();
            TInt tmpPos;

            if ((text.Locate(TChar('\n'))) >=0 ||
                    (text.Locate(TChar('\f'))) >=0)
            {
                tmpPos = CEikEdwin::CursorPos();
                SetTextL(*res);
                CEikEdwin::SetCursorPosL(tmpPos, EFalse);
            }

            textChanged = ETrue;
            CleanupStack::Pop(res);
            delete res;
        }

        // if there were any modifications the text is updated
        if (textChanged)
        {
            HandleTextChangedL();
        }
    }


}

void CMIDEdwin::SetInitialInputModeL(const TDesC& aCharacterSubset)
{
    iEdwinUtils->SetInitialInputModeL(aCharacterSubset,
                                      iConstraints,
                                      iInitialCurrentCase,
                                      iInitialCurrentInputMode,
                                      iInitialCurrentLanguage);

    TUint constraint = iConstraints & MMIDTextField::EConstraintMask;

    // Set permitted case modes for TextBox in lowercase or uppercase mode.
    if (aCharacterSubset.Compare(KMidpUppercaseLatin) == 0 ||
            aCharacterSubset.Compare(KMidpLowercaseLatin) == 0)
    {
        //Setting permited case mode for TextField in ANY do panic
        //when TextField loses focus.
        if (iTextFieldItem && iConstraints == MMIDTextField::EAny)
        {
            return;
        }
        // MIDP_UPPERCASE_LATIN or MIDP_LOWERCASE_LATIN are ignored if
        // INITIAL_CAPS_SENTENCE or INITIAL_CAPS_WORD modifier in ANY.
        if (!(iConstraints & MMIDTextField::EInitialCapsWordSentence ||
                iConstraints & MMIDTextField::EInitialCapsWord) ||
                constraint != MMIDTextField::EAny)
        {
            // If initial input mode is uppercase or lowercase then permit
            // only explicit case mode changes, automatic changes are not
            // allowed.
            SetAknEditorPermittedCaseModes(EAknEditorUpperCase |
                                           EAknEditorLowerCase);
        }
    }
    else
    {
        SetAknEditorPermittedCaseModes(EAknEditorAllCaseModes);
    }

}


TBool CMIDEdwin::IsNumberConversionNeeded()
{
    return iEdwinUtils->IsNumberConversionNeeded(GetConstraints());
}

void CMIDEdwin::SetFEPModeAndCharFormat()
{
    iEdwinUtils->SetFEPModeAndCharFormat(iConstraints, this);
}

/** Create non-midlet commands according to the constraints and add them
to either the displayable or to the item. Commands will be processed in ProcessCommandL(). */
void CMIDEdwin::CreateNonMidletCommandsL()
{
    if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && !(iConstraints & MMIDTextField::EUneditable))
    {
        AddCommandToEdwinL(R_MIDP_PB_FETCH_NUMBER_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_NUMBER_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchPhoneNumber);
        AddCommandToEdwinL(R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall);
    }

    if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && (iConstraints & MMIDTextField::EUneditable))
    {
        AddCommandToEdwinL(R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall);
    }

    if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr) && !(iConstraints & MMIDTextField::EUneditable))
    {
        AddCommandToEdwinL(R_MIDP_PB_FETCH_EMAIL_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_EMAIL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchEmailAddress);
    }
}

/**
Creates and adds new command to edwin based on shot & long label resource ids
and other parameters.
*/
void CMIDEdwin::AddCommandToEdwinL(TInt aCommandResIdShort,
                                   TInt aCommandResIdLong,
                                   TInt aCommandId)
{
    TBuf<64> shortLabel;
    iEikonEnv->ReadResourceL(shortLabel, aCommandResIdShort);
    TBuf<64> longLabel;
    iEikonEnv->ReadResourceL(longLabel, aCommandResIdLong);


    MMIDCommand* cmd = CMIDCommand::NewL(shortLabel, longLabel, MMIDCommand::EItem, 0, aCommandId);
    CleanupStack::PushL(cmd);

    STATIC_CAST(CMIDCommand*,cmd)->SetObserver(this);

    AddCommandToEdwinL(*cmd);
    CleanupStack::Pop(cmd);
}

/**
Creates and adds new command to edwin, short label is the same as long label.
*/
void CMIDEdwin::AddCommandToEdwinL(TInt aCommandResId, TInt aCommandId)
{
    AddCommandToEdwinL(aCommandResId, aCommandResId, aCommandId);
}

/** This method is called from the destructor and removes
    the commands added by CreateNonMidletCommandsL(). To do
    this we examine cmds on the list (either of the displayable
    or the item as applicable) and remove those whose observer is us.
    */
void CMIDEdwin::RemoveNonMidletCommands()
{
    CMIDCommandList* list = NULL;
    if (iDisplayable)
    {
        list = STATIC_CAST(CMIDDisplayable*, iDisplayable)->MainCommandList();
    }
    else if (iTextFieldItem)
    {
        list = STATIC_CAST(CMIDTextFieldItem*, iTextFieldItem)->CommandList();
    }

    if (!list)
    {
        return;
    }

    for (TInt i = 0; i < list->Count(); i++)
    {
        CMIDCommand* cmd = list->At(i).iCommand;
        if (cmd && (cmd->Observer() == this))
        {
            list->Remove(cmd);
            cmd->Dispose();
            i--;
        }
    }
}

/** Process non-midlet commands according to their unique negative id. See
MMIDCommandObserver, FetchFromPhoneBoolL() and CreateNonMidletCommandsL(). */
TBool CMIDEdwin::ProcessCommandL(CMIDCommand* aCommand)
{
    ASSERT(aCommand);
    TBool ret = EFalse;

    switch (aCommand->Id())
    {
    case CMIDEdwinUtils::EMenuCommandFetchPhoneNumber:
        // for fetching data from phonebook
        if (!iAiwPbkClient)
        {
            iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this);
        }
        iAiwPbkClient->FetchFromPhoneBookL(EAiwPhoneNumberSelect);
        ret = ETrue;
        break;
    case CMIDEdwinUtils::EMenuCommandFetchEmailAddress:
        // for fetching data from phonebook
        if (!iAiwPbkClient)
        {
            iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this);
        }
        iAiwPbkClient->FetchFromPhoneBookL(EAiwEMailSelect);
        ret = ETrue;
        break;
    case CMIDEdwinUtils::EMenuCommandCreatePhoneCall:
        CreatePhoneCallL();
        ret = ETrue;
        break;
    default:
        break;
    }

    return ret;
}

void CMIDEdwin::CreatePhoneCallL()
{
    iEdwinUtils->CreatePhoneCallL(TextLength(), CCoeEnv::Static()->WsSession(), this);
}

/** From MTickerObserver: If the ticker is showing disable the displaying of
edit indicators in the navi pane.  **/
void CMIDEdwin::TickerShowing(TBool aShowing)
{
    TInt flags = aShowing ? EAknEditorFlagNoEditIndicators | AknEdwinFlags() :
                 ~EAknEditorFlagNoEditIndicators & AknEdwinFlags();

    SetAknEditorFlags(flags);
}

void CMIDEdwin::HandleCurrentL(TBool aActivate)
{
    // when becoming the current Displayable, set editor input mode
    // to the one set by SetInitialInputModeL
    if (aActivate &&
            ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EAny ||
             (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr ||
             (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EUrl))
    {
        if (iInitialCurrentLanguage)
        {
            SetAknEditorLocalLanguage(iInitialCurrentLanguage);
            if (iInitialCurrentInputMode == 0)
            {
                // clears any number mode used previously
                SetAknEditorCurrentInputMode(EAknEditorNullInputMode);
            }
        }

        if (iInitialCurrentInputMode)
        {
            SetAknEditorCurrentInputMode(iInitialCurrentInputMode);
        }

        if (iInitialCurrentCase)
        {
            TInt initialCurrentCase = iInitialCurrentCase;
            if ((iConstraints & MMIDTextField::EPassword ||
                    iConstraints & MMIDTextField::EMailAddr ||
                    iConstraints & MMIDTextField::EUrl) &&
                    iInitialCurrentCase == EAknEditorTextCase)
            {
                // Text case is not used in passwords, emailaddrs and urls
                initialCurrentCase = EAknEditorLowerCase;
            }
            SetAknEditorCurrentCase(initialCurrentCase);
            SetAknEditorCase(initialCurrentCase);
        }
    }
    if (aActivate)
    {
        UpdateTextCapacityIndicatorValueL();
    }
}

/** Update the text capacity indicator if we have focus and are not read only.*/
void CMIDEdwin::UpdateTextCapacityIndicatorValueL()
{
    TBool isActive = iDisplayable ? iDisplayable->IsActive() :
                     (iTextFieldItem->Form() ? iTextFieldItem->Form()->CurrentDisplayable().IsActive() : EFalse);

    if (IsFocused() && isActive && !(iConstraints & MMIDTextField::EUneditable))
    {
        // Navi pane controller is opened on constructor phase so it should exists
        iUIManager->OpenNaviPaneControllerL()->UpdateTextInputIndicatorL(
            iMaxSize - TextLength());
        iDisplayingCapacityIndic = ETrue;
    }
    else if (iDisplayingCapacityIndic)
    {
        // Navi pane controller is opened on constructor phase so it should exists
        iUIManager->OpenNaviPaneControllerL()->UpdateTextInputIndicatorL(-1);
        iDisplayingCapacityIndic = EFalse;
    }
}

/** Updates capacity indicator when text is pasted. */
void CMIDEdwin::HandleTextPastedL(TInt aStartPos,TInt& aLength)
{
    // When TextBox field is NUMERIC, PHONENUMBER or DECIMAL new line
    // characters if exists in copied text must be filtered out before pasting

    if ((IsConstraintSet(MMIDTextField::ENumeric) ||
            IsConstraintSet(MMIDTextField::EPhoneNumber) ||
            IsConstraintSet(MMIDTextField::EDecimal)) != EFalse)
    {
        HBufC* hbuf = GetTextInHBufL();
        TPtr strPtr = hbuf->Des();
        TInt firstPos = strPtr.Find(KLineSeparator);

        if (firstPos != KErrNotFound)
        {
            CleanupStack::PushL(hbuf);
            while (firstPos != KErrNotFound)
            {
                strPtr.Delete(firstPos, KLineSeparator().Length());
                firstPos = strPtr.Find(KLineSeparator);
            }
            CEikEdwin::SetTextL(hbuf);
            CleanupStack::Pop(hbuf);
        }
        delete hbuf;
    }
    UpdateTextCapacityIndicatorValueL();
    CEikEdwin::HandleTextPastedL(aStartPos, aLength);
}

TPtrC CMIDEdwin::Read() const
{
    if (iConstraints & MMIDTextField::EPassword)
    {
        return static_cast<CPasswordBoxGlobalText*>(iText)->ClearText();
    }
    else
    {
        return iText->Read(0,TextLength());
    }
}