meetingrequest/mrgui/mrfieldbuildercommon/src/cesmrrichtextviewer.cpp
branchRCL_3
changeset 25 3533d4323edc
equal deleted inserted replaced
24:d189ee25cf9d 25:3533d4323edc
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 *  Description : CEikRichTextEditor based Rich Text viewer
       
    15 *  Version     : %version: e002sa33#45.3 %
       
    16 *
       
    17 */
       
    18 
       
    19 #include "cesmrrichtextviewer.h"
       
    20 
       
    21 #include "mesmrlistobserver.h"// SCROLLING_MOD: List observer header
       
    22 #include "esmrconfig.hrh"
       
    23 #include "esmrhelper.h"
       
    24 #include "cesmrfieldcommandevent.h"
       
    25 #include "mesmrfieldeventqueue.h"
       
    26 #include "cesmrrichtextlink.h"
       
    27 #include "cesmrcontactmenuhandler.h"
       
    28 #include "nmrbitmapmanager.h"
       
    29 #include "nmrcolormanager.h"
       
    30 #include "esmrfieldbuilderdef.h"
       
    31 #include "cesmrfield.h"
       
    32 
       
    33 #include <esmrgui.rsg>
       
    34 #include <commonphoneparser.h>
       
    35 #include <finditemengine.h>
       
    36 #include <txtrich.h>
       
    37 #include <AknsUtils.h>
       
    38 #include <AknBidiTextUtils.h>
       
    39 #include <AknUtils.h>
       
    40 #include <eikenv.h>
       
    41 #include <data_caging_path_literals.hrh>
       
    42 #include <baclipb.h> // for clipboard copy
       
    43 #include <txtclipboard.h>
       
    44 
       
    45 // DEBUG
       
    46 #include "emailtrace.h"
       
    47 
       
    48 // Unnamed namespace for local definitions
       
    49 namespace{ // codescanner::namespace
       
    50 
       
    51 #ifdef _DEBUG
       
    52     enum TPanic
       
    53         {
       
    54         EParaFormatNotInitialised = 1
       
    55         };
       
    56     void Panic( TPanic aPanic )
       
    57         {
       
    58         _LIT( KCategory, "CESMRRichTextViewer" );
       
    59         User::Panic( KCategory(), aPanic );
       
    60         }
       
    61 #endif // DEBUG
       
    62 
       
    63 // Side margin in twips, needed because not possible to set it in pixels
       
    64 const TInt KDefaultTextSideMargin( 1 );
       
    65 
       
    66 }//namespace
       
    67 
       
    68 // ======== MEMBER FUNCTIONS ========
       
    69 
       
    70 // -----------------------------------------------------------------------------
       
    71 // CESMRRichTextViewer::NewL
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 EXPORT_C CESMRRichTextViewer* CESMRRichTextViewer::NewL(
       
    75         const CCoeControl* aParent)
       
    76     {
       
    77     FUNC_LOG;
       
    78     CESMRRichTextViewer* self = new (ELeave) CESMRRichTextViewer;
       
    79     CleanupStack::PushL ( self );
       
    80     self->ConstructL( aParent );
       
    81     CleanupStack::Pop ( self );
       
    82     return self;
       
    83     }
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // CESMRRichTextViewer::~CESMRRichTextViewer
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 EXPORT_C CESMRRichTextViewer::~CESMRRichTextViewer( )
       
    90     {
       
    91     FUNC_LOG;
       
    92     iLinkList.ResetAndDestroy ( );
       
    93     iESMRStatic.Close ( );
       
    94     delete iParaFormat;
       
    95     }
       
    96 
       
    97 // -----------------------------------------------------------------------------
       
    98 // CESMRRichTextViewer::PositionChanged
       
    99 // -----------------------------------------------------------------------------
       
   100 //
       
   101 EXPORT_C void CESMRRichTextViewer::PositionChanged( )
       
   102     {
       
   103     FUNC_LOG;
       
   104     CTextView* view = TextView ( );
       
   105     if ( view )
       
   106         {
       
   107         view->SetViewRect ( Rect ( ) );
       
   108         }
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // CESMRRichTextViewer::FocusChanged
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 EXPORT_C void CESMRRichTextViewer::FocusChanged(
       
   116         TDrawNow aDrawNow )
       
   117     {
       
   118     FUNC_LOG;
       
   119     CEikRichTextEditor::FocusChanged( aDrawNow );
       
   120     if ( !TextLayout() || !TextView() )
       
   121         {
       
   122         // not constructed totally:
       
   123         return;
       
   124         }
       
   125 
       
   126     // Check the current selection.
       
   127     // If a link has been highlighted, don't change it.
       
   128     TCursorSelection selection = Selection();
       
   129 
       
   130     // Gaining focus
       
   131     if ( IsFocused()
       
   132          && iLinkList.Count() > 0
       
   133          && ( selection.Length() == 0 ) )
       
   134         {
       
   135         // We need the field indexes, cast required
       
   136         CESMRField* parent = static_cast< CESMRField* >( Parent() );
       
   137 
       
   138         iCntMenuHdlr->SetContactMenuObserver( this );
       
   139         // Focus coming from above ...
       
   140         if( parent->CurrentItemIndex() > parent->PreItemIndex() )
       
   141             {
       
   142             // ... Highlight first link
       
   143             TRAP_IGNORE( HighlightLinkL( *( iLinkList[0] ) ) );
       
   144             }
       
   145         // Focus coming from below ...
       
   146         else
       
   147             {
       
   148             // ... Highlight last link
       
   149             TRAP_IGNORE( HighlightLinkL( *( iLinkList[iLinkList.Count() - 1 ] ) ) );
       
   150             }
       
   151         DrawDeferred();
       
   152         }
       
   153 
       
   154     // Losing focus
       
   155     if ( !IsFocused() )
       
   156         {
       
   157         TRAP_IGNORE(
       
   158                 SetSelectionL( CursorPos(), CursorPos() );
       
   159                 ResetActionMenuL();
       
   160                 );
       
   161         }
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CESMRRichTextViewer::FindTextLinkBetweenNextScrollArea
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 TInt CESMRRichTextViewer::FindTextLinkBetweenNextScrollArea(
       
   169         TInt aStartRow,
       
   170         TInt aEndRow,
       
   171         TCursorPosition::TMovementType aDirection)
       
   172     {
       
   173     FUNC_LOG;
       
   174     TInt linkRow(KErrNotFound);
       
   175 
       
   176     // fetch the line number where the next link is located:
       
   177     if ( aDirection == TCursorPosition::EFLineDown )
       
   178         {
       
   179         for (TInt i = 0; i<iLinkList.Count(); i++)
       
   180             {
       
   181             linkRow = ValidLinkForFocusing(i, aDirection, aStartRow, aEndRow);
       
   182             if ( linkRow != KErrNotFound)
       
   183                 {
       
   184                 return linkRow;
       
   185                 }
       
   186             }
       
   187         }
       
   188     else
       
   189         for (TInt i = iLinkList.Count()-1; i>=0 ; i--)
       
   190             {
       
   191             linkRow = ValidLinkForFocusing(i, aDirection, aStartRow, aEndRow);
       
   192             if ( linkRow != KErrNotFound)
       
   193                 {
       
   194                 return linkRow;
       
   195                 }
       
   196             }
       
   197 
       
   198     return linkRow;
       
   199     }
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CESMRRichTextViewer::ValidLinkForFocusing
       
   203 // -----------------------------------------------------------------------------
       
   204 //
       
   205 TInt CESMRRichTextViewer::ValidLinkForFocusing(
       
   206         TInt aIndex,
       
   207         TCursorPosition::TMovementType aDirection,
       
   208         TInt aStartRow,
       
   209         TInt aEndRow )
       
   210     {
       
   211     FUNC_LOG;
       
   212 
       
   213     if ( iLinkList.Count() > aIndex)
       
   214 	    {
       
   215 	    TInt currPos( KErrNotFound );
       
   216         const CESMRRichTextLink* currentLink = GetSelectedLink();
       
   217         if ( currentLink )
       
   218             {
       
   219             currPos = currentLink->StartPos();
       
   220             }
       
   221 
       
   222         TInt pos = iLinkList[ aIndex ]->StartPos();
       
   223 
       
   224 	    TInt checkRow = TextLayout()->GetLineNumber( pos );
       
   225 
       
   226 	    if ( checkRow >= aStartRow && checkRow <= aEndRow )
       
   227 	        {
       
   228 	        if ( aDirection == TCursorPosition::EFLineDown &&
       
   229 	             pos > currPos ||
       
   230 	             aDirection == TCursorPosition::EFLineUp &&
       
   231 	             ( pos < currPos || currPos == KErrNotFound ) )
       
   232 	            {
       
   233 	            // link found between next scroll area.
       
   234 	            return checkRow;
       
   235 	            }
       
   236 	        }
       
   237 	    }
       
   238     return KErrNotFound;
       
   239     }
       
   240 
       
   241 // -----------------------------------------------------------------------------
       
   242 // CESMRRichTextViewer::OfferKeyEventL
       
   243 // -----------------------------------------------------------------------------
       
   244 //
       
   245 EXPORT_C TKeyResponse CESMRRichTextViewer::OfferKeyEventL(
       
   246         const TKeyEvent &aKeyEvent,
       
   247         TEventCode aType )
       
   248     {
       
   249     FUNC_LOG;
       
   250     TKeyResponse response( EKeyWasNotConsumed );
       
   251 
       
   252     // Handle only event keys.
       
   253     if( aType != EEventKey )
       
   254         {
       
   255         return response;
       
   256         }
       
   257 
       
   258     /*
       
   259      * Handles scrolling between rich text links.
       
   260      */
       
   261     const CESMRRichTextLink* selectedLink = GetSelectedLink();
       
   262     TInt linkCount = iLinkList.Count();
       
   263 
       
   264     // If a link is selected, it means that we are operating within
       
   265     // the field and can move focus between the links.
       
   266     if( linkCount && selectedLink )
       
   267         {
       
   268         TInt selectedLinkIndex = iLinkList.Find( selectedLink );
       
   269 
       
   270         switch ( aKeyEvent.iCode )
       
   271             {
       
   272             case EKeyLeftArrow:
       
   273             case EKeyUpArrow:
       
   274                 {
       
   275                 // If possible and exists ...
       
   276                 if( selectedLinkIndex > 0 &&
       
   277                         selectedLinkIndex < linkCount )
       
   278                     {
       
   279                     // ...Highlight previous link.
       
   280                     HighlightLinkL( *( iLinkList[ selectedLinkIndex - 1 ] ) );
       
   281                     response = EKeyWasConsumed;
       
   282 
       
   283                     // View update required, for example if link is out of
       
   284                     // viewable area.
       
   285                     UpdateViewL( aKeyEvent );
       
   286                     }
       
   287 
       
   288                 break;
       
   289                 }
       
   290             case EKeyRightArrow:
       
   291             case EKeyDownArrow:
       
   292                 {
       
   293                 // If possible and exists ...
       
   294                 if( selectedLinkIndex + 1 < linkCount &&
       
   295                         selectedLinkIndex >= 0 )
       
   296                     {
       
   297                     // ...Highlight next link.
       
   298                     HighlightLinkL( *( iLinkList[ selectedLinkIndex + 1 ] ) );
       
   299                     response = EKeyWasConsumed;
       
   300 
       
   301                     // View update required, for example if link is out of
       
   302                     // viewable area.
       
   303                     UpdateViewL( aKeyEvent );
       
   304                     }
       
   305 
       
   306                 break;
       
   307                 }
       
   308             case EKeyDevice3: // Selection key
       
   309             case EKeyEnter:
       
   310                 {
       
   311                 LinkSelectedL();
       
   312                 response = EKeyWasConsumed;
       
   313                 break;
       
   314                 }
       
   315             default:
       
   316                 break;
       
   317             }
       
   318         }
       
   319 
       
   320     return response;
       
   321     }
       
   322 
       
   323 // -----------------------------------------------------------------------------
       
   324 // CESMRRichTextViewer::HandlePointerEventL
       
   325 // -----------------------------------------------------------------------------
       
   326 //
       
   327 void CESMRRichTextViewer::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   328     {
       
   329     if ( Rect().Contains( aPointerEvent.iPosition) )
       
   330         {
       
   331         TBool linkFound( EFalse );
       
   332 
       
   333         switch ( aPointerEvent.iType )
       
   334             {
       
   335             case TPointerEvent::EButton1Down:
       
   336                 {
       
   337                 RRegion linkArea;
       
   338                 CleanupClosePushL( linkArea );
       
   339 
       
   340                 // Find matching link
       
   341                 TInt count = iLinkList.Count();
       
   342 
       
   343                 for ( TInt i = 0; i < count; ++i )
       
   344                     {
       
   345                     CESMRRichTextLink* link = iLinkList[ i ];
       
   346                     GetLinkAreaL( linkArea, *link );
       
   347 
       
   348                     if ( linkArea.Contains( aPointerEvent.iPosition ) )
       
   349                         {
       
   350                         if ( link != GetSelectedLink() )
       
   351                             {
       
   352                             iCntMenuHdlr->Reset();
       
   353                             iCntMenuHdlr->SetContactMenuObserver( this );
       
   354 
       
   355                             HighlightLinkL( *link );
       
   356                             DrawDeferred();
       
   357                             }
       
   358 
       
   359                         linkFound = ETrue;
       
   360                         break;
       
   361                         }
       
   362                     }
       
   363 
       
   364                 CleanupStack::PopAndDestroy( &linkArea );
       
   365 
       
   366                 break;
       
   367                 }
       
   368 
       
   369             case TPointerEvent::EButton1Up:
       
   370                 {
       
   371                 const CESMRRichTextLink* link = GetSelectedLink();
       
   372 
       
   373                 TBool menuAvailable = iCntMenuHdlr->OptionsMenuAvailable();
       
   374 
       
   375                 if ( link
       
   376                      && ( menuAvailable
       
   377                      || link->Type() == CESMRRichTextLink::ETypeLocationUrl
       
   378                      || link->Type() == CESMRRichTextLink::ETypeAttachment
       
   379                      || link->Type() == CESMRRichTextLink::ETypeShowAll ) )
       
   380                     {
       
   381                     linkFound = ETrue;
       
   382 
       
   383                     LinkSelectedL();
       
   384                     }
       
   385                 else if ( link && !menuAvailable )
       
   386                     {
       
   387                     linkFound = ETrue;
       
   388                     iOpenActionMenu = ETrue;
       
   389                     }
       
   390                 break;
       
   391                 }
       
   392             default:
       
   393                 {
       
   394                 break;
       
   395                 }
       
   396             }
       
   397 
       
   398         if ( !linkFound && TPointerEvent::EDrag != aPointerEvent.iType )
       
   399             {
       
   400             // Tap on plain text
       
   401             TextView()->ClearSelectionL();
       
   402             ResetActionMenuL();
       
   403             DrawDeferred();
       
   404             }
       
   405 
       
   406         }
       
   407 
       
   408     }
       
   409 
       
   410 // -----------------------------------------------------------------------------
       
   411 // CESMRRichTextViewer::SetMargins
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 EXPORT_C void CESMRRichTextViewer::SetMargins( TInt sMargin )
       
   415 	{
       
   416 	// Set new value for left and right margins
       
   417     TextView()->SetMarginWidths( sMargin ,0);
       
   418 	}
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // CESMRRichTextViewer::SetTextL
       
   422 // -----------------------------------------------------------------------------
       
   423 //
       
   424 EXPORT_C void CESMRRichTextViewer::SetTextL(
       
   425         const TDesC* aText,
       
   426         TBool aSearchLinks )
       
   427     {
       
   428     FUNC_LOG;
       
   429 
       
   430     iLinkList.ResetAndDestroy();
       
   431 
       
   432     TextView()->SetMarginWidths( KDefaultTextSideMargin ,0);
       
   433 
       
   434     // Clear edwin text
       
   435     CEikEdwin::SetCursorPosL( 0, EFalse );
       
   436     CEikRichTextEditor::SetTextL( &KNullDesC );
       
   437     RichText()->Reset();
       
   438 
       
   439     // text lenght plus one to ensure the formatting
       
   440     // used is full, not band formatting.
       
   441     SetUpperFullFormattingLength( aText->Length() + 1 );
       
   442 
       
   443     // Set new edwin text
       
   444     CEikEdwin::SetTextLimit( aText->Length ( ) );
       
   445     CEikRichTextEditor::SetTextL( aText );
       
   446 
       
   447     //Make sure cursor is invisible and selection visible
       
   448     TextView()->SetCursorVisibilityL(
       
   449             TCursor::EFCursorInvisible,
       
   450             TCursor::EFCursorInvisible );
       
   451     TextView()->SetSelectionVisibilityL( ETrue );
       
   452 
       
   453     // Search text for links (highlights)
       
   454     if ( aSearchLinks )
       
   455         {
       
   456         SearchLinksL( *aText );
       
   457         // find first link.
       
   458         FindTextLinkBetweenNextScrollArea(0, KMaxAddressFieldLines, TCursorPosition::EFLineDown);
       
   459         }
       
   460     }
       
   461 
       
   462 // -----------------------------------------------------------------------------
       
   463 // CESMRRichTextViewer::SetLinkObserver
       
   464 // -----------------------------------------------------------------------------
       
   465 //
       
   466 EXPORT_C void CESMRRichTextViewer::SetLinkObserver(
       
   467         MESMRRichTextObserver* aLinkObserver )
       
   468     {
       
   469     FUNC_LOG;
       
   470     iLinkObserver = aLinkObserver;
       
   471     }
       
   472 
       
   473 // -----------------------------------------------------------------------------
       
   474 // CESMRRichTextViewer::AddLinkL
       
   475 // -----------------------------------------------------------------------------
       
   476 //
       
   477 EXPORT_C void CESMRRichTextViewer::AddLinkL( CESMRRichTextLink* aLink )
       
   478     {
       
   479     FUNC_LOG;
       
   480     // If this is first link, set it highlighted
       
   481     TBool highlight = IsFocused()&& ( iLinkList.Count() == 0 );
       
   482 
       
   483     // Reserve space for new link
       
   484     iLinkList.ReserveL( iLinkList.Count() + 1 );
       
   485 
       
   486     RichText()->ApplyCharFormatL( iRichTextLinkFormat,
       
   487                                   iRichTextLinkFormatMask,
       
   488                                   aLink->StartPos(),
       
   489                                   aLink->Length() );
       
   490 
       
   491     // Append aLink to link list. Space has been reserved, so this cannot fail.
       
   492     iLinkList.AppendL( aLink );
       
   493 
       
   494     if ( highlight )
       
   495         {
       
   496         HighlightLinkL( *aLink );
       
   497         }
       
   498     }
       
   499 
       
   500 // -----------------------------------------------------------------------------
       
   501 // CESMRRichTextViewer::InsertLinkL
       
   502 // -----------------------------------------------------------------------------
       
   503 //
       
   504 EXPORT_C void CESMRRichTextViewer::InsertLinkL( CESMRRichTextLink* aLink,
       
   505                                                 TInt aPosition )
       
   506     {
       
   507     FUNC_LOG;
       
   508     // If this is first link, set it highlighted
       
   509     TBool highlight = IsFocused()&& ( iLinkList.Count() == 0 );
       
   510 
       
   511     // Reserve space for new link
       
   512     iLinkList.ReserveL( iLinkList.Count() + 1 );
       
   513 
       
   514     RichText()->ApplyCharFormatL( iRichTextLinkFormat,
       
   515                                   iRichTextLinkFormatMask,
       
   516                                   aLink->StartPos(),
       
   517                                   aLink->Length() );
       
   518 
       
   519     // Insert aLink to link list. Space has been reserved, so this cannot fail.
       
   520     // InsertL panics if aPosition is illegal.
       
   521     iLinkList.InsertL( aLink, aPosition );
       
   522 
       
   523     if ( highlight )
       
   524         {
       
   525         HighlightLinkL( *aLink );
       
   526         }
       
   527     }
       
   528 
       
   529 // -----------------------------------------------------------------------------
       
   530 // CESMRRichTextViewer::GetSelectedLink
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 EXPORT_C const CESMRRichTextLink* CESMRRichTextViewer::GetSelectedLink( ) const
       
   534     {
       
   535     FUNC_LOG;
       
   536     CESMRRichTextLink* link( NULL );
       
   537 
       
   538     TCursorSelection currentSelection = Selection();
       
   539 
       
   540     for ( TInt i = 0; i < iLinkList.Count(); ++i )
       
   541         {
       
   542         CESMRRichTextLink* tempLink = iLinkList[i];
       
   543         TInt startPos = tempLink->StartPos();
       
   544         TInt length = tempLink->Length();
       
   545 
       
   546         TCursorSelection linkSelection( startPos, startPos + length );
       
   547 
       
   548         if( currentSelection.iCursorPos == linkSelection.iCursorPos &&
       
   549                 currentSelection.iAnchorPos == linkSelection.iAnchorPos )
       
   550             {
       
   551             link = tempLink;
       
   552             break;
       
   553             }
       
   554         }
       
   555 
       
   556     return link;
       
   557     }
       
   558 
       
   559 // -----------------------------------------------------------------------------
       
   560 // CESMRRichTextViewer::GetLinkTextL
       
   561 // -----------------------------------------------------------------------------
       
   562 //
       
   563 EXPORT_C HBufC* CESMRRichTextViewer::GetLinkTextLC(
       
   564         const CESMRRichTextLink& aLink ) const
       
   565     {
       
   566     FUNC_LOG;
       
   567     return RichText()->Read( aLink.StartPos(), aLink.Length() ).AllocLC();
       
   568     }
       
   569 
       
   570 // -----------------------------------------------------------------------------
       
   571 // CESMRRichTextViewer::CESMRRichTextViewer
       
   572 // -----------------------------------------------------------------------------
       
   573 //
       
   574 EXPORT_C void CESMRRichTextViewer::SetListObserver(
       
   575         MESMRListObserver* aObserver )
       
   576     {
       
   577     FUNC_LOG;
       
   578     iObserver = aObserver;
       
   579     }
       
   580 
       
   581 // -----------------------------------------------------------------------------
       
   582 // CESMRRichTextViewer::RowHeight
       
   583 // -----------------------------------------------------------------------------
       
   584 //
       
   585 EXPORT_C TInt CESMRRichTextViewer::RowHeight()
       
   586     {
       
   587     FUNC_LOG;
       
   588     TInt bandHeight = TextLayout()->BandHeight();
       
   589     // Starts from zero, so let's increase the count by one.
       
   590     TInt lineNumberCount = TextLayout()->GetLineNumber( TextLength() ) + 1;
       
   591 
       
   592     return ( bandHeight / lineNumberCount );
       
   593     }
       
   594 
       
   595 // -----------------------------------------------------------------------------
       
   596 // CESMRRichTextViewer::LineCount
       
   597 // -----------------------------------------------------------------------------
       
   598 //
       
   599 EXPORT_C TInt CESMRRichTextViewer::LineCount()
       
   600     {
       
   601     FUNC_LOG;
       
   602 
       
   603     // First row is 0, so let's add one...
       
   604     return ( TextLayout()->GetLineNumber( TextLength() ) + 1 );
       
   605     }
       
   606 // -----------------------------------------------------------------------------
       
   607 // CESMRRichTextViewer::CurrentLineNumber
       
   608 // -----------------------------------------------------------------------------
       
   609 //
       
   610 EXPORT_C TInt CESMRRichTextViewer::CurrentLineNumber()
       
   611     {
       
   612     FUNC_LOG;
       
   613     // first line is zero, let's increase it by one
       
   614     return TextLayout()->GetLineNumber( CursorPos() ) + 1;
       
   615     }
       
   616 
       
   617 // -----------------------------------------------------------------------------
       
   618 // CESMRRichTextViewer::SetFontL
       
   619 // -----------------------------------------------------------------------------
       
   620 //
       
   621 EXPORT_C void CESMRRichTextViewer::SetFontL( const CFont* aFont )
       
   622     {
       
   623     FUNC_LOG;
       
   624     // iFont is stored for changing font color when losing or
       
   625     // gaining focus
       
   626     iFont = aFont;
       
   627     if ( !iParaFormat )
       
   628         {
       
   629         iParaFormat = new ( ELeave ) CParaFormat();
       
   630         }
       
   631 
       
   632     // All this required, otherwise the font loses its
       
   633     // antialiasing drawing.
       
   634     iParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingExactlyInPixels;
       
   635 
       
   636     iParaFormatMask.SetAttrib( EAttLineSpacing );
       
   637     iParaFormat->iHorizontalAlignment = CParaFormat::ELeftAlign;
       
   638     if ( AknLayoutUtils::LayoutMirrored() )
       
   639         {
       
   640         iParaFormat->iHorizontalAlignment = CParaFormat::ERightAlign;
       
   641         }
       
   642     iParaFormat->iVerticalAlignment = CParaFormat::ECenterAlign;
       
   643     iParaFormatMask.SetAttrib( EAttAlignment );
       
   644     iParaFormatMask.SetAttrib( EAttVerticalAlignment );
       
   645 
       
   646     iCharFormat.iFontSpec = iFont->FontSpecInTwips();
       
   647 
       
   648     iCharFormatMask.SetAttrib( EAttFontTypeface );
       
   649     iCharFormatMask.SetAttrib( EAttFontHeight );
       
   650     iCharFormatMask.SetAttrib( EAttFontPosture );
       
   651     iCharFormatMask.SetAttrib( EAttFontStrokeWeight );
       
   652 
       
   653     iCharFormat.iFontPresentation.iTextColor =
       
   654         NMRColorManager::Color( NMRColorManager::EMRMainAreaTextColor );
       
   655 
       
   656     iCharFormatMask.SetAttrib( EAttColor );
       
   657     }
       
   658 
       
   659 // -----------------------------------------------------------------------------
       
   660 // CESMRRichTextViewer::SetLineSpacingL
       
   661 // -----------------------------------------------------------------------------
       
   662 //
       
   663 EXPORT_C void CESMRRichTextViewer::SetLineSpacingL( TInt aLineSpacingInTwips )
       
   664     {
       
   665     __ASSERT_DEBUG( iParaFormat, Panic( EParaFormatNotInitialised ) );
       
   666     iParaFormatMask.SetAttrib( EAttLineSpacing );
       
   667     iParaFormatMask.SetAttrib( EAttLineSpacingControl );
       
   668     iParaFormat->iLineSpacingControl =
       
   669         CParaFormat::ELineSpacingExactlyInPixels;
       
   670 
       
   671     iParaFormat->iLineSpacingInTwips = aLineSpacingInTwips;
       
   672     }
       
   673 
       
   674 // -----------------------------------------------------------------------------
       
   675 // CESMRRichTextViewer::ApplyLayoutChanges
       
   676 // -----------------------------------------------------------------------------
       
   677 //
       
   678 EXPORT_C void CESMRRichTextViewer::ApplyLayoutChangesL()
       
   679     {
       
   680     __ASSERT_DEBUG( iParaFormat, Panic( EParaFormatNotInitialised ) );
       
   681     CRichText* richtext = RichText();
       
   682     TInt paraCount( richtext->ParagraphCount() );
       
   683     // Go through each paragraph and apply the same format
       
   684     for( TInt i = 0; i < paraCount; ++i  )
       
   685         {
       
   686         TInt paraLen( 0 );   // Length of paragraph
       
   687         TInt fiChPos( 0 );   // First character position of paragraph
       
   688         // Get the length of the paragraph
       
   689         fiChPos = richtext->CharPosOfParagraph( paraLen, i );
       
   690         richtext->ApplyParaFormatL(
       
   691                 iParaFormat, iParaFormatMask, fiChPos, paraLen );
       
   692         richtext->ApplyCharFormatL(
       
   693                 iCharFormat, iCharFormatMask, fiChPos, paraLen );
       
   694         }
       
   695     // This forces CEikEdwin::OnReformatL to notify observer
       
   696     // through HandleEdwinSizeEventL about changed size.
       
   697     // It is notified only if linecount changes.
       
   698     CEikEdwin::iNumberOfLines = 0;
       
   699     CEikEdwin::FormatTextL();
       
   700     }
       
   701 
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 // CESMRRichTextViewer::SetSelectedLink
       
   705 // -----------------------------------------------------------------------------
       
   706 //
       
   707 EXPORT_C void CESMRRichTextViewer::SetFocusLink( TInt aLinkIndex )
       
   708     {
       
   709     if ( ( aLinkIndex >= 0 ) && ( aLinkIndex < iLinkList.Count() ) )
       
   710         {
       
   711         TRAP_IGNORE( HighlightLinkL( *( iLinkList[aLinkIndex] ) ) );
       
   712         DrawDeferred();
       
   713         }
       
   714     }
       
   715 
       
   716 // -----------------------------------------------------------------------------
       
   717 // CESMRRichTextViewer::GetSelectedLink
       
   718 // -----------------------------------------------------------------------------
       
   719 //
       
   720 EXPORT_C TInt CESMRRichTextViewer::GetFocusLink( ) const
       
   721     {
       
   722     FUNC_LOG;
       
   723     // "-1" stand for no link be selected now.
       
   724     TInt linkIndex( KErrNotFound );
       
   725     if ( 0 == iLinkList.Count() )
       
   726         {
       
   727         return linkIndex;
       
   728         }
       
   729 
       
   730     TCursorSelection currentSelection = Selection();
       
   731 
       
   732     for ( TInt i = 0; i < iLinkList.Count(); ++i )
       
   733         {
       
   734         CESMRRichTextLink* tempLink = iLinkList[i];
       
   735         TInt startPos = tempLink->StartPos();
       
   736         TInt length = tempLink->Length();
       
   737 
       
   738         TCursorSelection linkSelection( startPos, startPos + length );
       
   739 
       
   740         if( currentSelection.iCursorPos == linkSelection.iCursorPos &&
       
   741                 currentSelection.iAnchorPos == linkSelection.iAnchorPos )
       
   742             {
       
   743             linkIndex = i;
       
   744             break;
       
   745             }
       
   746         }
       
   747 
       
   748     return linkIndex;
       
   749     }
       
   750 
       
   751 // -----------------------------------------------------------------------------
       
   752 // CESMRRichTextViewer::PointerEventOccuresOnALinkL
       
   753 // -----------------------------------------------------------------------------
       
   754 //
       
   755 EXPORT_C TBool CESMRRichTextViewer::PointerEventOccuresOnALinkL(
       
   756 		const TPointerEvent &aPointerEvent )
       
   757     {
       
   758     FUNC_LOG;
       
   759     TBool ret( EFalse );
       
   760 
       
   761     RRegion linkArea;
       
   762     CleanupClosePushL( linkArea );
       
   763 
       
   764     // Find matching link
       
   765     TInt count( iLinkList.Count() );
       
   766 
       
   767     for ( TInt i = 0; i < count; ++i )
       
   768         {
       
   769         CESMRRichTextLink* link = iLinkList[ i ];
       
   770         GetLinkAreaL( linkArea, *link );
       
   771 
       
   772         if ( linkArea.Contains( aPointerEvent.iPosition ) )
       
   773             {
       
   774             ret = ETrue;
       
   775             break;
       
   776             }
       
   777         }
       
   778 
       
   779     CleanupStack::PopAndDestroy( &linkArea );
       
   780 
       
   781     return ret;
       
   782     }
       
   783 
       
   784 
       
   785 // -----------------------------------------------------------------------------
       
   786 // CESMRRichTextViewer::CESMRRichTextViewer
       
   787 // -----------------------------------------------------------------------------
       
   788 //
       
   789 CESMRRichTextViewer::CESMRRichTextViewer( )
       
   790     {
       
   791     FUNC_LOG;
       
   792     }
       
   793 
       
   794 // -----------------------------------------------------------------------------
       
   795 // CESMRRichTextViewer::ConstructL
       
   796 // -----------------------------------------------------------------------------
       
   797 //
       
   798 void CESMRRichTextViewer::ConstructL(const CCoeControl* aParent)
       
   799     {
       
   800     FUNC_LOG;
       
   801 
       
   802     TInt flags = CEikEdwin::EReadOnly |
       
   803                  CEikEdwin::EResizable |
       
   804                  CEikEdwin::ENoAutoSelection |
       
   805                  CEikEdwin::EAvkonDisableCursor;
       
   806     if( !aParent )
       
   807         {
       
   808         flags |= CEikEdwin::EOwnsWindow;
       
   809         }
       
   810 
       
   811     CEikRichTextEditor::ConstructL( aParent, 1, 1, flags );
       
   812     SetSuppressBackgroundDrawing( ETrue );
       
   813 
       
   814     iESMRStatic.ConnectL();
       
   815     iCntMenuHdlr = &iESMRStatic.ContactMenuHandlerL();
       
   816     iRichTextLinkFormatMask.SetAttrib( EAttFontUnderline );
       
   817     iRichTextLinkFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   818     iRichTextLinkFormatMask.SetAttrib( EAttColor );
       
   819     iRichTextLinkFormat.iFontPresentation.iTextColor =
       
   820         NMRColorManager::Color(
       
   821                 NMRColorManager::EMRCutCopyPasteHighlightColor );
       
   822     }
       
   823 
       
   824 // -----------------------------------------------------------------------------
       
   825 // CESMRRichTextViewer::HighlightLinkL
       
   826 // -----------------------------------------------------------------------------
       
   827 //
       
   828 void CESMRRichTextViewer::HighlightLinkL(const CESMRRichTextLink& aLink )
       
   829     {
       
   830     FUNC_LOG;
       
   831     TCursorSelection selection( aLink.StartPos(), aLink.StartPos() + aLink.Length() );
       
   832 
       
   833     // If TextView is not constructed yet.
       
   834     if ( !TextView() )
       
   835         {
       
   836         SetSelectionL( selection.iCursorPos, selection.iAnchorPos );
       
   837         }
       
   838     else
       
   839         {
       
   840         TextView()->SetPendingSelection( selection );
       
   841         }
       
   842 
       
   843     SetValueL( aLink );
       
   844     ChangeMiddleSoftkeyL( aLink );
       
   845     }
       
   846 
       
   847 // -----------------------------------------------------------------------------
       
   848 // CESMRRichTextViewer::SetValueL
       
   849 // -----------------------------------------------------------------------------
       
   850 //
       
   851 void CESMRRichTextViewer::SetValueL( const CESMRRichTextLink& aLink )
       
   852     {
       
   853     FUNC_LOG;
       
   854     // Instantiate contact action menu for selected link
       
   855     switch ( aLink.Type() )
       
   856         {
       
   857         case CESMRRichTextLink::ETypeEmail:
       
   858             {
       
   859             iCntMenuHdlr->SetValueL( aLink.Value(),
       
   860             		CESMRContactMenuHandler::EValueTypeEmail );
       
   861             break;
       
   862             }
       
   863         case CESMRRichTextLink::ETypePhoneNumber:
       
   864             {
       
   865             iCntMenuHdlr->SetValueL( aLink.Value(),
       
   866             		CESMRContactMenuHandler::EValueTypePhoneNumber );
       
   867             break;
       
   868             }
       
   869         case CESMRRichTextLink::ETypeURL:
       
   870             {
       
   871             iCntMenuHdlr->SetValueL( aLink.Value(),
       
   872             		CESMRContactMenuHandler::EValueTypeURL );
       
   873             break;
       
   874             }
       
   875         case CESMRRichTextLink::ETypeAttachment:
       
   876             {
       
   877 
       
   878             break;
       
   879             }
       
   880         default:
       
   881             {
       
   882             break;
       
   883             }
       
   884         }
       
   885     }
       
   886 
       
   887 // -----------------------------------------------------------------------------
       
   888 // CESMRRichTextViewer::SearchLinksL
       
   889 // -----------------------------------------------------------------------------
       
   890 //
       
   891 void CESMRRichTextViewer::SearchLinksL(const TDesC& aText )
       
   892     {
       
   893     FUNC_LOG;
       
   894     // Search for emails, phone numbers and urls
       
   895     TInt searchCases = CFindItemEngine::EFindItemSearchMailAddressBin |
       
   896                        CFindItemEngine::EFindItemSearchPhoneNumberBin |
       
   897                        CFindItemEngine::EFindItemSearchURLBin;
       
   898 
       
   899     CFindItemEngine* itemEngine =
       
   900               CFindItemEngine::NewL ( aText,
       
   901                        ( CFindItemEngine::TFindItemSearchCase ) searchCases );
       
   902     CleanupStack::PushL (itemEngine );
       
   903 
       
   904     const CArrayFixFlat<CFindItemEngine::SFoundItem>
       
   905             * foundItems = itemEngine->ItemArray ( );
       
   906 
       
   907     // For each found item
       
   908     for (TInt i=0; i<foundItems->Count ( ); ++i )
       
   909         {
       
   910         // iItemType, iStartPos, iLength
       
   911         const CFindItemEngine::SFoundItem& item = foundItems->At (i );
       
   912         HBufC* valueBuf = aText.Mid (item.iStartPos, item.iLength ).AllocL ( );
       
   913         CleanupStack::PushL (valueBuf );
       
   914 
       
   915         CESMRRichTextLink::TType type = (CESMRRichTextLink::TType) -1;
       
   916         switch (item.iItemType )
       
   917             {
       
   918             case CFindItemEngine::EFindItemSearchMailAddressBin:
       
   919                 {
       
   920                 type = CESMRRichTextLink::ETypeEmail;
       
   921                 break;
       
   922                 }
       
   923             case CFindItemEngine::EFindItemSearchPhoneNumberBin:
       
   924                 {
       
   925                 type = CESMRRichTextLink::ETypePhoneNumber;
       
   926 
       
   927                 // patch the symbian level error , 10.120.22.141 this kind of url should not 
       
   928                 // be recognized to be a phone number.
       
   929                 TPtr phonePtr = valueBuf->Des ( );
       
   930                 if( phonePtr.Find(_L(".")) == KErrNotFound )
       
   931                 	{
       
   932                      CommonPhoneParser::ParsePhoneNumber (phonePtr,
       
   933                        CommonPhoneParser::EContactCardNumber );
       
   934                 	}
       
   935                 else
       
   936                 	{
       
   937                     type = (CESMRRichTextLink::TType) -1 ;
       
   938                     }
       
   939                 break;
       
   940                 }
       
   941             case CFindItemEngine::EFindItemSearchURLBin:
       
   942                 {
       
   943                 type = CESMRRichTextLink::ETypeURL;
       
   944                 break;
       
   945                 }
       
   946             default:
       
   947                 {
       
   948                 break;
       
   949                 }
       
   950             }
       
   951 
       
   952         if (valueBuf->Length ( )> 0 && type >= 0 )
       
   953             {
       
   954             CESMRRichTextLink* link = CESMRRichTextLink::NewL (item.iStartPos,
       
   955                     item.iLength, *valueBuf, type,
       
   956                     CESMRRichTextLink::ETriggerKeyRight );
       
   957             CleanupStack::PushL( link );
       
   958             AddLinkL( link );
       
   959             CleanupStack::Pop( link );
       
   960             }
       
   961 
       
   962         CleanupStack::PopAndDestroy (valueBuf );
       
   963         }
       
   964 
       
   965     // T
       
   966     HandleTextChangedL();
       
   967 
       
   968     CleanupStack::PopAndDestroy (itemEngine );
       
   969     }
       
   970 
       
   971 // -----------------------------------------------------------------------------
       
   972 // CESMRRichTextViewer::CopyCurrentLinkToClipBoardL
       
   973 // -----------------------------------------------------------------------------
       
   974 //
       
   975 EXPORT_C void CESMRRichTextViewer::CopyCurrentLinkToClipBoardL() const
       
   976     {
       
   977     FUNC_LOG;
       
   978     const CESMRRichTextLink* link = GetSelectedLink();
       
   979     HBufC* clipBoardText = NULL;
       
   980 
       
   981     if ( link )
       
   982     	{
       
   983     	clipBoardText = GetLinkTextLC( *link );
       
   984     	}
       
   985 
       
   986     if ( clipBoardText )
       
   987         {
       
   988         CClipboard* cb =
       
   989         CClipboard::NewForWritingLC( CCoeEnv::Static()->FsSession() );
       
   990         cb->StreamDictionary().At( KClipboardUidTypePlainText );
       
   991         CPlainText* plainText = CPlainText::NewL();
       
   992         CleanupStack::PushL( plainText );
       
   993         plainText->InsertL( 0 , *clipBoardText);
       
   994         plainText->CopyToStoreL( cb->Store(),
       
   995         		cb->StreamDictionary(), 0, plainText->DocumentLength());
       
   996         CleanupStack::PopAndDestroy( plainText );
       
   997         cb->CommitL();
       
   998         CleanupStack::PopAndDestroy( cb );
       
   999         CleanupStack::PopAndDestroy( clipBoardText );
       
  1000         }
       
  1001     }
       
  1002 
       
  1003 // -----------------------------------------------------------------------------
       
  1004 // CESMRRichTextViewer::ResetActionMenu
       
  1005 // -----------------------------------------------------------------------------
       
  1006 EXPORT_C void CESMRRichTextViewer::ResetActionMenuL() const // codescanner::LFunctionCantLeave
       
  1007     {
       
  1008     FUNC_LOG;
       
  1009     if ( iCntMenuHdlr )
       
  1010         {
       
  1011         iCntMenuHdlr->Reset();
       
  1012         }
       
  1013     }
       
  1014 
       
  1015 // -----------------------------------------------------------------------------
       
  1016 // CESMRRichTextViewer::SetEventObserver
       
  1017 // -----------------------------------------------------------------------------
       
  1018 //
       
  1019 EXPORT_C void CESMRRichTextViewer::SetEventQueue(
       
  1020         MESMRFieldEventQueue* aEventQueue )
       
  1021     {
       
  1022     FUNC_LOG;
       
  1023     iEventQueue = aEventQueue;
       
  1024     }
       
  1025 
       
  1026 // -----------------------------------------------------------------------------
       
  1027 // CESMRRichTextViewer::LinkSelectedL
       
  1028 // -----------------------------------------------------------------------------
       
  1029 //
       
  1030 EXPORT_C TBool CESMRRichTextViewer::LinkSelectedL()
       
  1031     {
       
  1032     FUNC_LOG;
       
  1033     TBool linkSelected = EFalse;
       
  1034 
       
  1035     const CESMRRichTextLink* link = GetSelectedLink();
       
  1036     if ( link )
       
  1037         {
       
  1038         switch ( link->TriggerKey() )
       
  1039             {
       
  1040             case CESMRRichTextLink::ETriggerKeyRight:
       
  1041                 {
       
  1042                 if ( !iLinkObserver ||
       
  1043                      !iLinkObserver->HandleRichTextLinkSelection(link) )
       
  1044                     {
       
  1045                     ShowContextMenuL();
       
  1046                     }
       
  1047                 linkSelected = ETrue;
       
  1048                 break;
       
  1049                 }
       
  1050             case CESMRRichTextLink::ETriggerKeyOk:
       
  1051                 {
       
  1052                 if (iLinkObserver &&
       
  1053                     iLinkObserver->HandleRichTextLinkSelection( link ) )
       
  1054                     {
       
  1055                     linkSelected = ETrue;
       
  1056                     }
       
  1057                 break;
       
  1058                 }
       
  1059             default:
       
  1060                 {
       
  1061                 break;
       
  1062                 }
       
  1063             }
       
  1064         }
       
  1065 
       
  1066     return linkSelected;
       
  1067     }
       
  1068 
       
  1069 // -----------------------------------------------------------------------------
       
  1070 // CESMRRichTextViewer::ProcessCommandL
       
  1071 // -----------------------------------------------------------------------------
       
  1072 //
       
  1073 void CESMRRichTextViewer::ProcessCommandL( TInt aCommandId )
       
  1074     {
       
  1075     FUNC_LOG;
       
  1076     if ( iEventQueue )
       
  1077         {
       
  1078         // Forward commands from contact menu handler as command events.
       
  1079         // Contact menu handler has the command observer for binary
       
  1080         // compatibility reason.
       
  1081         CESMRFieldCommandEvent* event =
       
  1082             CESMRFieldCommandEvent::NewLC( NULL, aCommandId );
       
  1083         iEventQueue->NotifyEventL( *event );
       
  1084         CleanupStack::PopAndDestroy( event );
       
  1085         }
       
  1086     }
       
  1087 
       
  1088 // -----------------------------------------------------------------------------
       
  1089 // CESMRRichTextViewer::ActivateL
       
  1090 // -----------------------------------------------------------------------------
       
  1091 //
       
  1092 void CESMRRichTextViewer::ActivateL()
       
  1093     {
       
  1094     FUNC_LOG;
       
  1095     CEikRichTextEditor::ActivateL();
       
  1096 
       
  1097     // CEikEdwin::ActivateL removes selection, re-set highlight
       
  1098     // if focused and there's a selected link.
       
  1099     const CESMRRichTextLink* link = GetSelectedLink();
       
  1100     if ( link && IsFocused() )
       
  1101         {
       
  1102         HighlightLinkL( *link );
       
  1103         DrawDeferred();
       
  1104         }
       
  1105     }
       
  1106 
       
  1107 // -----------------------------------------------------------------------------
       
  1108 // CESMRRichTextViewer::ContactActionQueryComplete
       
  1109 // -----------------------------------------------------------------------------
       
  1110 //
       
  1111 void CESMRRichTextViewer::ContactActionQueryComplete()
       
  1112     {
       
  1113     FUNC_LOG;
       
  1114     if ( iOpenActionMenu )
       
  1115         {
       
  1116         // Activate link as actions have been discovered
       
  1117         iOpenActionMenu = EFalse;
       
  1118         TRAP_IGNORE(  LinkSelectedL() );
       
  1119         }
       
  1120 
       
  1121     // Reset menu observer
       
  1122     iCntMenuHdlr->SetContactMenuObserver( NULL );    
       
  1123     }
       
  1124 
       
  1125 // -----------------------------------------------------------------------------
       
  1126 // CESMRRichTextViewer::ShowContextMenuL
       
  1127 // -----------------------------------------------------------------------------
       
  1128 //
       
  1129 void CESMRRichTextViewer::ShowContextMenuL()
       
  1130     {
       
  1131     FUNC_LOG;
       
  1132     
       
  1133     if ( !iOpenActionMenu )
       
  1134         {
       
  1135         ProcessCommandL( EAknSoftkeyContextOptions );
       
  1136         }
       
  1137     }
       
  1138 
       
  1139 // -----------------------------------------------------------------------------
       
  1140 // CESMRRichTextViewer::GetLinkAreaL
       
  1141 // -----------------------------------------------------------------------------
       
  1142 //
       
  1143 void CESMRRichTextViewer::GetLinkAreaL(
       
  1144         TRegion& aRegion,
       
  1145         const CESMRRichTextLink& aLink ) const
       
  1146     {
       
  1147     FUNC_LOG;
       
  1148     TTmDocPosSpec posSpec;
       
  1149     TTmPosInfo2 posInfo;
       
  1150 
       
  1151     posSpec.iPos = aLink.StartPos();
       
  1152     posSpec.iType = TTmDocPosSpec::ELeading;
       
  1153 
       
  1154     aRegion.Clear();
       
  1155 
       
  1156     if ( TextView()->FindDocPosL( posSpec, posInfo ) )
       
  1157         {
       
  1158         TRect linkRect( 0, 0, 0, 0 );
       
  1159 
       
  1160         // Create link surrounding rectangle
       
  1161         HBufC* text = GetLinkTextLC( aLink );
       
  1162         TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth(
       
  1163                 *iFont,
       
  1164                 *text,
       
  1165                 CFont::TMeasureTextInput::EFVisualOrder );
       
  1166 
       
  1167         TPoint tl( posInfo.iEdge );
       
  1168         tl.iY -= iFont->FontMaxAscent();
       
  1169 
       
  1170         TPoint br( tl.iX + textWidth, tl.iY + iFont->FontMaxHeight() );
       
  1171 
       
  1172         TRect rect( Rect() );
       
  1173 
       
  1174         while ( ( tl.iX < rect.iTl.iX || br.iX > rect.iBr.iX )
       
  1175                 && !aRegion.CheckError() )
       
  1176             {
       
  1177             // Link on multiple lines
       
  1178 
       
  1179             tl.iX = Max( rect.iTl.iX, tl.iX );
       
  1180             br.iX = Min( br.iX, rect.iBr.iX );
       
  1181             linkRect.SetRect( tl, br );
       
  1182             aRegion.AddRect( linkRect );
       
  1183 
       
  1184             TPtrC remainder( text->Mid( posSpec.iPos - aLink.StartPos() ) );
       
  1185             TInt numChars = iFont->TextCount( remainder,
       
  1186                                               linkRect.Width() );
       
  1187             posSpec.iPos += numChars;
       
  1188             remainder.Set( remainder.Mid( numChars) );
       
  1189 
       
  1190             if ( TextView()->FindDocPosL( posSpec, posInfo ) )
       
  1191                 {
       
  1192                 textWidth = AknBidiTextUtils::MeasureTextBoundsWidth(
       
  1193                                 *iFont,
       
  1194                                 remainder,
       
  1195                                 CFont::TMeasureTextInput::EFVisualOrder );
       
  1196 
       
  1197                 tl = posInfo.iEdge;
       
  1198 
       
  1199                 if ( AknLayoutUtils::LayoutMirrored() )
       
  1200                     {
       
  1201                     // move top left x to end of text
       
  1202                     tl.iX -= textWidth;
       
  1203                     }
       
  1204 
       
  1205                 tl.iY -= iFont->FontMaxAscent();
       
  1206                 br.SetXY( tl.iX + textWidth, tl.iY + iFont->FontMaxHeight() );
       
  1207                 }
       
  1208             }
       
  1209 
       
  1210         linkRect.SetRect( tl, br );
       
  1211         aRegion.AddRect( linkRect );
       
  1212 
       
  1213         CleanupStack::PopAndDestroy( text );
       
  1214         }
       
  1215     }
       
  1216 
       
  1217 // -----------------------------------------------------------------------------
       
  1218 // CESMRRichTextViewer::ChangeMiddleSoftkeyL
       
  1219 // -----------------------------------------------------------------------------
       
  1220 //
       
  1221 void CESMRRichTextViewer::ChangeMiddleSoftkeyL( const CESMRRichTextLink& aLink )
       
  1222     {
       
  1223     FUNC_LOG;
       
  1224     CESMRField* field = static_cast< CESMRField* >( Parent() );
       
  1225 
       
  1226     if ( field )
       
  1227         {
       
  1228         field->ChangeMiddleSoftKeyL( aLink.MSKCommand(), aLink.MSKText() );
       
  1229         }
       
  1230     }
       
  1231 
       
  1232 // -----------------------------------------------------------------------------
       
  1233 // CESMRRichTextViewer::UpdateViewL
       
  1234 // -----------------------------------------------------------------------------
       
  1235 //
       
  1236 void CESMRRichTextViewer::UpdateViewL( const TKeyEvent &aKeyEvent )
       
  1237     {
       
  1238     FUNC_LOG;
       
  1239     const CESMRRichTextLink* selectedLink = GetSelectedLink();
       
  1240 
       
  1241     if( !selectedLink )
       
  1242         {
       
  1243         return;
       
  1244         }
       
  1245 
       
  1246     RRegion linkRegion;
       
  1247     CleanupClosePushL( linkRegion );
       
  1248 
       
  1249     GetLinkAreaL( linkRegion, *selectedLink );
       
  1250     TRect linkRect = linkRegion.BoundingRect();
       
  1251 
       
  1252     CleanupStack::PopAndDestroy( &linkRegion );
       
  1253 
       
  1254     TRect viewableAreaRect = iObserver->ViewableAreaRect();
       
  1255 
       
  1256 
       
  1257     switch ( aKeyEvent.iCode )
       
  1258         {
       
  1259         case EKeyLeftArrow:
       
  1260         case EKeyUpArrow:
       
  1261             {
       
  1262             if( linkRect.iTl.iY < viewableAreaRect.iTl.iY )
       
  1263                 {
       
  1264                 // Move fields down
       
  1265                 iObserver->RePositionFields(
       
  1266                         -( linkRect.iTl.iY - viewableAreaRect.iTl.iY ) );
       
  1267                 }
       
  1268 
       
  1269             break;
       
  1270             }
       
  1271         case EKeyRightArrow:
       
  1272         case EKeyDownArrow:
       
  1273             {
       
  1274             if( linkRect.iBr.iY > viewableAreaRect.iBr.iY )
       
  1275                 {
       
  1276                 // Move fields up
       
  1277                 iObserver->RePositionFields(
       
  1278                         -( linkRect.iBr.iY - viewableAreaRect.iBr.iY ) );
       
  1279                 }
       
  1280             break;
       
  1281             }
       
  1282         default:
       
  1283             break;
       
  1284         }
       
  1285     }
       
  1286 
       
  1287 // EOF
       
  1288