meetingrequest/mrgui/mrfieldbuilderpluginextension/src/cesmrncsaifeditor.cpp
changeset 0 8466d47a6819
child 16 4ce476e64c59
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2007-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: This file implements classes CESMRNcsAifEntry, CESMRNcsAifEditor.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "emailtrace.h"
       
    19 #include "cesmrncsaifeditor.h"
       
    20 
       
    21 #include <AknsDrawUtils.h>
       
    22 #include <s32mem.h>
       
    23 #include <txtrich.h>
       
    24 #include <baclipb.h>
       
    25 #include <PtiDefs.h>
       
    26 #include <StringLoader.h>
       
    27 #include <eikedwin.h>
       
    28 
       
    29 #ifndef FF_CMAIL_INTEGRATION
       
    30 #include <txtclipboard.h>
       
    31 #endif // FF_CMAIL_INTEGRATION
       
    32 
       
    33 #include "cesmrncsemailaddressobject.h"
       
    34 #include "cesmrcontacthandler.h"
       
    35 #include "esmrfieldbuilderdef.h"
       
    36 
       
    37 // ======== MEMBER FUNCTIONS ========
       
    38 
       
    39 // ---------------------------------------------------------------------------
       
    40 // CESMRNcsAifEntry::NewL
       
    41 // ---------------------------------------------------------------------------
       
    42 //
       
    43 CESMRNcsAifEntry* CESMRNcsAifEntry::NewL(
       
    44     const CESMRNcsEmailAddressObject& addr,
       
    45     TBool aDisplayFull )
       
    46     {
       
    47     FUNC_LOG;
       
    48     CESMRNcsAifEntry* self = new (ELeave) CESMRNcsAifEntry( aDisplayFull );
       
    49     CleanupStack::PushL(self);
       
    50     self->ConstructL( addr );
       
    51     CleanupStack::Pop(self);
       
    52     return self;
       
    53     }
       
    54 
       
    55 // ---------------------------------------------------------------------------
       
    56 // CESMRNcsAifEntry::NewL
       
    57 // ---------------------------------------------------------------------------
       
    58 //
       
    59 CESMRNcsAifEntry* CESMRNcsAifEntry::NewL(
       
    60     const TDesC& aDn,
       
    61     const TDesC& aEml,
       
    62     TBool aDisplayFull )
       
    63     {
       
    64     FUNC_LOG;
       
    65     CESMRNcsAifEntry* self = new ( ELeave ) CESMRNcsAifEntry( aDisplayFull );
       
    66     CleanupStack::PushL(self);
       
    67     self->ConstructL( aDn, aEml);
       
    68     CleanupStack::Pop( self );
       
    69     return self;
       
    70     }
       
    71 
       
    72 // ---------------------------------------------------------------------------
       
    73 // CESMRNcsAifEntry::~CESMRNcsAifEntry
       
    74 // ---------------------------------------------------------------------------
       
    75 //
       
    76 CESMRNcsAifEntry::~CESMRNcsAifEntry()
       
    77     {
       
    78     FUNC_LOG;
       
    79     delete iAddress;
       
    80     delete iDisplayString;
       
    81     }
       
    82 
       
    83 // ---------------------------------------------------------------------------
       
    84 // CESMRNcsAifEntry::CESMRNcsAifEntry
       
    85 // ---------------------------------------------------------------------------
       
    86 //
       
    87 CESMRNcsAifEntry::CESMRNcsAifEntry( TBool aDisplayFull ) :
       
    88     iDisplayFull( aDisplayFull )
       
    89     {
       
    90     FUNC_LOG;
       
    91     //do nothing
       
    92     }
       
    93 
       
    94 // ---------------------------------------------------------------------------
       
    95 // CESMRNcsAifEntry::ConstructL
       
    96 // ---------------------------------------------------------------------------
       
    97 //
       
    98 void CESMRNcsAifEntry::ConstructL( const TDesC& aDn, const TDesC& aEml )
       
    99     {
       
   100     FUNC_LOG;
       
   101     iAddress = CESMRNcsEmailAddressObject::NewL( aDn, aEml );
       
   102     ConstructL();
       
   103     }
       
   104 
       
   105 // ---------------------------------------------------------------------------
       
   106 // CESMRNcsAifEntry::ConstructL
       
   107 // ---------------------------------------------------------------------------
       
   108 //
       
   109 void CESMRNcsAifEntry::ConstructL( const CESMRNcsEmailAddressObject& aAddress )
       
   110     {
       
   111     FUNC_LOG;
       
   112     iAddress = CESMRNcsEmailAddressObject::NewL( aAddress );
       
   113     ConstructL();
       
   114     }
       
   115 
       
   116 // ---------------------------------------------------------------------------
       
   117 // CESMRNcsAifEntry::ConstructL
       
   118 // ---------------------------------------------------------------------------
       
   119 //
       
   120 void CESMRNcsAifEntry::ConstructL()
       
   121     {
       
   122     FUNC_LOG;
       
   123     SetDisplayStringL();
       
   124     }
       
   125 
       
   126 // ---------------------------------------------------------------------------
       
   127 // CESMRNcsAifEntry::SetDisplayStringL
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 void CESMRNcsAifEntry::SetDisplayStringL()
       
   131     {
       
   132     FUNC_LOG;
       
   133     if ( iDisplayString )
       
   134         {
       
   135         delete iDisplayString;
       
   136         iDisplayString = NULL;
       
   137         }
       
   138 
       
   139     const TDesC& dname = iAddress->DisplayName();
       
   140     const TDesC& email = iAddress->EmailAddress();
       
   141 
       
   142     TInt dnameLength = dname.Length();
       
   143     TInt emailLength = email.Length();
       
   144 
       
   145     TInt length;
       
   146     if ( !iIsDup && !iDisplayFull )
       
   147         {
       
   148         length = dnameLength > 0 ? dnameLength : emailLength;
       
   149         length += 1; // ';'
       
   150 
       
   151         iDisplayString = HBufC::NewL( length );
       
   152         TPtr ptr = iDisplayString->Des();
       
   153 
       
   154         ptr.Append( dname.Length() > 0 ? dname : email );
       
   155         ptr.Append( KAddressDelimeterSemiColon );
       
   156         }
       
   157     else
       
   158         {
       
   159         // Display, Name <display.name(at)dn.com>;
       
   160         length = dnameLength + emailLength + 4;
       
   161 
       
   162         iDisplayString = HBufC::NewL( length );
       
   163         TPtr ptr = iDisplayString->Des();
       
   164 
       
   165         ptr.Append( dname );
       
   166         _LIT(KLeft, " <");
       
   167         ptr.Append( KLeft );
       
   168         ptr.Append( email );
       
   169         _LIT(KRight, ">");
       
   170         ptr.Append( KRight );
       
   171         ptr.Append( KAddressDelimeterSemiColon );
       
   172         }
       
   173     }
       
   174 
       
   175 // ---------------------------------------------------------------------------
       
   176 // constructor/destructor
       
   177 // ---------------------------------------------------------------------------
       
   178 //
       
   179 CESMRNcsAifEditor::CESMRNcsAifEditor( CESMRContactHandler& aContactHandler, HBufC* aDefaultText ) :
       
   180     CESMRNcsEditor( aDefaultText ), iContactHandler( aContactHandler )
       
   181     {
       
   182     FUNC_LOG;
       
   183     SetEdwinObserver( this );
       
   184     }
       
   185 
       
   186 // ---------------------------------------------------------------------------
       
   187 // constructor/destructor
       
   188 // ---------------------------------------------------------------------------
       
   189 //
       
   190 CESMRNcsAifEditor::~CESMRNcsAifEditor()
       
   191     {
       
   192     FUNC_LOG;
       
   193     iArray.ResetAndDestroy();
       
   194     iAddressArray.Reset();
       
   195     }
       
   196 
       
   197 // -----------------------------------------------------------------------------
       
   198 // CESMRNcsAifEditor::CursorLineNumber() const
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 TInt CESMRNcsAifEditor::CursorLineNumber() const
       
   202     {
       
   203     FUNC_LOG;
       
   204 
       
   205     TInt ret = iLayout->GetLineNumber( CursorPos() );
       
   206     ret++;
       
   207     if( ret > KMaxAddressFieldLines )
       
   208         {
       
   209         ret = KMaxAddressFieldLines;
       
   210         }
       
   211     return ret;
       
   212     }
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // CESMRNcsAifEditor::LineCount() const
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 TInt CESMRNcsAifEditor::LineCount() const
       
   219     {
       
   220     FUNC_LOG;
       
   221     TInt lineCount = iLayout->GetLineNumber( TextLength() );
       
   222     lineCount++;
       
   223     if( lineCount > KMaxAddressFieldLines )
       
   224         {
       
   225         lineCount = KMaxAddressFieldLines;
       
   226         }
       
   227     return lineCount;
       
   228     }
       
   229 
       
   230 // -----------------------------------------------------------------------------
       
   231 // CESMRNcsAifEditor::OfferKeyEventL()
       
   232 // -----------------------------------------------------------------------------
       
   233 //
       
   234 TKeyResponse CESMRNcsAifEditor::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
       
   235     {
       
   236     FUNC_LOG;
       
   237     TKeyResponse ret = EKeyWasNotConsumed;
       
   238 
       
   239     // check if we are copying
       
   240     if ( ret == EKeyWasNotConsumed )
       
   241         {
       
   242         ret = CopyEntriesToClipboardL( aKeyEvent, aType );
       
   243         }
       
   244 
       
   245     // Check if we need to delete a contact
       
   246     // We must do this before select sincey they
       
   247     // key off of the same key code.
       
   248     if ( ret == EKeyWasNotConsumed )
       
   249         {
       
   250         ret = HandleContactDeletionL( aKeyEvent, aType );
       
   251         }
       
   252 
       
   253     // Check if we need to highlight a contact
       
   254     if ( ret == EKeyWasNotConsumed )
       
   255         {
       
   256         ret = SetEditorSelectionL( aKeyEvent, aType );
       
   257         }
       
   258 
       
   259     if ( ret == EKeyWasNotConsumed )
       
   260         {
       
   261         ret = CESMRNcsEditor::OfferKeyEventL( aKeyEvent, aType );
       
   262         }
       
   263     return ret;
       
   264     }
       
   265 
       
   266 // -----------------------------------------------------------------------------
       
   267 // CESMRNcsAifEditor::HandleEdwinEventL()
       
   268 // This function gets called if a character is entered through the FEP.
       
   269 // Otherwise the character entry is added through OfferKeyEvent
       
   270 // -----------------------------------------------------------------------------
       
   271 //
       
   272 void CESMRNcsAifEditor::HandleEdwinEventL( CEikEdwin* /*aEdwin*/, TEdwinEvent aEventType )
       
   273     {
       
   274     FUNC_LOG;
       
   275     if ( aEventType == MEikEdwinObserver::EEventTextUpdate )
       
   276         {
       
   277         HandleContactDeletionL();
       
   278         HandleTextUpdateL();
       
   279         }
       
   280     else if ( aEventType == MEikEdwinObserver::EEventNavigation )
       
   281         {
       
   282         HandleNavigationEventL();
       
   283         }
       
   284     }
       
   285 
       
   286 // -----------------------------------------------------------------------------
       
   287 // CESMRNcsAifEditor::SetEditorSelectionL()
       
   288 // -----------------------------------------------------------------------------
       
   289 //
       
   290 TKeyResponse CESMRNcsAifEditor::SetEditorSelectionL( const TKeyEvent& aKeyEvent, TEventCode aType )
       
   291     {
       
   292     FUNC_LOG;
       
   293     TKeyResponse response = EKeyWasNotConsumed;
       
   294     CESMRNcsAifEntry* entry = NULL;
       
   295     TCursorSelection selection = Selection();
       
   296 
       
   297     // Moving to a new line is a special case.
       
   298     // We need to offer the key to the editor control first so it can
       
   299     // move the cursor for us.  Then we check if it's in an entry.
       
   300     if ( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow )
       
   301         {
       
   302         response = CESMRNcsEditor::OfferKeyEventL( aKeyEvent,aType );
       
   303         if ( response == EKeyWasConsumed )
       
   304             {
       
   305             // We're moving to a new line.
       
   306             entry = GetEntryAt( CursorPos() );
       
   307             if ( entry )
       
   308                 {
       
   309                 SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
       
   310                 }
       
   311             }
       
   312         }
       
   313     // Check if the cursor is in any of the addresses
       
   314     else if( aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyBackspace )
       
   315         {
       
   316         // We're moving left, but haven't yet.
       
   317         entry = GetEntryAt( CursorPos(), EDirectionLeft );
       
   318         if ( entry )
       
   319             {
       
   320             if ( selection.Length() && aKeyEvent.iCode == EKeyLeftArrow)
       
   321                 {
       
   322                 // Adds or removes the entry from the current selection.
       
   323                 SetSelectionL( entry->LowerPos(), selection.iAnchorPos );
       
   324                 response = EKeyWasConsumed;
       
   325                 }
       
   326             else if ( !selection.Length() )
       
   327                 {
       
   328                 SetSelectionL( entry->LowerPos(), entry->HigherPos() );
       
   329                 response = EKeyWasConsumed;
       
   330                 }
       
   331             }
       
   332         }
       
   333     else if( aKeyEvent.iCode == EKeyRightArrow || aKeyEvent.iCode == EKeyDelete )
       
   334         {
       
   335         // We're moving right, but haven't yet.
       
   336         entry = GetEntryAt( CursorPos(), EDirectionRight );
       
   337         if ( entry )
       
   338             {
       
   339             if ( selection.Length() && aKeyEvent.iCode == EKeyRightArrow  )
       
   340                 {
       
   341                 // Adds or removes the entry form the current selection.
       
   342                 SetSelectionL( entry->HigherPos(), selection.iAnchorPos );
       
   343                 response = EKeyWasConsumed;
       
   344                 }
       
   345             else if ( !selection.Length() )
       
   346                 {
       
   347                 SetSelectionL( entry->HigherPos(), entry->LowerPos() );
       
   348                 response = EKeyWasConsumed;
       
   349                 }
       
   350             }
       
   351         }
       
   352 
       
   353     // Close the address popup if we handled the event
       
   354     if ( response == EKeyWasConsumed )
       
   355         {
       
   356         iAddressPopupList->ClosePopupContactListL();
       
   357         }
       
   358 
       
   359     return response;
       
   360     }
       
   361 
       
   362 // -----------------------------------------------------------------------------
       
   363 // CESMRNcsAifEditor::HandleContactDeletionL()
       
   364 // -----------------------------------------------------------------------------
       
   365 //
       
   366 TKeyResponse CESMRNcsAifEditor::HandleContactDeletionL(
       
   367         const TKeyEvent& aKeyEvent,
       
   368         TEventCode aType)
       
   369     {
       
   370     FUNC_LOG;
       
   371     TKeyResponse response  = EKeyWasNotConsumed;
       
   372     if ( SelectionLength() && aType == EEventKey
       
   373         && !IsNavigationKey( aKeyEvent ) )
       
   374         {
       
   375         // Delete highlighted entries.
       
   376         TCursorSelection selection = Selection();
       
   377         TBool entryDeleted = EFalse;
       
   378         for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
       
   379             {
       
   380             if ( iArray[ii]->LowerPos() >= selection.LowerPos() &&
       
   381                 iArray[ii]->HigherPos() <= selection.HigherPos() )
       
   382                 {
       
   383                 delete iArray[ii];
       
   384                 iArray.Remove( ii );
       
   385                 entryDeleted = ETrue;
       
   386                 }
       
   387             }
       
   388 
       
   389         if ( entryDeleted )
       
   390             {
       
   391             // Check that duplicate entries are correctly marked.
       
   392             UpdateDuplicateEntryMarkings();
       
   393 
       
   394             // Set the cursor after the entry before the ones we just deleted
       
   395             CESMRNcsAifEntry* entry = NULL;
       
   396             for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
       
   397                 {
       
   398                 if ( iArray[ii]->HigherPos() <= selection.LowerPos() )
       
   399                     {
       
   400                     entry = iArray[ii];
       
   401                     break;
       
   402                     }
       
   403                 }
       
   404 
       
   405             ClearSelectionL();
       
   406 
       
   407             RepositionEntriesL( entry );
       
   408 
       
   409             // The key event is set consumed only on delete and backpace
       
   410             // events, other events need to be forwarded to the editor.
       
   411             if ( aKeyEvent.iCode == EKeyDelete ||
       
   412                  aKeyEvent.iCode == EKeyBackspace )
       
   413                 {
       
   414                 response = EKeyWasConsumed;
       
   415                 }
       
   416             }
       
   417         }
       
   418     return response;
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------
       
   422 // CESMRNcsAifEditor::DoCharChangeL
       
   423 // ---------------------------------------------------------
       
   424 //
       
   425 void CESMRNcsAifEditor::DoCharChangeL()
       
   426     {
       
   427     FUNC_LOG;
       
   428     RecalculateEntryPositions();
       
   429 
       
   430     TChar previousChar = CharAtPos( CursorPos() - 1 );
       
   431     TBool sentinel = ( previousChar == KSemiColon ||
       
   432         previousChar == KComma );
       
   433     if ( sentinel )
       
   434         {
       
   435         // if comma was pressed we replace it with semicolon
       
   436         if ( previousChar == KComma )
       
   437             {
       
   438             CPlainText* text = Text();
       
   439             text->DeleteL( CursorPos() - 1, 1 );
       
   440             text->InsertL( CursorPos() - 1, KSemiColon );
       
   441             }
       
   442         TBool check = ParseNewAddressL();
       
   443         }
       
   444     UpdateAddressAutoCompletionL();
       
   445     }
       
   446 
       
   447 // ---------------------------------------------------------
       
   448 // CESMRNcsAifEditor::CharAtPos
       
   449 // ---------------------------------------------------------
       
   450 //
       
   451 TChar CESMRNcsAifEditor::CharAtPos( TInt aPos ) const
       
   452     {
       
   453     FUNC_LOG;
       
   454     if ( aPos >= 0 && aPos < TextLength() )
       
   455         {
       
   456         TBuf<1> buf;
       
   457         Text()->Extract( buf, aPos, 1 );
       
   458         return buf[0];
       
   459         }
       
   460     else
       
   461         {
       
   462         return 0;
       
   463         }
       
   464     }
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CESMRNcsAifEditor::SetAddressesL()
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 void CESMRNcsAifEditor::SetAddressesL( const RPointerArray<CESMRNcsEmailAddressObject>& aAddresses )
       
   471     {
       
   472     FUNC_LOG;
       
   473     iArray.ResetAndDestroy();
       
   474     AppendAddressesL( aAddresses );
       
   475     }
       
   476 
       
   477 // -----------------------------------------------------------------------------
       
   478 // CESMRNcsAifEditor::AppendAddressesL()
       
   479 // -----------------------------------------------------------------------------
       
   480 //
       
   481 void CESMRNcsAifEditor::AppendAddressesL( const RPointerArray<CESMRNcsEmailAddressObject>& aAddresses )
       
   482     {
       
   483     FUNC_LOG;
       
   484     iArray.ReserveL( iArray.Count() + aAddresses.Count() );
       
   485 
       
   486     CESMRNcsAifEntry* entry = NULL;
       
   487     for (int i=0;i<aAddresses.Count();i++)
       
   488         {
       
   489         CESMRNcsEmailAddressObject* address = aAddresses[i];
       
   490         entry = CESMRNcsAifEntry::NewL( *address, address->DisplayFull() );
       
   491 
       
   492         int idx;
       
   493         // Check for duplicate display names
       
   494         for ( idx=0; idx<iArray.Count(); idx++ )
       
   495             {
       
   496             if ( iArray[idx]->IsSameDN( *entry ) )
       
   497                 {
       
   498                 iArray[idx]->SetDup();
       
   499                 entry->SetDup();
       
   500                 }
       
   501             }
       
   502 
       
   503         CleanupStack::PushL( entry );
       
   504         iArray.AppendL( entry );
       
   505         CleanupStack::Pop( entry );
       
   506         }
       
   507 
       
   508     RepositionEntriesL( entry );
       
   509     }
       
   510 
       
   511 // -----------------------------------------------------------------------------
       
   512 // CESMRNcsAifEditor::GetAddressesL()
       
   513 // -----------------------------------------------------------------------------
       
   514 //
       
   515 const RPointerArray<CESMRNcsEmailAddressObject>& CESMRNcsAifEditor::GetAddressesL()
       
   516     {
       
   517     // Clear the existing array since it may be out of sync
       
   518     iAddressArray.Reset();
       
   519 
       
   520     for (int i=0;i<iArray.Count();i++)
       
   521         {
       
   522         iAddressArray.AppendL(&iArray[i]->Address());
       
   523         }
       
   524 
       
   525     return iAddressArray;
       
   526     }
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // CESMRNcsAifEditor::GetEntryAt()
       
   530 // -----------------------------------------------------------------------------
       
   531 //
       
   532 CESMRNcsAifEntry* CESMRNcsAifEditor::GetEntryAt(
       
   533     TInt aPos,
       
   534     TEntryDirection aDirection ) const
       
   535     {
       
   536     FUNC_LOG;
       
   537 
       
   538     TChar KSpace( ' ' );
       
   539 
       
   540     for( TInt i = 0; i < iArray.Count(); i++ )
       
   541       {
       
   542       CESMRNcsAifEntry* entry = iArray[i];
       
   543       if ( aDirection == EDirectionNone )
       
   544           {
       
   545           // no direction, check if cursor is on entry
       
   546           if ( entry->Includes( aPos ) )
       
   547               {
       
   548               return entry;
       
   549               }
       
   550           }
       
   551       else if ( aDirection == EDirectionRight )
       
   552           {
       
   553           // direction to the righ. check if cursor is on entry or
       
   554           // entry is immediately to the right of the cursor
       
   555           if ( entry->Includes( aPos ) )
       
   556               {
       
   557               return entry;
       
   558               }
       
   559 
       
   560           if ( entry->Start() >= aPos && entry->Start() - aPos <= 1 &&
       
   561               CharAtPos( aPos ) == KSpace )
       
   562               {
       
   563               return entry;
       
   564               }
       
   565           }
       
   566       else if ( aDirection == EDirectionLeft )
       
   567           {
       
   568           // direction to the left. decrease cursor by one and check if it
       
   569           // is on entry or if entry is immediately to the left of the cursor
       
   570           if ( entry->Includes( aPos - 1 ) )
       
   571               {
       
   572               return entry;
       
   573               }
       
   574 
       
   575           if ( aPos >= entry->End() && aPos - entry->End() <= 1 &&
       
   576               CharAtPos( aPos - 1 ) == KSpace )
       
   577               {
       
   578               return entry;
       
   579               }
       
   580           }
       
   581       }
       
   582     return NULL;
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 // CESMRNcsAifEditor::CheckAddressWhenFocusLostL()
       
   587 // -----------------------------------------------------------------------------
       
   588 //
       
   589 void CESMRNcsAifEditor::CheckAddressWhenFocusLostL()
       
   590     {
       
   591     FUNC_LOG;
       
   592     ParseNewAddressL();
       
   593     }
       
   594 
       
   595 // -----------------------------------------------------------------------------
       
   596 // CESMRNcsAifEditor::ParseNewAddressL()
       
   597 // -----------------------------------------------------------------------------
       
   598 //
       
   599 TBool CESMRNcsAifEditor::ParseNewAddressL()
       
   600     {
       
   601     FUNC_LOG;
       
   602     HBufC* text = GetNonEntryTextLC();
       
   603 
       
   604     if ( !text )
       
   605         {
       
   606         return false;
       
   607         }
       
   608     // check if there is a name for the email address
       
   609 
       
   610     // if name = NULL, it isn't in cleanupstack
       
   611     HBufC* name = iContactHandler.GetLastSearchNameLC( *text );
       
   612     if ( name )
       
   613         {
       
   614         AddAddressL( *name, *text, ETrue );
       
   615         CleanupStack::PopAndDestroy( name );
       
   616         }
       
   617     else
       
   618         {
       
   619         AddAddressL(KNullDesC(),*text);
       
   620         }
       
   621 
       
   622     CleanupStack::PopAndDestroy(text);
       
   623 
       
   624     return true;
       
   625     }
       
   626 
       
   627 // -----------------------------------------------------------------------------
       
   628 // CESMRNcsAifEditor::GetNonEntryTextL()
       
   629 // This will extract any text that was entered that is not
       
   630 // part of any existing entries
       
   631 // -----------------------------------------------------------------------------
       
   632 //
       
   633 HBufC* CESMRNcsAifEditor::GetNonEntryTextLC() const
       
   634     {
       
   635     FUNC_LOG;
       
   636     // The user entered a new email address directly into the AIF
       
   637     TInt pos = CursorPos();
       
   638 
       
   639     // Check if the cursor is in an existing entry
       
   640     for (int i=0;i<iArray.Count(); i++)
       
   641         {
       
   642         if (iArray[i]->Includes(pos-1)) return NULL;
       
   643         }
       
   644 
       
   645     // Pull the text to the left of the cursor up to the
       
   646     // previous entry or the beginning of the doc
       
   647     int idx = -1;
       
   648     for (int i=0;i<iArray.Count();i++)
       
   649         {
       
   650         if (iArray[i]->End() < pos) idx = i;
       
   651         }
       
   652 
       
   653     // No entry before this text, pull to beginning of doc
       
   654     int len, start;
       
   655     if (idx == -1)
       
   656         {
       
   657         len = pos;
       
   658         start = 0;
       
   659         }
       
   660     else
       
   661         {
       
   662         len = pos - iArray[idx]->End();
       
   663         start = iArray[idx]->End();
       
   664         }
       
   665 
       
   666     // The user could have moved the cursor into the new text.
       
   667     // Pull the text to the right of the cursor up to the
       
   668     // next entry or the end of the doc
       
   669     for (idx=0;idx<iArray.Count();idx++)
       
   670         {
       
   671         if (iArray[idx]->Start() >= pos) break;
       
   672         }
       
   673 
       
   674     // No entry after this text, pull to end of doc
       
   675     if (iArray.Count() == 0 || idx == iArray.Count())
       
   676         {
       
   677         len += TextLength() - pos;
       
   678         }
       
   679     else
       
   680         {
       
   681         len += iArray[idx]->Start() - pos;
       
   682         }
       
   683 
       
   684     // Extract the address text
       
   685     HBufC* text = HBufC::NewLC(len);
       
   686     TPtr ptr = text->Des();
       
   687     Text()->Extract(ptr,start,len);
       
   688 
       
   689     // Wipe out any delimiters
       
   690     TChar semiColon(KSemiColon);
       
   691     pos = ptr.Locate(semiColon);
       
   692     if (pos != KErrNotFound)
       
   693         ptr.Delete(pos,1);
       
   694 
       
   695     // Trim the string and add it to the entries list
       
   696     ptr.Trim();
       
   697 
       
   698     if (ptr.Length() == 0)
       
   699         {
       
   700         CleanupStack::PopAndDestroy(text);
       
   701         return NULL;
       
   702         }
       
   703 
       
   704     return text;
       
   705     }
       
   706 
       
   707 // -----------------------------------------------------------------------------
       
   708 // CESMRNcsAifEditor::CopyEntriesToClipBoardL
       
   709 // -----------------------------------------------------------------------------
       
   710 //
       
   711 TKeyResponse CESMRNcsAifEditor::CopyEntriesToClipboardL(
       
   712     const TKeyEvent& aKeyEvent,
       
   713     TEventCode aType )
       
   714     {
       
   715     FUNC_LOG;
       
   716     TKeyResponse ret = EKeyWasNotConsumed;
       
   717 
       
   718     const TInt KCopyKeyEventCode = 3;
       
   719     const TInt KCutKeyEventCode = 24;
       
   720 
       
   721     // check that we are copying
       
   722     TBool copyKeyEvent = ( aType == EEventKey && aKeyEvent.iCode == KCopyKeyEventCode &&
       
   723                            aKeyEvent.iModifiers & EModifierCtrl &&
       
   724                            aKeyEvent.iScanCode == EPtiKeyQwertyC );
       
   725     TBool cutKeyEvent = ( aType == EEventKey && aKeyEvent.iCode == KCutKeyEventCode &&
       
   726                           aKeyEvent.iModifiers & EModifierCtrl &&
       
   727                           aKeyEvent.iScanCode == EPtiKeyQwertyX );
       
   728     if ( copyKeyEvent || cutKeyEvent )
       
   729         {
       
   730         RPointerArray<CESMRNcsAifEntry> entries;
       
   731         CleanupClosePushL( entries );
       
   732         FindSelectedEntriesL( entries );
       
   733         if ( entries.Count() > 0 )
       
   734             {
       
   735             CancelFepTransaction();
       
   736             HBufC* formattedText = GetFormattedAddressListLC( entries, EFalse );
       
   737             CopyToClipboardL( *formattedText );
       
   738             CleanupStack::PopAndDestroy( formattedText );
       
   739 
       
   740             if ( !cutKeyEvent )
       
   741                 { // cutting needs more handling
       
   742                 ret = EKeyWasConsumed;
       
   743                 }
       
   744             }
       
   745         CleanupStack::PopAndDestroy( &entries );
       
   746         }
       
   747     return ret;
       
   748     }
       
   749 
       
   750 // -----------------------------------------------------------------------------
       
   751 // CESMRNcsAifEditor::FindSelectedEntriesL( )
       
   752 // -----------------------------------------------------------------------------
       
   753 //
       
   754 void CESMRNcsAifEditor::FindSelectedEntriesL( RPointerArray<CESMRNcsAifEntry>& aEntries )
       
   755     {
       
   756     FUNC_LOG;
       
   757     TCursorSelection selection = Selection();
       
   758     TInt count = iArray.Count();
       
   759     for ( TInt i = 0; i < iArray.Count(); i++ )
       
   760         {
       
   761         CESMRNcsAifEntry* entry = iArray[i];
       
   762         if ( entry->Start() >= selection.LowerPos() &&
       
   763              entry->End() <= selection.HigherPos() )
       
   764             {
       
   765             aEntries.AppendL( entry );
       
   766             }
       
   767         }
       
   768     }
       
   769 
       
   770 // -----------------------------------------------------------------------------
       
   771 // CESMRNcsAifEditor::EmailAddressIndexNameBySelection( )
       
   772 // -----------------------------------------------------------------------------
       
   773 //
       
   774 const CESMRNcsEmailAddressObject* CESMRNcsAifEditor::EmailAddressObjectBySelection() const
       
   775 
       
   776     {
       
   777     FUNC_LOG;
       
   778     // Find the contact the cursor is in
       
   779     const CESMRNcsAifEntry* aEntry = GetEntryAt(CursorPos());
       
   780     ASSERT(aEntry != NULL);
       
   781     return &aEntry->Address();
       
   782     }
       
   783 
       
   784 
       
   785 // -----------------------------------------------------------------------------
       
   786 // CESMRNcsAifEditor::AddAddressL()
       
   787 // -----------------------------------------------------------------------------
       
   788 //
       
   789 void CESMRNcsAifEditor::AddAddressL( const CESMRNcsEmailAddressObject& aAddress )
       
   790     {
       
   791     FUNC_LOG;
       
   792     AddAddressL( CESMRNcsAifEntry::NewL( aAddress, aAddress.DisplayFull() ) );
       
   793     }
       
   794 
       
   795 // -----------------------------------------------------------------------------
       
   796 // CESMRNcsAifEditor::AddAddressL()
       
   797 // -----------------------------------------------------------------------------
       
   798 //
       
   799 void CESMRNcsAifEditor::AddAddressL(
       
   800     const TDesC& aDisplayName,
       
   801     const TDesC& aEmail,
       
   802     TBool aDisplayFull )
       
   803     {
       
   804     FUNC_LOG;
       
   805     AddAddressL( CESMRNcsAifEntry::NewL( aDisplayName, aEmail, aDisplayFull ) );
       
   806     }
       
   807 
       
   808 // -----------------------------------------------------------------------------
       
   809 // CESMRNcsAifEditor::AddAddressL()
       
   810 // -----------------------------------------------------------------------------
       
   811 //
       
   812 void CESMRNcsAifEditor::AddAddressL( CESMRNcsAifEntry* aNewEntry )
       
   813     {
       
   814     FUNC_LOG;
       
   815     int idx;
       
   816     // Check for duplicate display names
       
   817     for (idx=0;idx<iArray.Count();idx++)
       
   818         {
       
   819         if (iArray[idx]->IsSameDN(*aNewEntry))
       
   820             {
       
   821             iArray[idx]->SetDup();
       
   822             aNewEntry->SetDup();
       
   823             }
       
   824         }
       
   825 
       
   826     // Find the location where we need to insert the address
       
   827     TInt pos = CursorPos();
       
   828     for (idx=0;idx<iArray.Count();idx++)
       
   829         {
       
   830         if (pos <= iArray[idx]->Start()) break;
       
   831         }
       
   832     if (idx == iArray.Count())
       
   833         {
       
   834         // Tack the address onto the end of the array
       
   835         iArray.Append(aNewEntry);
       
   836         }
       
   837     else
       
   838         {
       
   839         iArray.Insert(aNewEntry,idx);
       
   840         }
       
   841     RepositionEntriesL( aNewEntry );
       
   842     }
       
   843 
       
   844 // -----------------------------------------------------------------------------
       
   845 // CESMRNcsAifEditor::RecalculateEntryPositions()
       
   846 // The text has changed, so recalculate the positions of the items.
       
   847 // -----------------------------------------------------------------------------
       
   848 //
       
   849 void CESMRNcsAifEditor::RecalculateEntryPositions()
       
   850     {
       
   851     FUNC_LOG;
       
   852 
       
   853     TInt pos(0);
       
   854     TInt idx(0);
       
   855     TInt error(0);
       
   856     for	(;idx<iArray.Count();idx++)
       
   857     	{
       
   858     	    TRAP( error, pos = FindTextL( &iArray[idx]->DisplayString(), pos,
       
   859     	        CEikEdwin::EFindCaseSensitive | CEikEdwin::ENoBusyMessage ) );
       
   860     	    ASSERT( KErrNone == error && KErrNotFound != pos );
       
   861     	    if(pos != iArray[idx]->Start())
       
   862     	    	{
       
   863     	    	break;
       
   864     	    	}
       
   865     	    pos += iArray[idx]->Length();
       
   866     	}
       
   867 
       
   868     if(idx != iArray.Count())
       
   869     	{
       
   870 		for (; idx<iArray.Count(); idx++ )
       
   871 			{
       
   872 			pos = iArray[idx]->SetPos( pos );
       
   873 			pos++; // for whitespace
       
   874 			}
       
   875     	}
       
   876     }
       
   877 // -----------------------------------------------------------------------------
       
   878 // CESMRNcsAifEditor::RepositionEntriesL()
       
   879 // -----------------------------------------------------------------------------
       
   880 //
       
   881 void CESMRNcsAifEditor::RepositionEntriesL( const CESMRNcsAifEntry* aPosEntry )
       
   882     {
       
   883     FUNC_LOG;
       
   884     TInt pos = 0;
       
   885     CESMRNcsAifEntry* aEntry;
       
   886     for (int i=0;i<iArray.Count();i++)
       
   887         {
       
   888         aEntry = iArray[i];
       
   889         pos = aEntry->SetPos( pos );
       
   890         pos++; // for whitespace
       
   891         }
       
   892 
       
   893     // Reset the text
       
   894     SetCursorPosL( 0, EFalse ); //In case the cursor pos is invalid
       
   895     HBufC* text = NULL;
       
   896     text = GetFormattedAddressListL( iArray );
       
   897     CleanupStack::PushL( text );
       
   898 
       
   899     // text lenght plus one to ensure the formatting
       
   900     // used is full, not band formatting.
       
   901     SetUpperFullFormattingLength( text->Length() + 1 );
       
   902 
       
   903     // The stupid control will reset all atributes if the text is blank ( font color, etc.).
       
   904     if ( text->Length() == 0 )
       
   905         {
       
   906         CleanupStack::PopAndDestroy( text );
       
   907         text = KEmptySpace().AllocL();
       
   908         CleanupStack::PushL( text );
       
   909         SetTextL( text );
       
   910         }
       
   911     else
       
   912         {
       
   913         SetTextL( text );
       
   914         }
       
   915 
       
   916     CleanupStack::PopAndDestroy( text );
       
   917     HandleTextChangedL();
       
   918 
       
   919     // Set the cursor at the end of the given entry
       
   920     if ( !aPosEntry )
       
   921         {
       
   922         SetCursorPosL( 0, EFalse );
       
   923         }
       
   924     else
       
   925         {
       
   926         SetCursorPosL( aPosEntry->End(), EFalse );
       
   927         }
       
   928     }
       
   929 // -----------------------------------------------------------------------------
       
   930 // CESMRNcsAifEditor::GetLookupTextLC()
       
   931 // -----------------------------------------------------------------------------
       
   932 //
       
   933 HBufC* CESMRNcsAifEditor::GetLookupTextLC() const
       
   934     {
       
   935     FUNC_LOG;
       
   936     HBufC* text = GetTextInHBufL();
       
   937 
       
   938     if (text == NULL) return NULL;
       
   939 
       
   940     CleanupStack::PushL( text );
       
   941     TPtr ptr( text->Des() );
       
   942     ptr = ptr.LeftTPtr( CursorPos() );
       
   943     TChar semiColon(KSemiColon);
       
   944     TInt location = ptr.LocateReverse( semiColon );
       
   945     if( location != KErrNotFound )
       
   946         {
       
   947         ptr = ptr.RightTPtr( ptr.Length() - location -1 );
       
   948         ptr.TrimLeft();
       
   949         }
       
   950     return text;
       
   951     }
       
   952 // -----------------------------------------------------------------------------
       
   953 // CESMRNcsAifEditor::GetFormattedAddressListLC()
       
   954 // -----------------------------------------------------------------------------
       
   955 //
       
   956 HBufC* CESMRNcsAifEditor::GetFormattedAddressListLC(
       
   957     RPointerArray<CESMRNcsAifEntry>& aEntries,
       
   958     TBool aDisplayList ) const
       
   959     {
       
   960     FUNC_LOG;
       
   961     TInt length = CalculateAddressListLength( aEntries, aDisplayList );
       
   962     if( length <= 0 )
       
   963         {
       
   964         return HBufC::NewLC(0);
       
   965         }
       
   966 
       
   967     HBufC* buf = HBufC::NewLC( length );
       
   968     TPtr ptr = buf->Des();
       
   969 
       
   970     TInt count = aEntries.Count();
       
   971     for( TInt i = 0; i < count; i++ )
       
   972         {
       
   973         if ( aDisplayList )
       
   974             {
       
   975             ptr.Append( aEntries[i]->DisplayString() );
       
   976             }
       
   977         else
       
   978             {
       
   979             ptr.Append( aEntries[i]->Address().EmailAddress() );
       
   980             ptr.Append( KAddressDelimeterSemiColon );
       
   981             }
       
   982 
       
   983         // append whitespace, if not in the last entry
       
   984         if ( i < count - 1 )
       
   985             {
       
   986             ptr.Append( KEmptySpace );
       
   987             }
       
   988         }
       
   989 
       
   990     return buf;
       
   991     }
       
   992 // -----------------------------------------------------------------------------
       
   993 // CESMRNcsAifEditor::GetFormattedAddressListL()
       
   994 // -----------------------------------------------------------------------------
       
   995 //
       
   996 HBufC* CESMRNcsAifEditor::GetFormattedAddressListL(
       
   997     RPointerArray<CESMRNcsAifEntry>& aEntries,
       
   998     TBool aDisplayList ) const
       
   999     {
       
  1000     FUNC_LOG;
       
  1001     HBufC* buf = GetFormattedAddressListLC( aEntries, aDisplayList );
       
  1002     CleanupStack::Pop( buf );
       
  1003     return buf;
       
  1004     }
       
  1005 // -----------------------------------------------------------------------------
       
  1006 // CESMRNcsAifEditor::CalculateAddressListLength()
       
  1007 // -----------------------------------------------------------------------------
       
  1008 //
       
  1009 TInt CESMRNcsAifEditor::CalculateAddressListLength(
       
  1010     RPointerArray<CESMRNcsAifEntry>& aEntries,
       
  1011     TBool aDisplayList ) const
       
  1012     {
       
  1013     FUNC_LOG;
       
  1014     TInt length = 0;
       
  1015     TInt count = aEntries.Count();
       
  1016     for( TInt i = 0; i < count; i++ )
       
  1017         {
       
  1018         CESMRNcsAifEntry* aEntry = aEntries[ i ];
       
  1019         if ( !aEntry  ) continue;
       
  1020         if ( aDisplayList )
       
  1021             {
       
  1022             length += aEntry->Length();
       
  1023             }
       
  1024         else
       
  1025             {
       
  1026             // +1 is for semicolon
       
  1027             length += aEntry->Address().EmailAddress().Length() + 1;
       
  1028             }
       
  1029         }
       
  1030 
       
  1031     // add one white space after that so the format is
       
  1032     // aa(at)bb.com; cc(at)dd.com; ee(at)ff.com
       
  1033     if( count > 1 )
       
  1034         {
       
  1035         // ( count - 1 ) we do need white space after the last address
       
  1036         length += count - 1 ;
       
  1037         }
       
  1038 
       
  1039     if( aEntries.Count() > 0 )
       
  1040         {
       
  1041         length += 2;
       
  1042         }
       
  1043 
       
  1044     return length;
       
  1045     }
       
  1046 
       
  1047 // -----------------------------------------------------------------------------
       
  1048 // CESMRNcsAifEditor::UpdateAddressAutoCompletionL()
       
  1049 // -----------------------------------------------------------------------------
       
  1050 //
       
  1051 void CESMRNcsAifEditor::UpdateAddressAutoCompletionL()
       
  1052     {
       
  1053     FUNC_LOG;
       
  1054     HBufC* text = GetNonEntryTextLC();
       
  1055 
       
  1056     if( text )
       
  1057         {
       
  1058         iAddressPopupList->UpdatePopupContactListL( *text, EFalse );
       
  1059         CleanupStack::PopAndDestroy( text );
       
  1060         }
       
  1061     else
       
  1062         {
       
  1063         iAddressPopupList->UpdatePopupContactListL( KNullDesC, EFalse );
       
  1064         }
       
  1065     }
       
  1066 // -----------------------------------------------------------------------------
       
  1067 // CESMRNcsAifEditor::UpdateAddressAutoCompletionL()
       
  1068 // -----------------------------------------------------------------------------
       
  1069 //
       
  1070 void CESMRNcsAifEditor::UpdateAddressAutoCompletionL(
       
  1071     const TCursorSelection& aSelection )
       
  1072     {
       
  1073     FUNC_LOG;
       
  1074     TInt length = aSelection.Length();
       
  1075     HBufC* text = HBufC::NewLC( length );
       
  1076     TPtr ptr = text->Des();
       
  1077     Text()->Extract( ptr, aSelection.LowerPos(), length );
       
  1078     ptr.Trim();
       
  1079     if ( text->Length() )
       
  1080         {
       
  1081         iAddressPopupList->UpdatePopupContactListL( *text, EFalse );
       
  1082         }
       
  1083     else
       
  1084         {
       
  1085         iAddressPopupList->ClosePopupContactListL();
       
  1086         }
       
  1087     CleanupStack::PopAndDestroy( text );
       
  1088     }
       
  1089 
       
  1090 // -----------------------------------------------------------------------------
       
  1091 // CESMRNcsAifEditor::UpdateAddressListAllL()
       
  1092 // -----------------------------------------------------------------------------
       
  1093 //
       
  1094 void CESMRNcsAifEditor::UpdateAddressListAllL()
       
  1095     {
       
  1096     FUNC_LOG;
       
  1097     iAddressPopupList->UpdatePopupContactListL( KNullDesC, ETrue );
       
  1098     }
       
  1099 
       
  1100 void CESMRNcsAifEditor::UpdateDuplicateEntryMarkings()
       
  1101     {
       
  1102     FUNC_LOG;
       
  1103     const TInt entryCount = iArray.Count();
       
  1104     for ( TInt ii = entryCount - 1; ii >= 0; --ii )
       
  1105         {
       
  1106         TBool duplicateFound = EFalse;
       
  1107         for ( TInt jj = entryCount - 1; jj >= 0; --jj )
       
  1108             {
       
  1109             if ( ii != jj && iArray[ii]->IsSameDN( *iArray[jj] ) )
       
  1110                 {
       
  1111                 duplicateFound = ETrue;
       
  1112                 iArray[jj]->SetDup( ETrue );
       
  1113                 }
       
  1114             }
       
  1115         iArray[ii]->SetDup( duplicateFound );
       
  1116         }
       
  1117     }
       
  1118 
       
  1119 // -----------------------------------------------------------------------------
       
  1120 // CESMRNcsAifEditor::CopyToClipboardL
       
  1121 // -----------------------------------------------------------------------------
       
  1122 void CESMRNcsAifEditor::CopyToClipboardL( const TDesC &aBuf )
       
  1123     {
       
  1124     FUNC_LOG;
       
  1125     CClipboard* cb = CClipboard::NewForWritingLC( CCoeEnv::Static()->FsSession() );
       
  1126 
       
  1127     cb->StreamDictionary().At( KClipboardUidTypePlainText );
       
  1128 
       
  1129     CPlainText* plainText = CPlainText::NewL();
       
  1130     CleanupStack::PushL( plainText );
       
  1131 
       
  1132     plainText->InsertL( 0 , aBuf );
       
  1133 
       
  1134     plainText->CopyToStoreL( cb->Store(), cb->StreamDictionary(), 0, plainText->DocumentLength() );
       
  1135 
       
  1136     CleanupStack::PopAndDestroy( plainText );
       
  1137     cb->CommitL();
       
  1138     CleanupStack::PopAndDestroy( cb );
       
  1139     }
       
  1140 // -----------------------------------------------------------------------------
       
  1141 // CESMRNcsAifEditor::HandleContactDeletionL
       
  1142 // -----------------------------------------------------------------------------
       
  1143 void CESMRNcsAifEditor::HandleContactDeletionL()
       
  1144     {
       
  1145     FUNC_LOG;
       
  1146     const TInt count(iArray.Count());
       
  1147     for (TInt i=count-1;i>=0;--i)
       
  1148         {
       
  1149         CESMRNcsAifEntry* entry = iArray[i];
       
  1150         if ( FindTextL( &entry->DisplayString(), 0, 0 ) == KErrNotFound )
       
  1151             {
       
  1152             iArray.Remove(i);
       
  1153             delete entry;
       
  1154             }
       
  1155         }
       
  1156     }
       
  1157 // -----------------------------------------------------------------------------
       
  1158 // CESMRNcsAifEditor::HandleTextUpdateL
       
  1159 // -----------------------------------------------------------------------------
       
  1160 void CESMRNcsAifEditor::HandleTextUpdateL()
       
  1161     {
       
  1162     FUNC_LOG;
       
  1163     RecalculateEntryPositions();
       
  1164     TCursorSelection textSelection = NonEntryTextAtPos( CursorPos() );
       
  1165     if ( textSelection.Length() )
       
  1166         {
       
  1167         // Check non-entry text for complete entries.
       
  1168         HandleTextUpdateL( textSelection );
       
  1169         }
       
  1170     UpdateAddressAutoCompletionL( textSelection );
       
  1171     }
       
  1172 // -----------------------------------------------------------------------------
       
  1173 // CESMRNcsAifEditor::HandleTextUpdateL
       
  1174 // -----------------------------------------------------------------------------
       
  1175 void CESMRNcsAifEditor::HandleTextUpdateL( TCursorSelection& aSelection )
       
  1176     {
       
  1177     FUNC_LOG;
       
  1178     TInt firstCharacter = aSelection.LowerPos();
       
  1179     TInt lastCharacter = aSelection.HigherPos();
       
  1180     for ( TInt ii = firstCharacter; ii <= lastCharacter; ++ii )
       
  1181         {
       
  1182         TChar character = CharAtPos( ii );
       
  1183         if ( IsSentinel( character ) )
       
  1184             {
       
  1185             if ( character == KComma )
       
  1186                 {
       
  1187                 // Replace comma with semicolon
       
  1188                 CPlainText* text = Text();
       
  1189                 text->DeleteL( ii, 1 );
       
  1190                 text->InsertL( ii, KSemiColon );
       
  1191                 }
       
  1192 
       
  1193             // Create new entry.
       
  1194             AddEntryL( firstCharacter, ii );
       
  1195             TCursorSelection tmpSelection = NonEntryTextAtPos( CursorPos() );
       
  1196             firstCharacter = tmpSelection.LowerPos();
       
  1197             lastCharacter = tmpSelection.HigherPos();
       
  1198             }
       
  1199         }
       
  1200     aSelection.SetSelection( lastCharacter, firstCharacter );
       
  1201 
       
  1202     }
       
  1203 
       
  1204 // ---------------------------------------------------------------------------
       
  1205 // Handles navigation event.
       
  1206 // ---------------------------------------------------------------------------
       
  1207 //
       
  1208 void CESMRNcsAifEditor::HandleNavigationEventL()
       
  1209     {
       
  1210     FUNC_LOG;
       
  1211     // Close the contact popup when cursor is moved withing the field to make it less distracting.
       
  1212     // It's reopened when user types something.
       
  1213     iAddressPopupList->ClosePopupContactListL();
       
  1214     }
       
  1215 
       
  1216 // ---------------------------------------------------------------------------
       
  1217 // Gets the range of non-entry text at the given position.
       
  1218 // ---------------------------------------------------------------------------
       
  1219 //
       
  1220 TCursorSelection CESMRNcsAifEditor::NonEntryTextAtPos( TUint aPosition ) const
       
  1221     {
       
  1222     FUNC_LOG;
       
  1223     TCursorSelection text( TextLength(), 0 );
       
  1224     for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
       
  1225         {
       
  1226         if ( iArray[ii]->Includes( aPosition - 1) )
       
  1227             {
       
  1228             // Given position is included in existing entry
       
  1229             text.SetSelection( 0, 0 );
       
  1230             break;
       
  1231             }
       
  1232         else if ( iArray[ii]->LowerPos() >= aPosition )
       
  1233             {
       
  1234             // Found entry after the given position
       
  1235             text.iCursorPos = iArray[ii]->LowerPos();
       
  1236             }
       
  1237         else if ( iArray[ii]->HigherPos() < aPosition )
       
  1238             {
       
  1239             // Found first entry before given position
       
  1240             text.iAnchorPos = iArray[ii]->HigherPos();
       
  1241             break;
       
  1242             }
       
  1243         }
       
  1244     return text;
       
  1245     }
       
  1246 
       
  1247 // ---------------------------------------------------------------------------
       
  1248 // Gets the range of text immediatelly before given position that does not
       
  1249 // belong to any entry.
       
  1250 // ---------------------------------------------------------------------------
       
  1251 //
       
  1252 TCursorSelection CESMRNcsAifEditor::NonEntryTextBeforePos( TUint aPosition ) const
       
  1253     {
       
  1254     FUNC_LOG;
       
  1255     TCursorSelection text( aPosition, 0 );
       
  1256     for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
       
  1257         {
       
  1258         if ( iArray[ii]->Includes( aPosition - 1 ) )
       
  1259             {
       
  1260             // Given position is included in existing entry
       
  1261             text.SetSelection( 0, 0 );
       
  1262             break;
       
  1263             }
       
  1264         else if ( iArray[ii]->HigherPos() < aPosition )
       
  1265             {
       
  1266             // Found first existing entry before given position
       
  1267             text.SetSelection( aPosition, iArray[ii]->HigherPos() );
       
  1268             break;
       
  1269             }
       
  1270         }
       
  1271     return text;
       
  1272     }
       
  1273 
       
  1274 // ---------------------------------------------------------------------------
       
  1275 // Checks whether given character is considered as sentinel.
       
  1276 // ---------------------------------------------------------------------------
       
  1277 //
       
  1278 TBool CESMRNcsAifEditor::IsSentinel( TChar aCharacter ) const
       
  1279     {
       
  1280     FUNC_LOG;
       
  1281     return ( aCharacter == KSemiColon ||
       
  1282         aCharacter == KComma );
       
  1283     }
       
  1284 
       
  1285 // ---------------------------------------------------------------------------
       
  1286 // Checks whether given event is considered as navigation event.
       
  1287 // ---------------------------------------------------------------------------
       
  1288 //
       
  1289 TBool CESMRNcsAifEditor::IsNavigationKey( const TKeyEvent& aKeyEvent ) const
       
  1290     {
       
  1291     FUNC_LOG;
       
  1292     return ( aKeyEvent.iCode == EKeyLeftArrow ||
       
  1293              aKeyEvent.iCode == EKeyRightArrow ||
       
  1294              aKeyEvent.iCode == EKeyUpArrow ||
       
  1295              aKeyEvent.iCode == EKeyDownArrow );
       
  1296     }
       
  1297 
       
  1298 // ---------------------------------------------------------------------------
       
  1299 // Creates new entry from the specified section of the the input field.
       
  1300 // ---------------------------------------------------------------------------
       
  1301 //
       
  1302 void CESMRNcsAifEditor::AddEntryL( TInt aStart, TInt aEnd )
       
  1303     {
       
  1304     FUNC_LOG;
       
  1305     // Get the text for the entry (excluding the delimiter)
       
  1306     TInt length = aEnd - aStart;
       
  1307     HBufC* text = HBufC::NewLC( length );
       
  1308     TPtr ptr = text->Des();
       
  1309     Text()->Extract( ptr, aStart, length );
       
  1310     ptr.Trim();
       
  1311     if ( text->Length() )
       
  1312         {
       
  1313         AddAddressL( KNullDesC(), *text );
       
  1314         }
       
  1315     CleanupStack::PopAndDestroy( text );
       
  1316     }
       
  1317 // End of File
       
  1318