meetingrequest/mrgui/mrfieldbuildercommon/src/cesmrrichtextviewer.cpp
branchRCL_3
changeset 12 4ce476e64c59
parent 4 e7aa27f58ae1
child 13 8592a65ad3fb
--- a/meetingrequest/mrgui/mrfieldbuildercommon/src/cesmrrichtextviewer.cpp	Mon Mar 15 12:39:10 2010 +0200
+++ b/meetingrequest/mrgui/mrfieldbuildercommon/src/cesmrrichtextviewer.cpp	Wed Mar 31 21:08:33 2010 +0300
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+* Copyright (c) 2009 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"
@@ -12,6 +12,7 @@
 * Contributors:
 *
 *  Description : CEikRichTextEditor based Rich Text viewer
+*  Version     : %version: e002sa32#36 %
 *
 */
 
@@ -20,39 +21,47 @@
 #include "mesmrlistobserver.h"// SCROLLING_MOD: List observer header
 #include "esmrconfig.hrh"
 #include "esmrhelper.h"
-#include "cesmriconfield.h"
 #include "cesmrfieldcommandevent.h"
 #include "mesmrfieldeventqueue.h"
-#include "cesmrlayoutmgr.h"
 #include "cesmrrichtextlink.h"
 #include "cesmrcontactmenuhandler.h"
 #include "nmrbitmapmanager.h"
+#include "nmrcolormanager.h"
+#include "esmrfieldbuilderdef.h"
+#include "cesmrfield.h"
 
 #include <esmrgui.rsg>
 #include <commonphoneparser.h>
 #include <finditemengine.h>
 #include <txtrich.h>
-#include <AknsUtils.h>
+#include <aknsutils.h>
+#include <aknbiditextutils.h>
+#include <aknutils.h>
 #include <eikenv.h>
 #include <data_caging_path_literals.hrh>
 #include <baclipb.h> // for clipboard copy
-#include <aknlongtapdetector.h>
-#include <touchfeedback.h>
-
-#ifndef FF_CMAIL_INTEGRATION
 #include <txtclipboard.h>
-#endif // FF_CMAIL_INTEGRATION
 
 // DEBUG
 #include "emailtrace.h"
 
-// <cmail> Removed profiling. </cmail>
-
 // Unnamed namespace for local definitions
 namespace{ // codescanner::namespace
 
-const TInt KArrowUpperMargin (2);
-const TInt KArrowRightMargin (5);
+#ifdef _DEBUG
+    enum TPanic
+        {
+        EParaFormatNotInitialised = 1
+        };
+    void Panic( TPanic aPanic )
+        {
+        _LIT( KCategory, "CESMRRichTextViewer" );
+        User::Panic( KCategory(), aPanic );
+        }
+#endif // DEBUG
+
+// Side margin in twips, needed because not possible to set it in pixels
+const TInt KDefaultTextSideMargin( 1 );
 
 }//namespace
 
@@ -81,10 +90,8 @@
     {
     FUNC_LOG;
     iLinkList.ResetAndDestroy ( );
-    delete iActionMenuIcon;
-    delete iActionMenuIconMask;
     iESMRStatic.Close ( );
-    delete iLongTapDetector;
+    delete iParaFormat;
     }
 
 // -----------------------------------------------------------------------------
@@ -116,61 +123,41 @@
         return;
         }
 
-    if ( IsFocused() )
+    // Check the current selection.
+    // If a link has been highlighted, don't change it.
+    TCursorSelection selection = Selection();
+
+    // Gaining focus
+    if ( IsFocused()
+         && iLinkList.Count() > 0
+         && selection.Length() == 0 )
         {
-        if( iLayout )
-            {
-            TRAP_IGNORE( SetFontColorL( ETrue ) );
-            }
+        // We need the field indexes, cast required
+        CESMRField* parent = static_cast< CESMRField* >( Parent() );
 
-        if ( iCurrentLinkIndex == KErrNotFound )
+        iCntMenuHdlr->SetContactMenuObserver( this );
+        // Focus coming from above ...
+        if( parent->CurrentItemIndex() > parent->PreItemIndex() )
             {
-            TInt linkRow = KErrNotFound;
-            if ( CursorPos() == 0 )
-                {
-                // focus is coming from field above:
-                linkRow = FindTextLinkBetweenNextScrollArea(
-                		0, 1, TCursorPosition::EFLineDown );
-                }
-            else
-                {
-                linkRow = FindTextLinkBetweenNextScrollArea(
-                		LineCount()-2,
-                        LineCount()-1,
-                        TCursorPosition::EFLineUp);
-                }
-            if ( linkRow != KErrNotFound )
-                {
-                const CESMRRichTextLink* link = GetSelectedLink ( );
-                if (link )
-                    {
-                    HighlightLink (*link );
-                    DrawDeferred ( );
-                    }
-                }
+            // ... Highlight first link
+            TRAP_IGNORE( HighlightLinkL( *( iLinkList[0] ) ) );
             }
+        // Focus coming from below ...
         else
             {
-            const CESMRRichTextLink* link = GetSelectedLink ( );
-            if ( link )
-            	{
-            	HighlightLink( *link );
-            	DrawDeferred();
-            	}
+            // ... Highlight last link
+            TRAP_IGNORE( HighlightLinkL( *( iLinkList[iLinkList.Count() - 1 ] ) ) );
             }
+        DrawDeferred();
         }
 
-    if (!IsFocused())
+    // Losing focus
+    if ( !IsFocused() )
         {
-        // losing focus
-        // <cmail> codescanner
-		TRAP_IGNORE(SetSelectionL(CursorPos(), CursorPos()));
-        if( iLayout )
-            {
-            TRAP_IGNORE(SetFontColorL( EFalse ));
-            }
-        // </cmail>
-        TRAP_IGNORE( TextView()->SetDocPosL( 0 ));
+        TRAP_IGNORE(
+                SetSelectionL( CursorPos(), CursorPos() );
+                ResetActionMenuL();
+                );
         }
     }
 
@@ -208,7 +195,6 @@
                 }
             }
 
-    iCurrentLinkIndex = KErrNotFound;
     return linkRow;
     }
 
@@ -224,23 +210,26 @@
     {
     FUNC_LOG;
 
+    if ( iLinkList.Count() > aIndex)
+	    {
+	    TInt currPos( KErrNotFound );
+        const CESMRRichTextLink* currentLink = GetSelectedLink();
+        if ( currentLink )
+            {
+            currPos = currentLink->StartPos();
+            }
 
-    if(iLinkList.Count() > aIndex)
-	    {
-        TInt pos = iLinkList[aIndex]->StartPos();
+        TInt pos = iLinkList[ aIndex ]->StartPos();
 
 	    TInt checkRow = TextLayout()->GetLineNumber( pos );
 
-	    if ( checkRow >= aStartRow && checkRow <= ( aEndRow ) )
+	    if ( checkRow >= aStartRow && checkRow <= aEndRow )
 	        {
 	        if ( aDirection == TCursorPosition::EFLineDown &&
-	             aIndex > iCurrentLinkIndex  ||
+	             pos > currPos ||
 	             aDirection == TCursorPosition::EFLineUp &&
-	             ( aIndex < iCurrentLinkIndex ||
-	               iCurrentLinkIndex == KErrNotFound ))
+	             ( pos < currPos || currPos == KErrNotFound ) )
 	            {
-	            iCurrentLinkIndex = aIndex;
-
 	            // link found between next scroll area.
 	            return checkRow;
 	            }
@@ -250,60 +239,6 @@
     }
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::SetHighLightToNextLinkL
-// -----------------------------------------------------------------------------
-//
-TBool CESMRRichTextViewer::SetHighLightToNextLinkL(
-        TCursorPosition::TMovementType aDirection,
-        TInt aStartRow,
-        TInt aEndRow )
-    {
-    FUNC_LOG;
-    TBool ret( EFalse );
-
-    TInt currentLineNumber = TextLayout()->GetLineNumber( CursorPos() );
-
-    // check is there a link before next scroll point:
-    TInt linkRow = FindTextLinkBetweenNextScrollArea(
-						aStartRow , aEndRow, aDirection);
-
-    if ( linkRow != KErrNotFound && iCurrentLinkIndex != KErrNotFound )
-        {
-        const CESMRRichTextLink* link = GetSelectedLink ( );
-        if (link )
-            {
-            HighlightLink (*link );
-
-            if ( iObserver && linkRow != currentLineNumber )
-                {
-                TInt endOfLink = link->StartPos()+link->Length();
-                TInt line = TextLayout()->GetLineNumber( endOfLink );
-                if ( aDirection == TCursorPosition::EFLineUp ) // moving up:
-                    {
-                    iObserver->MoveListAreaDownL(
-                            RowHeight() * ( currentLineNumber - line ));
-                    }
-                else
-                    {
-                    iObserver->MoveListAreaUpL(
-                            RowHeight() * ( line - currentLineNumber ));
-                    }
-                }
-
-            DrawDeferred ( );
-            ret = ETrue;
-            }
-        }
-    else
-    	{
-    	// no link are focused, do reset work to refresh the option menu.
-    	ResetActionMenuL();
-    	}
-
-    return ret;
-    }
-
-// -----------------------------------------------------------------------------
 // CESMRRichTextViewer::OfferKeyEventL
 // -----------------------------------------------------------------------------
 //
@@ -312,167 +247,160 @@
         TEventCode aType )
     {
     FUNC_LOG;
-    // Handle only event keys
-    if ( aType == EEventKey )
+    TKeyResponse response( EKeyWasNotConsumed );
+
+    // Handle only event keys.
+    if( aType != EEventKey )
         {
-        if ( iObserver ) // only description field has observer set.
+        return response;
+        }
+
+    /*
+     * Handles scrolling between rich text links.
+     */
+    const CESMRRichTextLink* selectedLink = GetSelectedLink();
+    TInt linkCount = iLinkList.Count();
+
+    // If a link is selected, it means that we are operating within
+    // the field and can move focus between the links.
+    if( linkCount && selectedLink )
+        {
+        TInt selectedLinkIndex = iLinkList.Find( selectedLink );
+
+        switch ( aKeyEvent.iCode )
             {
-            // fetch the current line number:
-            TInt currentLineNumber = TextLayout()->GetLineNumber( CursorPos() );
-
-            if ( aKeyEvent.iCode == EKeyDownArrow && aType == EEventKey )
+            case EKeyLeftArrow:
+            case EKeyUpArrow:
                 {
-                if ( !iObserver->IsFieldBottomVisible() &&
-                     SetHighLightToNextLinkL(
-                    		 TCursorPosition::EFLineDown,
-                             currentLineNumber,
-                             currentLineNumber + KMaxAddressFieldLines) )
-                    {
-                    return EKeyWasConsumed;
-                    }
-                else if ( iObserver->IsFieldBottomVisible() )
+                // If possible and exists ...
+                if( selectedLinkIndex > 0 &&
+                        selectedLinkIndex < linkCount )
                     {
-                    if ( SetHighLightToNextLinkL(TCursorPosition::EFLineDown,
-                                            currentLineNumber,
-                                            iNumberOfLines) )
-                        {
-                        return EKeyWasConsumed;
-                        }
-                    // means that the whole control is visible:
-                    // and we can skip to next field
-                    return EKeyWasNotConsumed;
-                    }
+                    // ...Highlight previous link.
+                    HighlightLinkL( *( iLinkList[ selectedLinkIndex - 1 ] ) );
+                    response = EKeyWasConsumed;
 
-                if ( currentLineNumber == iNumberOfLines )
-                    {
-                    // the end of text has been reached
-                    return EKeyWasConsumed;
-                    }
-
-                // move three lines...
-                ScrollViewL( KMaxAddressFieldLines,
-							 TCursorPosition::EFLineDown);
-
-
-                SetSelectionL( CursorPos(), CursorPos() );
-                iCurrentLinkIndex = KErrNotFound;
-                if ( iObserver )
-                    {
-                    iObserver->MoveListAreaUpL(
-                    		RowHeight() * KMaxAddressFieldLines );
+                    // View update required, for example if link is out of
+                    // viewable area.
+                    UpdateViewL( aKeyEvent );
                     }
 
-                return EKeyWasConsumed;
+                break;
                 }
-            else if ( aKeyEvent.iCode == EKeyUpArrow && aType == EEventKey )
+            case EKeyRightArrow:
+            case EKeyDownArrow:
                 {
-                if (iPosition.iY < 0 &&
-                    SetHighLightToNextLinkL(
-                    		TCursorPosition::EFLineUp,
-                            currentLineNumber - KMaxAddressFieldLines,
-                            currentLineNumber))
-                    {
-                    return EKeyWasConsumed;
-                    }
-                if ( iPosition.iY > 0 )
+                // If possible and exists ...
+                if( selectedLinkIndex + 1 < linkCount &&
+                        selectedLinkIndex >= 0 )
                     {
-                    // before changing the focus the field above,
-                    // check is there any links in rest of text
-                    if (SetHighLightToNextLinkL(TCursorPosition::EFLineUp,
-                                        0,
-                                        currentLineNumber))
-                        {
-                        return EKeyWasConsumed;
-                        }
-
-                    // means that the whole control is visible:
-                    // and we can skip to next field
-                    return EKeyWasNotConsumed;
-                    }
-                else
-                    {
-                    TInt currentLineNumber =
-                    TextLayout()->GetLineNumber( CursorPos() );
-                    // move three lines...
-                    ScrollViewL( KMaxAddressFieldLines,
-                    		     TCursorPosition::EFLineUp);
-
-                    SetSelectionL( CursorPos(), CursorPos());
-                    iCurrentLinkIndex = KErrNotFound;
-
-                     if ( iObserver )
-                        {
-                        iObserver->MoveListAreaDownL(
-                        		RowHeight() * KMaxAddressFieldLines );
-                        }
+                    // ...Highlight next link.
+                    HighlightLinkL( *( iLinkList[ selectedLinkIndex + 1 ] ) );
+                    response = EKeyWasConsumed;
 
-                    currentLineNumber =
-						TextLayout()->GetLineNumber( CursorPos() );
-                    return EKeyWasConsumed;
+                    // View update required, for example if link is out of
+                    // viewable area.
+                    UpdateViewL( aKeyEvent );
                     }
-                }
-            }
-        if ( aKeyEvent.iCode == EKeyRightArrow ||
-        	 aKeyEvent.iCode == EKeyDevice3 ||
-             aKeyEvent.iCode == EKeyDevice4 ||
-             aKeyEvent.iCode == EKeyEnter )
-            {
-            // Show right click menu (action menu)
-            const CESMRRichTextLink* link = GetSelectedLink();
-            if (link &&
-            	link->TriggerKey ( )== CESMRRichTextLink::ETriggerKeyRight )
-                {
-                if ( !iLinkObserver ||
-                	 !iLinkObserver->HandleRichTextLinkSelection(link) )
-                    {
-                    iCntMenuHdlr->ShowActionMenuL();
-                    }
-                return EKeyWasConsumed;
+
+                break;
                 }
-            }
-        if ( aKeyEvent.iCode == EKeyLeftArrow )
-            {
-            const CESMRRichTextLink* link = GetSelectedLink();
-            if ( link )
+            case EKeyDevice3: // Selection key
                 {
-                return EKeyWasConsumed;
+                // No implementation. Non-MSK devices might require this.
+                break;
                 }
-            }
-        if ( aKeyEvent.iCode == EKeyDevice3 ||
-        		aKeyEvent.iCode == EKeyDevice4 ||
-        		aKeyEvent.iCode == EKeyEnter )
-            {
-            // Select link
-            const CESMRRichTextLink* link = GetSelectedLink ( );
-            if (link &&
-            	link->TriggerKey ( )== CESMRRichTextLink::ETriggerKeyOk )
-                {
-                if (iLinkObserver &&
-                	iLinkObserver->HandleRichTextLinkSelection (link ) )
-                    {
-                    return EKeyWasConsumed;
-                    }
-                }
+            default:
+                break;
             }
         }
 
-    return EKeyWasNotConsumed;
+    return response;
     }
 
-
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::ScrollViewL
+// CESMRRichTextViewer::HandlePointerEventL
 // -----------------------------------------------------------------------------
 //
-void CESMRRichTextViewer::ScrollViewL(
-        TInt aNumberOfRows,
-        TCursorPosition::TMovementType aDirection)
+void CESMRRichTextViewer::HandlePointerEventL( const TPointerEvent& aPointerEvent )
     {
-    FUNC_LOG;
-    for( TInt i=0; i < aNumberOfRows; i++ )
+    if ( Rect().Contains( aPointerEvent.iPosition) )
         {
-        MoveCursorL( aDirection, EFalse);
+        TBool linkFound( EFalse );
+
+        switch ( aPointerEvent.iType )
+            {
+            case TPointerEvent::EButton1Down:
+            case TPointerEvent::EDrag:
+                {
+                RRegion linkArea;
+                CleanupClosePushL( linkArea );
+
+                // Find matching link
+                TInt count = iLinkList.Count();
+
+                for ( TInt i = 0; i < count; ++i )
+                    {
+                    CESMRRichTextLink* link = iLinkList[ i ];
+                    GetLinkAreaL( linkArea, *link );
+
+                    if ( linkArea.Contains( aPointerEvent.iPosition ) )
+                        {
+                        if ( link != GetSelectedLink() )
+                            {
+                            iCntMenuHdlr->SetContactMenuObserver( this );
+                            HighlightLinkL( *link );
+                            DrawDeferred();
+                            }
+
+                        linkFound = ETrue;
+                        break;
+                        }
+                    }
+
+                CleanupStack::PopAndDestroy( &linkArea );
+
+                break;
+                }
+
+            case TPointerEvent::EButton1Up:
+                {
+                const CESMRRichTextLink* link = GetSelectedLink();
+
+                TBool menuAvailable = iCntMenuHdlr->OptionsMenuAvailable();
+
+                if ( link
+                     && ( menuAvailable
+                     || link->Type() == CESMRRichTextLink::ETypeLocationUrl
+                     || link->Type() == CESMRRichTextLink::ETypeAttachment ) )
+                    {
+                    linkFound = ETrue;
+
+                    LinkSelectedL();
+                    }
+                else if ( link && !menuAvailable )
+                    {
+                    linkFound = ETrue;
+                    iOpenActionMenu = ETrue;
+                    }
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+
+        if ( !linkFound )
+            {
+            // Tap on plain text
+            TextView()->ClearSelectionL();
+            ResetActionMenuL();
+            DrawDeferred();
+            }
+
         }
+
     }
 
 // -----------------------------------------------------------------------------
@@ -482,88 +410,10 @@
 EXPORT_C void CESMRRichTextViewer::SetMargins( TInt sMargin )
 	{
 	// Set new value for left and right margins
-	if ( TextView() )
-	    {
-        TextView()->SetMarginWidths( sMargin ,0);
-	    }
+    TextView()->SetMarginWidths( sMargin ,0);
 	}
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::SetFontL
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CESMRRichTextViewer::SetFontL( const CFont* aFont,
-                                             CESMRLayoutManager* aLayout )
-    {
-    FUNC_LOG;
-    // These pointers are stored to able font color changing when losing or
-    // gaining focus
-    iLayout = aLayout;
-    iFont = aFont;
-
-    SetFontColorL( IsFocused() );
-
-    // This forces CEikEdwin::OnReformatL to notify observer
-    // through HandleEdwinSizeEventL about changed size.
-    // It is notified only if linecount changes.
-    CEikEdwin::iNumberOfLines = 0;
-    CEikEdwin::FormatTextL();
-    }
-
-// -----------------------------------------------------------------------------
-// CESMRRichTextViewer::SetFontColor
-// -----------------------------------------------------------------------------
-//
-void CESMRRichTextViewer::SetFontColorL( TBool aFocused )
-    {
-    FUNC_LOG;
-    // all this stuff is needed to be set, otherwise the
-    // font loses its antialiasing drawing
-
-    TFontSpec fontSpec = iFont->FontSpecInTwips();
-
-    CParaFormat paraFormat;
-    TParaFormatMask paraFormatMask;
-    paraFormat.iLineSpacingControl = CParaFormat::ELineSpacingExactlyInPixels;
-
-    paraFormatMask.SetAttrib( EAttLineSpacing );
-    paraFormat.iHorizontalAlignment = CParaFormat::ELeftAlign;
-    paraFormatMask.SetAttrib( EAttAlignment );
-
-    TCharFormat charFormat;
-    TCharFormatMask formatMask;
-    charFormat.iFontSpec = fontSpec;
-
-    formatMask.SetAttrib( EAttFontTypeface );
-    formatMask.SetAttrib( EAttFontHeight );
-    formatMask.SetAttrib( EAttFontPosture );
-    formatMask.SetAttrib( EAttFontStrokeWeight );
-
-    if( aFocused )
-        {
-        charFormat.iFontPresentation.iTextColor =
-        iLayout->ViewerListAreaHighlightedTextColor();
-        }
-    else
-        {
-        charFormat.iFontPresentation.iTextColor = KRgbBlack;
-        }
-    formatMask.SetAttrib( EAttColor );
-
-    CParaFormatLayer* paraFormatLayer =
-        CParaFormatLayer::NewL( &paraFormat, paraFormatMask );
-    CleanupStack::PushL( paraFormatLayer );
-
-    CCharFormatLayer* charFormatLayer =
-        CCharFormatLayer::NewL( charFormat, formatMask );
-
-    SetParaFormatLayer( paraFormatLayer );
-    SetCharFormatLayer( charFormatLayer );
-
-    CleanupStack::Pop( paraFormatLayer );
-    }
-
-// -----------------------------------------------------------------------------
 // CESMRRichTextViewer::SetTextL
 // -----------------------------------------------------------------------------
 //
@@ -572,34 +422,37 @@
         TBool aSearchLinks )
     {
     FUNC_LOG;
-    iCurrentLinkIndex = KErrNotFound;
-    iLinkList.ResetAndDestroy ( );
+
+    iLinkList.ResetAndDestroy();
+
+    TextView()->SetMarginWidths( KDefaultTextSideMargin ,0);
 
     // Clear edwin text
     CEikEdwin::SetCursorPosL( 0, EFalse );
+    CEikRichTextEditor::SetTextL( &KNullDesC );
+    RichText()->Reset();
 
     // text lenght plus one to ensure the formatting
     // used is full, not band formatting.
     SetUpperFullFormattingLength( aText->Length() + 1 );
 
     // Set new edwin text
+    CEikEdwin::SetTextLimit( aText->Length ( ) );
     CEikRichTextEditor::SetTextL( aText );
 
     //Make sure cursor is invisible and selection visible
-    TextView()->SetCursorVisibilityL (TCursor::EFCursorInvisible,
+    TextView()->SetCursorVisibilityL(
+            TCursor::EFCursorInvisible,
             TCursor::EFCursorInvisible );
-    TextView()->SetSelectionVisibilityL (ETrue );
+    TextView()->SetSelectionVisibilityL( ETrue );
 
     // Search text for links (highlights)
-    if (aSearchLinks )
+    if ( aSearchLinks )
         {
         SearchLinksL( *aText );
         // find first link.
         FindTextLinkBetweenNextScrollArea(0, KMaxAddressFieldLines, TCursorPosition::EFLineDown);
         }
-
-    // first row is 0, so let's add one...
-    iNumberOfLines = TextLayout()->GetLineNumber( TextLength() ) + 1;
     }
 
 // -----------------------------------------------------------------------------
@@ -626,8 +479,8 @@
     // Reserve space for new link
     iLinkList.ReserveL( iLinkList.Count() + 1 );
 
-    RichText()->ApplyCharFormatL( iFormat,
-                                  iFormatMask,
+    RichText()->ApplyCharFormatL( iRichTextLinkFormat,
+                                  iRichTextLinkFormatMask,
                                   aLink->StartPos(),
                                   aLink->Length() );
 
@@ -636,7 +489,7 @@
 
     if ( highlight )
         {
-        HighlightLink( *aLink );
+        HighlightLinkL( *aLink );
         }
     }
 
@@ -654,8 +507,8 @@
     // Reserve space for new link
     iLinkList.ReserveL( iLinkList.Count() + 1 );
 
-    RichText()->ApplyCharFormatL( iFormat,
-                                  iFormatMask,
+    RichText()->ApplyCharFormatL( iRichTextLinkFormat,
+                                  iRichTextLinkFormatMask,
                                   aLink->StartPos(),
                                   aLink->Length() );
 
@@ -665,7 +518,7 @@
 
     if ( highlight )
         {
-        HighlightLink( *aLink );
+        HighlightLinkL( *aLink );
         }
     }
 
@@ -676,25 +529,38 @@
 EXPORT_C const CESMRRichTextLink* CESMRRichTextViewer::GetSelectedLink( ) const
     {
     FUNC_LOG;
-    if (iCurrentLinkIndex >= 0 && iCurrentLinkIndex < iLinkList.Count ( ) )
+    CESMRRichTextLink* link( NULL );
+
+    TCursorSelection currentSelection = Selection();
+
+    for ( TInt i = 0; i < iLinkList.Count(); ++i )
         {
-        return iLinkList[iCurrentLinkIndex];
+        CESMRRichTextLink* tempLink = iLinkList[i];
+        TInt startPos = tempLink->StartPos();
+        TInt length = tempLink->Length();
+
+        TCursorSelection linkSelection( startPos, startPos + length );
+
+        if( currentSelection.iCursorPos == linkSelection.iCursorPos &&
+                currentSelection.iAnchorPos == linkSelection.iAnchorPos )
+            {
+            link = tempLink;
+            break;
+            }
         }
-    else
-        {
-        return NULL;
-        }
+
+    return link;
     }
 
 // -----------------------------------------------------------------------------
 // CESMRRichTextViewer::GetLinkTextL
 // -----------------------------------------------------------------------------
 //
-EXPORT_C HBufC* CESMRRichTextViewer::GetLinkTextL(
+EXPORT_C HBufC* CESMRRichTextViewer::GetLinkTextLC(
         const CESMRRichTextLink& aLink ) const
     {
     FUNC_LOG;
-    return RichText()->Read( aLink.StartPos ( ), aLink.Length ( ) ).AllocL();
+    return RichText()->Read( aLink.StartPos(), aLink.Length() ).AllocLC();
     }
 
 // -----------------------------------------------------------------------------
@@ -729,7 +595,9 @@
 EXPORT_C TInt CESMRRichTextViewer::LineCount()
     {
     FUNC_LOG;
-    return iNumberOfLines;
+
+    // First row is 0, so let's add one...
+    return ( TextLayout()->GetLineNumber( TextLength() ) + 1 );
     }
 // -----------------------------------------------------------------------------
 // CESMRRichTextViewer::CurrentLineNumber
@@ -743,13 +611,133 @@
     }
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::CESMRRichTextViewer
+// CESMRRichTextViewer::SetFontL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRichTextViewer::SetFontL( const CFont* aFont )
+    {
+    FUNC_LOG;
+    // iFont is stored for changing font color when losing or
+    // gaining focus
+    iFont = aFont;
+    if ( !iParaFormat )
+        {
+        iParaFormat = new ( ELeave ) CParaFormat();
+        }
+
+    // All this required, otherwise the font loses its
+    // antialiasing drawing.
+    iParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingExactlyInPixels;
+
+    iParaFormatMask.SetAttrib( EAttLineSpacing );
+    iParaFormat->iHorizontalAlignment = CParaFormat::ELeftAlign;
+    iParaFormat->iVerticalAlignment = CParaFormat::ECenterAlign;
+    iParaFormatMask.SetAttrib( EAttAlignment );
+    iParaFormatMask.SetAttrib( EAttVerticalAlignment );
+
+    iCharFormat.iFontSpec = iFont->FontSpecInTwips();
+
+    iCharFormatMask.SetAttrib( EAttFontTypeface );
+    iCharFormatMask.SetAttrib( EAttFontHeight );
+    iCharFormatMask.SetAttrib( EAttFontPosture );
+    iCharFormatMask.SetAttrib( EAttFontStrokeWeight );
+
+    iCharFormat.iFontPresentation.iTextColor =
+        NMRColorManager::Color( NMRColorManager::EMRMainAreaTextColor );
+
+    iCharFormatMask.SetAttrib( EAttColor );
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::SetLineSpacingL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRichTextViewer::SetLineSpacingL( TInt aLineSpacingInTwips )
+    {
+    __ASSERT_DEBUG( iParaFormat, Panic( EParaFormatNotInitialised ) );
+    iParaFormatMask.SetAttrib( EAttLineSpacing );
+    iParaFormatMask.SetAttrib( EAttLineSpacingControl );
+    iParaFormat->iLineSpacingControl =
+        CParaFormat::ELineSpacingExactlyInPixels;
+
+    iParaFormat->iLineSpacingInTwips = aLineSpacingInTwips;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::ApplyLayoutChanges
 // -----------------------------------------------------------------------------
 //
-EXPORT_C void CESMRRichTextViewer::SetActionMenuStatus( TBool aStatus )
+EXPORT_C void CESMRRichTextViewer::ApplyLayoutChangesL()
+    {
+    __ASSERT_DEBUG( iParaFormat, Panic( EParaFormatNotInitialised ) );
+    CRichText* richtext = RichText();
+    TInt paraCount( richtext->ParagraphCount() );
+    // Go through each paragraph and apply the same format
+    for( TInt i = 0; i < paraCount; ++i  )
+        {
+        TInt paraLen( 0 );   // Length of paragraph
+        TInt fiChPos( 0 );   // First character position of paragraph
+        // Get the length of the paragraph
+        fiChPos = richtext->CharPosOfParagraph( paraLen, i );
+        richtext->ApplyParaFormatL(
+                iParaFormat, iParaFormatMask, fiChPos, paraLen );
+        richtext->ApplyCharFormatL(
+                iCharFormat, iCharFormatMask, fiChPos, paraLen );
+        }
+    // This forces CEikEdwin::OnReformatL to notify observer
+    // through HandleEdwinSizeEventL about changed size.
+    // It is notified only if linecount changes.
+    CEikEdwin::iNumberOfLines = 0;
+    CEikEdwin::FormatTextL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::SetSelectedLink
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRichTextViewer::SetFocusLink( TInt aLinkIndex )
+    {
+    if ( ( aLinkIndex >= 0 ) && ( aLinkIndex < iLinkList.Count() ) )
+        {
+        TRAP_IGNORE( HighlightLinkL( *( iLinkList[aLinkIndex] ) ) );
+        DrawDeferred();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::GetSelectedLink
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CESMRRichTextViewer::GetFocusLink( ) const
     {
     FUNC_LOG;
-    iActionMenuStatus = aStatus;
+    // "-1" stand for no link be selected now.
+    TInt linkIndex( KErrNotFound );
+    if ( 0 == iLinkList.Count() )
+        {
+        return linkIndex;
+        }
+    
+    TCursorSelection currentSelection = Selection();
+
+    for ( TInt i = 0; i < iLinkList.Count(); ++i )
+        {
+        CESMRRichTextLink* tempLink = iLinkList[i];
+        TInt startPos = tempLink->StartPos();
+        TInt length = tempLink->Length();
+
+        TCursorSelection linkSelection( startPos, startPos + length );
+
+        if( currentSelection.iCursorPos == linkSelection.iCursorPos &&
+                currentSelection.iAnchorPos == linkSelection.iAnchorPos )
+            {
+            linkIndex = i;
+            break;
+            }
+        }
+
+    return linkIndex;
     }
 
 // -----------------------------------------------------------------------------
@@ -757,7 +745,6 @@
 // -----------------------------------------------------------------------------
 //
 CESMRRichTextViewer::CESMRRichTextViewer( )
-:   iActionMenuStatus( ETrue ), iActionMenuOpen( EFalse )
     {
     FUNC_LOG;
     }
@@ -779,103 +766,40 @@
         flags |= CEikEdwin::EOwnsWindow;
         }
 
-    CEikRichTextEditor::ConstructL (aParent, 1, 1, flags );
-    SetSuppressBackgroundDrawing (ETrue );
-
-    User::LeaveIfError(
-            NMRBitmapManager::GetSkinBasedBitmap(
-                    NMRBitmapManager::EMRBitmapRightClickArrow, iActionMenuIcon,
-                    iActionMenuIconMask, KIconSize ) );
-
-    iESMRStatic.ConnectL ( );
-    iCntMenuHdlr = &iESMRStatic.ContactMenuHandlerL();
-    iCurrentLinkIndex = KErrNotFound;
-    iFormatMask.SetAttrib( EAttFontUnderline );
-    iFormat.iFontPresentation.iUnderline = EUnderlineOn;
-    iFormatMask.SetAttrib( EAttColor );
-    iFormat.iFontPresentation.iTextColor = KRgbBlue;
+    CEikRichTextEditor::ConstructL( aParent, 1, 1, flags );
+    SetSuppressBackgroundDrawing( ETrue );
 
-    iLongTapDetector = CAknLongTapDetector::NewL(this);
-    }
-
-// -----------------------------------------------------------------------------
-// CESMRRichTextViewer::Draw
-// -----------------------------------------------------------------------------
-//
-void CESMRRichTextViewer::Draw( const TRect& aRect ) const
-    {
-    FUNC_LOG;
-    CEikEdwin::Draw( aRect );
-    if (IsFocused ( ) && iActionMenuStatus )
-        {
-        const CESMRRichTextLink* link = GetSelectedLink ( );
-        if (link && link->TriggerKey ( )== CESMRRichTextLink::ETriggerKeyRight )
-            {
-            TRAP_IGNORE(DrawRightClickIconL(*link));
-            }
-        }
+    iESMRStatic.ConnectL();
+    iCntMenuHdlr = &iESMRStatic.ContactMenuHandlerL();
+    iRichTextLinkFormatMask.SetAttrib( EAttFontUnderline );
+    iRichTextLinkFormat.iFontPresentation.iUnderline = EUnderlineOn;
+    iRichTextLinkFormatMask.SetAttrib( EAttColor );
+    iRichTextLinkFormat.iFontPresentation.iTextColor =
+        NMRColorManager::Color(
+                NMRColorManager::EMRCutCopyPasteHighlightColor );
     }
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::DrawRightClickIconL
+// CESMRRichTextViewer::HighlightLinkL
 // -----------------------------------------------------------------------------
 //
-void CESMRRichTextViewer::DrawRightClickIconL(
-		const CESMRRichTextLink& aLink ) const
+void CESMRRichTextViewer::HighlightLinkL(const CESMRRichTextLink& aLink )
     {
     FUNC_LOG;
-    TTmDocPosSpec posSpec;
-    TTmPosInfo2 posInfo;
-
-    posSpec.iPos = aLink.StartPos ( )+ aLink.Length ( );
-    posSpec.iType = TTmDocPosSpec::ETrailing;
-
-    if (TextView()->FindDocPosL (posSpec, posInfo ) )
-        {
-        TPoint pt = posInfo.iEdge;
-        pt -= iActionMenuIcon->SizeInPixels ( );
-
-        pt.iY = pt.iY + KArrowUpperMargin;
-        pt.iX = Parent()->Rect().iBr.iX -
-                iActionMenuIcon->SizeInPixels().iWidth - KArrowRightMargin;
-        TRect dst(pt, iActionMenuIcon->SizeInPixels ( ));
-        TRect src(TPoint (0, 0 ), iActionMenuIcon->SizeInPixels ( ));
-
-        CWindowGc& gc = SystemGc ( );
-        gc.DrawBitmapMasked (dst, iActionMenuIcon, src, iActionMenuIconMask,
-                EFalse );
-        }
-    }
-
-// -----------------------------------------------------------------------------
-// CESMRRichTextViewer::HighlightLink
-// -----------------------------------------------------------------------------
-//
-void CESMRRichTextViewer::HighlightLink(const CESMRRichTextLink& aLink )
-    {
-    FUNC_LOG;
-    TInt error = KErrNone;
     TCursorSelection selection( aLink.StartPos(), aLink.StartPos() + aLink.Length() );
 
     // If TextView is not constructed yet.
     if ( !TextView() )
         {
-        TRAP( error, SetSelectionL( selection.iCursorPos, selection.iAnchorPos ) );
+        SetSelectionL( selection.iCursorPos, selection.iAnchorPos );
         }
     else
         {
         TextView()->SetPendingSelection( selection );
         }
 
-    if ( error == KErrNone )
-        {
-        TRAP( error, SetValueL( aLink ) );
-        if ( error != KErrNone )
-            {
-            CEikonEnv::Static()->// codescanner::eikonenvstatic
-                HandleError( error );
-            }
-        }
+    SetValueL( aLink );
+    ChangeMiddleSoftkeyL( aLink );
     }
 
 // -----------------------------------------------------------------------------
@@ -908,15 +832,7 @@
             }
         case CESMRRichTextLink::ETypeAttachment:
             {
-            // Set this as command observer.
-            // Commands from contact menu handler are
-            // processed in ProcessCommandL and forwarded
-            // as field command events
-            // <cmail>
-            //iCntMenuHdlr->SetCommandObserver( this );
-            // </cmail>
-            iCntMenuHdlr->SetValueL( aLink.Value(),
-            		CESMRContactMenuHandler::EValueTypeAttachment );
+
             break;
             }
         default:
@@ -1005,68 +921,42 @@
 // -----------------------------------------------------------------------------
 // CESMRRichTextViewer::CopyCurrentLinkToClipBoardL
 // -----------------------------------------------------------------------------
+//
 EXPORT_C void CESMRRichTextViewer::CopyCurrentLinkToClipBoardL() const
     {
     FUNC_LOG;
     const CESMRRichTextLink* link = GetSelectedLink();
-
-    if( link )
-        {
-    	HBufC* clipBoardText = GetLinkTextL(*link);
+    HBufC* clipBoardText = NULL;
 
-    	if ( clipBoardText )
-    	    {
-    	    CleanupStack::PushL( clipBoardText );
-    	    CClipboard* cb =
-            CClipboard::NewForWritingLC( CCoeEnv::Static()->FsSession() );
-            cb->StreamDictionary().At( KClipboardUidTypePlainText );
-            CPlainText* plainText = CPlainText::NewL();
-            CleanupStack::PushL( plainText );
-            plainText->InsertL( 0 , *clipBoardText);
-            plainText->CopyToStoreL( cb->Store(),
-                    cb->StreamDictionary(), 0, plainText->DocumentLength());
-            CleanupStack::PopAndDestroy( plainText );
-            cb->CommitL();
-            CleanupStack::PopAndDestroy( cb );
-            CleanupStack::PopAndDestroy( clipBoardText );
-    	    }
-        }
-    }
+    if ( link )
+    	{
+    	clipBoardText = GetLinkTextLC( *link );
+    	}
 
-// -----------------------------------------------------------------------------
-// CESMRRichTextViewer::CopyCurrentLinkValueToClipBoardL
-// -----------------------------------------------------------------------------
-EXPORT_C void CESMRRichTextViewer::CopyCurrentLinkValueToClipBoardL() const
-    {
-    FUNC_LOG;
-    const CESMRRichTextLink* link = GetSelectedLink();
-
-    if( link )
+    if ( clipBoardText )
         {
-    	TDesC& clipBoardText = link->Value();
-
-	    CClipboard* cb =
+        CClipboard* cb =
         CClipboard::NewForWritingLC( CCoeEnv::Static()->FsSession() );
         cb->StreamDictionary().At( KClipboardUidTypePlainText );
         CPlainText* plainText = CPlainText::NewL();
         CleanupStack::PushL( plainText );
-        plainText->InsertL( 0 , clipBoardText);
+        plainText->InsertL( 0 , *clipBoardText);
         plainText->CopyToStoreL( cb->Store(),
-                cb->StreamDictionary(), 0, plainText->DocumentLength());
+        		cb->StreamDictionary(), 0, plainText->DocumentLength());
         CleanupStack::PopAndDestroy( plainText );
         cb->CommitL();
         CleanupStack::PopAndDestroy( cb );
+        CleanupStack::PopAndDestroy( clipBoardText );
         }
     }
 
-
 // -----------------------------------------------------------------------------
 // CESMRRichTextViewer::ResetActionMenu
 // -----------------------------------------------------------------------------
 EXPORT_C void CESMRRichTextViewer::ResetActionMenuL() const // codescanner::LFunctionCantLeave
     {
     FUNC_LOG;
-    if(iCntMenuHdlr)
+    if ( iCntMenuHdlr )
         {
         iCntMenuHdlr->Reset();
         }
@@ -1095,7 +985,6 @@
     const CESMRRichTextLink* link = GetSelectedLink();
     if ( link )
         {
-        iActionMenuOpen = ETrue;
         switch ( link->TriggerKey() )
             {
             case CESMRRichTextLink::ETriggerKeyRight:
@@ -1103,7 +992,7 @@
                 if ( !iLinkObserver ||
                      !iLinkObserver->HandleRichTextLinkSelection(link) )
                     {
-                    iCntMenuHdlr->ShowActionMenuL();
+                    ShowContextMenuL();
                     }
                 linkSelected = ETrue;
                 break;
@@ -1111,7 +1000,7 @@
             case CESMRRichTextLink::ETriggerKeyOk:
                 {
                 if (iLinkObserver &&
-                    iLinkObserver->HandleRichTextLinkSelection (link ) )
+                    iLinkObserver->HandleRichTextLinkSelection( link ) )
                     {
                     linkSelected = ETrue;
                     }
@@ -1122,13 +1011,11 @@
                 break;
                 }
             }
-        iActionMenuOpen = EFalse;
         }
 
     return linkSelected;
     }
 
-
 // -----------------------------------------------------------------------------
 // CESMRRichTextViewer::ProcessCommandL
 // -----------------------------------------------------------------------------
@@ -1157,101 +1044,198 @@
     FUNC_LOG;
     CEikRichTextEditor::ActivateL();
 
-    // Make sure correct font color is in use.
-    SetFontColorL( IsFocused() );
-
     // CEikEdwin::ActivateL removes selection, re-set highlight
     // if focused and there's a selected link.
-    if ( IsFocused() && GetSelectedLink() )
+    const CESMRRichTextLink* link = GetSelectedLink();
+    if ( link && IsFocused() )
         {
-        HighlightLink( *GetSelectedLink() );
+        HighlightLinkL( *link );
         DrawDeferred();
         }
     }
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::HandlePointerEventL
+// CESMRRichTextViewer::ContactActionQueryComplete
 // -----------------------------------------------------------------------------
 //
-void CESMRRichTextViewer::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+void CESMRRichTextViewer::ContactActionQueryComplete()
     {
-    TBool linkTapped( EFalse );
-    CESMRRichTextLink* link = NULL;
-    // fetch the current line number:
-    TInt currentLineNumber = TextLayout()->GetLineNumber( CursorPos() );
-    // find out tapped position
-    TPoint touchPoint = aPointerEvent.iPosition;
-
-    TInt tappedPos = TextView()->XyPosToDocPosL( touchPoint );
-    for (TInt i = 0; i<iLinkList.Count(); i++)
+    FUNC_LOG;
+    if ( iOpenActionMenu )
         {
-        link = iLinkList[ i ];
-        TInt linkStart = link->StartPos();
-        TInt linkEnd = link->StartPos() + link->Length() - 1;
-        if ( tappedPos >= linkStart && tappedPos <= linkEnd )
-            {
-            // link tapped
-            linkTapped = ETrue;
-            iCurrentLinkIndex = i;
-            break;
-            }
+        // Activate link as actions have been discovered
+        TRAP_IGNORE(  LinkSelectedL() );
         }
 
-    if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+    // Reset menu observer
+    iCntMenuHdlr->SetContactMenuObserver( NULL );
+    iOpenActionMenu = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::ShowContextMenuL
+// -----------------------------------------------------------------------------
+//
+void CESMRRichTextViewer::ShowContextMenuL()
+    {
+    FUNC_LOG;
+    iOpenActionMenu = EFalse;
+    ProcessCommandL( EAknSoftkeyContextOptions );
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::GetLinkAreaL
+// -----------------------------------------------------------------------------
+//
+void CESMRRichTextViewer::GetLinkAreaL(
+        TRegion& aRegion,
+        const CESMRRichTextLink& aLink ) const
+    {
+    FUNC_LOG;
+    TTmDocPosSpec posSpec;
+    TTmPosInfo2 posInfo;
+
+    posSpec.iPos = aLink.StartPos();
+    posSpec.iType = TTmDocPosSpec::ELeading;
+
+    aRegion.Clear();
+
+    if ( TextView()->FindDocPosL( posSpec, posInfo ) )
         {
-        if ( linkTapped )
-            {
-            // tactile feedback
-            MTouchFeedback* feedback = MTouchFeedback::Instance();
-            if ( feedback )
-                {
-                feedback->InstantFeedback( this, ETouchFeedbackBasic );
-                }
+        TRect linkRect( 0, 0, 0, 0 );
+
+        // Create link surrounding rectangle
+        HBufC* text = GetLinkTextLC( aLink );
+        TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth(
+                *iFont,
+                *text,
+                CFont::TMeasureTextInput::EFVisualOrder );
 
-            TPointerEvent pointerEvent = aPointerEvent;
-            pointerEvent.iParentPosition = pointerEvent.iPosition
-                + DrawableWindow()->AbsPosition();
-            iLongTapDetector->PointerEventL( pointerEvent );
-            HighlightLink( *link );
-            if ( Parent() )
+        TPoint tl( posInfo.iEdge );
+
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // move top left x to end of text
+            tl.iX -= textWidth;
+            }
+
+        tl.iY -= iFont->FontMaxAscent();
+        TPoint br( tl.iX + textWidth, tl.iY + iFont->FontMaxHeight() );
+
+        TRect rect( Rect() );
+
+        while ( ( tl.iX < rect.iTl.iX || br.iX > rect.iBr.iX )
+                && !aRegion.CheckError() )
+            {
+            // Link on multiple lines
+
+            tl.iX = Max( rect.iTl.iX, tl.iX );
+            br.iX = Min( br.iX, rect.iBr.iX );
+            linkRect.SetRect( tl, br );
+            aRegion.AddRect( linkRect );
+
+            TPtrC remainder( text->Mid( posSpec.iPos - aLink.StartPos() ) );
+            TInt numChars = iFont->TextCount( remainder,
+                                              linkRect.Width() );
+            posSpec.iPos += numChars;
+            remainder.Set( remainder.Mid( numChars) );
+
+            if ( TextView()->FindDocPosL( posSpec, posInfo ) )
                 {
-                Parent()->DrawDeferred();
-                }
-            else
-                {
-                DrawDeferred();
+                textWidth = AknBidiTextUtils::MeasureTextBoundsWidth(
+                                *iFont,
+                                remainder,
+                                CFont::TMeasureTextInput::EFVisualOrder );
+
+                tl = posInfo.iEdge;
+
+                if ( AknLayoutUtils::LayoutMirrored() )
+                    {
+                    // move top left x to end of text
+                    tl.iX -= textWidth;
+                    }
+
+                tl.iY -= iFont->FontMaxAscent();
+                br.SetXY( tl.iX + textWidth, tl.iY + iFont->FontMaxHeight() );
                 }
             }
-        }
-    else
-        {
-        TPointerEvent pointerEvent = aPointerEvent;
-        pointerEvent.iParentPosition = pointerEvent.iPosition
-            + DrawableWindow()->AbsPosition();
-        iLongTapDetector->PointerEventL( pointerEvent );
 
-        if ( aPointerEvent.iType  == TPointerEvent::EButton1Up )
-            {
-            if ( linkTapped && !iActionMenuOpen )
-                {
-                // tapped highlighted field, execute action
-                LinkSelectedL();
-                }
-            }
+        linkRect.SetRect( tl, br );
+        aRegion.AddRect( linkRect );
+
+        CleanupStack::PopAndDestroy( text );
         }
     }
 
 // -----------------------------------------------------------------------------
-// CESMRRichTextViewer::HandleLongTapEventL
+// CESMRRichTextViewer::ChangeMiddleSoftkeyL
+// -----------------------------------------------------------------------------
+//
+void CESMRRichTextViewer::ChangeMiddleSoftkeyL( const CESMRRichTextLink& aLink )
+    {
+    FUNC_LOG;
+    CESMRField* field = static_cast< CESMRField* >( Parent() );
+
+    if ( field )
+        {
+        field->ChangeMiddleSoftKeyL( aLink.MSKCommand(), aLink.MSKText() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRichTextViewer::UpdateViewL
 // -----------------------------------------------------------------------------
 //
-void CESMRRichTextViewer::HandleLongTapEventL( const TPoint& /*aPenEventLocation*/,
-                                              const TPoint& /*aPenEventScreenLocation*/ )
+void CESMRRichTextViewer::UpdateViewL( const TKeyEvent &aKeyEvent )
     {
-    if ( !iActionMenuOpen )
+    FUNC_LOG;
+    const CESMRRichTextLink* selectedLink = GetSelectedLink();
+
+    if( !selectedLink )
+        {
+        return;
+        }
+
+    RRegion linkRegion;
+    CleanupClosePushL( linkRegion );
+
+    GetLinkAreaL( linkRegion, *selectedLink );
+    TRect linkRect = linkRegion.BoundingRect();
+
+    CleanupStack::PopAndDestroy( &linkRegion );
+
+    TRect viewableAreaRect = iObserver->ViewableAreaRect();
+
+
+    switch ( aKeyEvent.iCode )
         {
-        LinkSelectedL();
+        case EKeyLeftArrow:
+        case EKeyUpArrow:
+            {
+            if( linkRect.iTl.iY < viewableAreaRect.iTl.iY )
+                {
+                // Move fields down
+                iObserver->RePositionFields(
+                        -( linkRect.iTl.iY - viewableAreaRect.iTl.iY ) );
+                }
+
+            break;
+            }
+        case EKeyRightArrow:
+        case EKeyDownArrow:
+            {
+            if( linkRect.iBr.iY > viewableAreaRect.iBr.iY )
+                {
+                // Move fields up
+                iObserver->RePositionFields(
+                        -( linkRect.iBr.iY - viewableAreaRect.iBr.iY ) );
+                }
+            break;
+            }
+        default:
+            break;
         }
     }
+
 // EOF