emailuis/emailui/src/ncsaifeditor.cpp
branchRCL_3
changeset 73 c8382f7b54ef
parent 64 3533d4323edc
child 80 726fba06891a
equal deleted inserted replaced
70:968773a0b6ef 73:c8382f7b54ef
   214     const TDesC& otherDn = entry.Address().DisplayName();
   214     const TDesC& otherDn = entry.Address().DisplayName();
   215     return ownDn.Compare( otherDn ) == 0;
   215     return ownDn.Compare( otherDn ) == 0;
   216     }
   216     }
   217 
   217 
   218 // ---------------------------------------------------------------------------
   218 // ---------------------------------------------------------------------------
   219 // constructor/destructor
   219 // Constructor
   220 // ---------------------------------------------------------------------------
   220 // ---------------------------------------------------------------------------
   221 //
   221 //
   222 CNcsAifEditor::CNcsAifEditor(
   222 CNcsAifEditor::CNcsAifEditor(
   223     MNcsFieldSizeObserver* aSizeObserver, const TDesC& aCaptionText ) 
   223     MNcsFieldSizeObserver* aSizeObserver, const TDesC& aCaptionText ) 
   224     : CNcsEditor( aSizeObserver, ETrue, ENcsEditorAddress, aCaptionText ), iAddressPopupList( NULL ),
   224     : CNcsEditor( aSizeObserver, ETrue, ENcsEditorAddress, aCaptionText ),
       
   225     iAddressPopupList( NULL ),
   225     iAddLeftover( ETrue )
   226     iAddLeftover( ETrue )
   226     {
   227     {
   227     FUNC_LOG;
   228     FUNC_LOG;
   228 	SetEdwinObserver( this );
   229     SetEdwinObserver( this );
   229     }
   230     }
   230 
   231 
   231 // ---------------------------------------------------------------------------
   232 // ---------------------------------------------------------------------------
   232 // second phase constructor
   233 // second phase constructor
   233 // ---------------------------------------------------------------------------
   234 // ---------------------------------------------------------------------------
   246 // ---------------------------------------------------------------------------
   247 // ---------------------------------------------------------------------------
   247 //
   248 //
   248 CNcsAifEditor::~CNcsAifEditor()
   249 CNcsAifEditor::~CNcsAifEditor()
   249     {
   250     {
   250     FUNC_LOG;
   251     FUNC_LOG;
   251 	iArray.ResetAndDestroy();
   252     iArray.ResetAndDestroy();
   252 	iAddressArray.Reset();
   253     iAddressArray.Reset();
   253 	if ( iAsyncCallBack )
   254     if ( iAsyncCallBack )
   254 	    {
   255         {
   255 	    iAsyncCallBack->Cancel();
   256         iAsyncCallBack->Cancel();
   256 	    delete iAsyncCallBack;
   257         delete iAsyncCallBack;
   257 	    }
   258         }
   258     }
   259     }
   259 
       
   260 
   260 
   261 // -----------------------------------------------------------------------------
   261 // -----------------------------------------------------------------------------
   262 // CNcsAifEditor::CursorLineNumber() const
   262 // CNcsAifEditor::CursorLineNumber() const
   263 // -----------------------------------------------------------------------------
   263 // -----------------------------------------------------------------------------
   264 //
   264 //
   309     // Check if we need to highlight a contact
   309     // Check if we need to highlight a contact
   310     if ( ret == EKeyWasNotConsumed )
   310     if ( ret == EKeyWasNotConsumed )
   311         {
   311         {
   312         ret = SetEditorSelectionL( aKeyEvent, aType );
   312         ret = SetEditorSelectionL( aKeyEvent, aType );
   313         }
   313         }
   314     
   314 
   315     //when press a key down, record the coursor position
   315     //when press a key down, record the coursor position
   316     if ( aType == EEventKeyDown )
   316     if ( aType == EEventKeyDown )
   317     	{
   317         {
   318     	iLastTimeCursorPos = CursorPos();
   318         iLastTimeCursorPos = CursorPos();
   319     	}
   319         }
   320 
   320 
   321     if ( ret == EKeyWasNotConsumed )
   321     if ( ret == EKeyWasNotConsumed )
   322         {
   322         {
   323         // enter completes the address entry
   323         // enter completes the address entry
   324         if( aType == EEventKey && (aKeyEvent.iCode == EKeyEnter || 
   324         if ( aType == EEventKey && ( aKeyEvent.iCode == EKeyEnter || 
   325         	aKeyEvent.iScanCode == EStdKeyEnter) )
   325              aKeyEvent.iScanCode == EStdKeyEnter ) )
   326         	{
   326             {
   327         	// make sure there is really some text inputted 
   327             // make sure there is really some text inputted 
       
   328             const TInt cursorPos = CursorPos();
       
   329             TCursorSelection selection = NonEntryTextAtPos( cursorPos );
       
   330 
       
   331             const TInt length = selection.Length();
       
   332             if ( length > 0 )
       
   333                 {
       
   334                 HBufC* text = HBufC::NewLC( length );
       
   335                 TPtr ptr = text->Des();
       
   336                 Text()->Extract( ptr, selection.LowerPos(), length );
       
   337                 ptr.Trim();
       
   338 
       
   339                 // complete the entry by adding a semicolon, 
       
   340                 // address will be added in HandleTextUpdateL
       
   341                 if ( ptr.Length() > 0 )
       
   342                     {
       
   343                     Text()->InsertL( cursorPos, KCharAddressDelimeterSemiColon );
       
   344                     HandleTextChangedL();
       
   345                     SetCursorPosL( cursorPos + 1, EFalse );
       
   346                     iLastTimeCursorPos = CursorPos();
       
   347                     HandleTextUpdateL();
       
   348                     }
       
   349 
       
   350                 CleanupStack::PopAndDestroy( text );
       
   351                 }
       
   352             }
       
   353         else if ( IsCharacterKey( aKeyEvent ) )
       
   354             {
       
   355             PrepareForTextInputL( CursorPos() );
       
   356             }
       
   357         iTextSelection = Selection();
       
   358         ret = CNcsEditor::OfferKeyEventL( aKeyEvent, aType );
       
   359         }
       
   360 
       
   361     // for Korean we need to simulate event 'text update' as FEP
       
   362     // doesn't send it and the MRU is not shown
       
   363     if ( User::Language() == ELangKorean )
       
   364         {
       
   365         if ( ret == EKeyWasNotConsumed && aType == EEventKeyUp )
       
   366             {
   328             TInt cursorPos( CursorPos() );
   367             TInt cursorPos( CursorPos() );
   329         	
   368 
   330             TCursorSelection selection = NonEntryTextAtPos( cursorPos );
   369             TCursorSelection selection = NonEntryTextAtPos( cursorPos );
   331             
   370             
   332             TInt length( selection.Length() );
   371             TInt length( selection.Length() );
   333             
   372             
   334             HBufC* text = HBufC::NewLC( length );
   373             HBufC* text = HBufC::NewLC( length );
   335             TPtr ptr = text->Des();
   374             TPtr ptr = text->Des();
   336             Text()->Extract( ptr, selection.LowerPos(), length );
   375             Text()->Extract( ptr, selection.LowerPos(), length );
   337             ptr.Trim();
   376             ptr.Trim();
   338             
   377         
   339             // complete the entry by adding a semicolon, 
   378             if ( TFsEmailUiUtility::IsKoreanWord( ptr ) )
   340             // address will be added in HandleTextUpdateL
   379                 {
   341             if( ptr.Length() > 0 )
   380                 HandleTextUpdateDeferred();
   342             	{            
   381                 }
   343 				Text()->InsertL( cursorPos, KCharAddressDelimeterSemiColon );
   382         
   344 				HandleTextChangedL();
   383             CleanupStack::PopAndDestroy( text );
   345 				SetCursorPosL( cursorPos + 1, EFalse );
   384             }
   346             	}
       
   347             
       
   348             CleanupStack::PopAndDestroy( text );            
       
   349         	}
       
   350         iTextSelection = Selection();        
       
   351         ret = CNcsEditor::OfferKeyEventL( aKeyEvent, aType );
       
   352         }
   385         }
   353     
   386     
   354     return ret;
   387     return ret;
   355     }
   388     }
   356 
   389 
   398     // We need to offer the key to the editor control first so it can
   431     // We need to offer the key to the editor control first so it can
   399     // move the cursor for us.  Then we check if it's in an entry.
   432     // move the cursor for us.  Then we check if it's in an entry.
   400     if ( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow )
   433     if ( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow )
   401         {
   434         {
   402         CompleteEntryL();
   435         CompleteEntryL();
   403 		
   436 
   404         response = CNcsEditor::OfferKeyEventL( aKeyEvent,aType );
   437         response = CNcsEditor::OfferKeyEventL( aKeyEvent,aType );
   405         if ( response == EKeyWasConsumed ) 
   438         if ( response == EKeyWasConsumed ) 
   406             {
   439             {
   407             // We're moving to a new line.
   440             // We're moving to a new line.
   408             entry = GetEntryAt( CursorPos() );
   441             entry = GetEntryAt( CursorPos() );
   411                 SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
   444                 SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
   412                 }
   445                 }
   413             }
   446             }
   414         }
   447         }
   415     // Check if the cursor is in any of the addresses
   448     // Check if the cursor is in any of the addresses
   416     else if( aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyBackspace ) 
   449     else if ( aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyBackspace ) 
   417         {
   450         {
   418         // We're moving left, but haven't yet.
   451         // We're moving left, but haven't yet.
   419         entry = GetEntryAt( CursorPos(), EDirectionLeft );
   452         const TInt cursorPos = CursorPos();
       
   453         entry = GetEntryAt( cursorPos, EDirectionLeft );
   420         if ( entry )
   454         if ( entry )
   421             {
   455             {
   422             if ( selection.Length() && aKeyEvent.iCode == EKeyLeftArrow)
   456             if ( selection.Length() && aKeyEvent.iCode == EKeyLeftArrow)
   423                 {
   457                 {
   424                 // Adds or removes the entry from the current selection.
   458                 // Adds or removes the entry from the current selection.
   429                 {
   463                 {
   430                 SetSelectionL( entry->LowerPos(), entry->HigherPos() );
   464                 SetSelectionL( entry->LowerPos(), entry->HigherPos() );
   431                 response = EKeyWasConsumed;
   465                 response = EKeyWasConsumed;
   432                 }
   466                 }
   433             }
   467             }
   434         }
   468         else
   435     else if( aKeyEvent.iCode == EKeyRightArrow || aKeyEvent.iCode == EKeyDelete )
   469             {
       
   470             // Complete entry, if cursor is being moved to the previous row.
       
   471             TCursorSelection selection = NonEntryTextAndSpaceAtPos( cursorPos );
       
   472             if ( cursorPos > 0 && selection.LowerPos() + 1 == cursorPos )
       
   473                 {
       
   474                 if ( IsDelimiter( CharAtPos( selection.LowerPos() ) ) )
       
   475                     {
       
   476                     CompleteEntryL();
       
   477                     SetCursorPosL( cursorPos, EFalse );
       
   478                     }
       
   479                 }
       
   480             }
       
   481         }
       
   482     else if ( aKeyEvent.iCode == EKeyRightArrow || aKeyEvent.iCode == EKeyDelete )
   436         {
   483         {
   437         // We're moving right, but haven't yet.
   484         // We're moving right, but haven't yet.
   438         entry = GetEntryAt( CursorPos(), EDirectionRight );
   485         const TInt cursorPos = CursorPos();
       
   486         entry = GetEntryAt( cursorPos, EDirectionRight );
   439         if ( entry )
   487         if ( entry )
   440             {
   488             {
   441             if ( selection.Length() && aKeyEvent.iCode == EKeyRightArrow  )
   489             if ( selection.Length() && aKeyEvent.iCode == EKeyRightArrow  )
   442                 {
   490                 {
   443                 // Adds or removes the entry form the current selection.
   491                 // Adds or removes the entry form the current selection.
   446                 }
   494                 }
   447             else if ( !selection.Length() )
   495             else if ( !selection.Length() )
   448                 {
   496                 {
   449                 SetSelectionL( entry->HigherPos(), entry->LowerPos() );
   497                 SetSelectionL( entry->HigherPos(), entry->LowerPos() );
   450                 response = EKeyWasConsumed;
   498                 response = EKeyWasConsumed;
       
   499                 }
       
   500             }
       
   501         else
       
   502             {
       
   503             // Complete entry, if cursor is being moved to the next row.
       
   504             TCursorSelection selection = NonEntryTextAndSpaceAtPos( cursorPos );
       
   505             if ( cursorPos > 0 && selection.HigherPos() - 1 == cursorPos )
       
   506                 {
       
   507                 if ( IsDelimiter( CharAtPos( selection.HigherPos() - 1 ) ) )
       
   508                     {
       
   509                     CompleteEntryL();
       
   510                     }
   451                 }
   511                 }
   452             }
   512             }
   453         }
   513         }
   454     // to fix problems with updating CBA when hash key is pressed and hold
   514     // to fix problems with updating CBA when hash key is pressed and hold
   455     else if ( aKeyEvent.iScanCode == EStdKeyHash ) 
   515     else if ( aKeyEvent.iScanCode == EStdKeyHash ) 
   505                     {
   565                     {
   506                     entry = iArray[ii];
   566                     entry = iArray[ii];
   507                     break;
   567                     break;
   508                     }
   568                     }
   509                 }
   569                 }
   510             
   570 
       
   571             SetCursorVisible( EFalse );
   511             ClearSelectionL();
   572             ClearSelectionL();
   512             
   573             RepositionEntries( entry );
   513             RepositionEntriesL( entry );
   574             SetCursorVisible( ETrue );
   514 
   575 
   515             // The key event is set consumed only on delete and backpace
   576             // The key event is set consumed only on delete and backpace
   516             // events, other events need to be forwarded to the editor.
   577             // events, other events need to be forwarded to the editor.
   517             if ( aKeyEvent.iCode == EKeyDelete || 
   578             if ( aKeyEvent.iCode == EKeyDelete || 
   518                  aKeyEvent.iCode == EKeyBackspace )
   579                  aKeyEvent.iCode == EKeyBackspace )
   527 // ---------------------------------------------------------------------------
   588 // ---------------------------------------------------------------------------
   528 // CNcsAifEditor::DoCharChangeL
   589 // CNcsAifEditor::DoCharChangeL
   529 // ---------------------------------------------------------------------------
   590 // ---------------------------------------------------------------------------
   530 //
   591 //
   531 void CNcsAifEditor::DoCharChangeL()
   592 void CNcsAifEditor::DoCharChangeL()
   532 	{
   593     {
   533     FUNC_LOG;
   594     FUNC_LOG;
   534 	RecalculateEntryPositions();
   595     RecalculateEntryPositions();
   535 
   596 
   536 	TChar previousChar = CharAtPos( CursorPos() - 1 );
   597     TChar previousChar = CharAtPos( CursorPos() - 1 );
   537 	TBool sentinel = ( previousChar == KCharAddressDelimeterSemiColon || 
   598     TBool sentinel = ( previousChar == KCharAddressDelimeterSemiColon || 
   538 	    previousChar == KCharAddressDelimeterComma );
   599         previousChar == KCharAddressDelimeterComma );
   539 	if ( sentinel )
   600     if ( sentinel )
   540         {
   601         {
   541         // if comma was pressed we replace it with semicolon
   602         // if comma was pressed we replace it with semicolon
   542 		if ( previousChar == KCharAddressDelimeterComma )
   603         if ( previousChar == KCharAddressDelimeterComma )
   543             {
   604             {
   544 			CPlainText* text = Text();
   605             CPlainText* text = Text();
   545 			text->DeleteL( CursorPos() - 1, 1 );
   606             text->DeleteL( CursorPos() - 1, 1 );
   546 			text->InsertL( CursorPos() - 1, KCharAddressDelimeterSemiColon );
   607             text->InsertL( CursorPos() - 1, KCharAddressDelimeterSemiColon );
   547             }
   608             }
   548 		ParseNewAddressL();
   609         ParseNewAddressL();
   549         }
   610         }
   550 	UpdateAddressAutoCompletionL();
   611     UpdateAddressAutoCompletionL();
   551 	}
   612     }
   552 
   613 
   553 // ---------------------------------------------------------------------------
   614 // ---------------------------------------------------------------------------
   554 // CNcsAddressInputField::CharAtPos
   615 // CNcsAddressInputField::CharAtPos
   555 // ---------------------------------------------------------------------------
   616 // ---------------------------------------------------------------------------
   556 //
   617 //
   557 TChar CNcsAifEditor::CharAtPos( TInt aPos ) const
   618 TChar CNcsAifEditor::CharAtPos( TInt aPos ) const
   558     {
   619     {
   559     FUNC_LOG;
   620     FUNC_LOG;
   560 	if ( aPos >= 0 && aPos < TextLength() )
   621     if ( aPos >= 0 && aPos < TextLength() )
   561         {
   622         {
   562 		TBuf<1> buf;
   623         TBuf<1> buf;
   563 		Text()->Extract( buf, aPos, 1 );
   624         Text()->Extract( buf, aPos, 1 );
   564 		return buf[0];
   625         return buf[0];
   565         }
   626         }
   566 	else
   627     else
   567         {
   628         {
   568 		return 0;
   629         return 0;
   569         }
   630         }
   570     }
   631     }
   571 
   632 
   572 // -----------------------------------------------------------------------------
   633 // -----------------------------------------------------------------------------
   573 // CNcsAifEditor::SetAddressesL()
   634 // CNcsAifEditor::SetAddressesL()
   582 
   643 
   583 // -----------------------------------------------------------------------------
   644 // -----------------------------------------------------------------------------
   584 // CNcsAifEditor::AppendAddressesL()
   645 // CNcsAifEditor::AppendAddressesL()
   585 // -----------------------------------------------------------------------------
   646 // -----------------------------------------------------------------------------
   586 //
   647 //
   587 void CNcsAifEditor::AppendAddressesL( const RPointerArray<CNcsEmailAddressObject>& aAddresses )
   648 void CNcsAifEditor::AppendAddressesL( 
       
   649     const RPointerArray<CNcsEmailAddressObject>& aAddresses )
   588     {
   650     {
   589     FUNC_LOG;
   651     FUNC_LOG;
   590     // First, add all the addresses without updating the editor text contents 
   652     // First, add all the addresses without updating the editor text contents 
   591     for ( TInt i=0 ; i<aAddresses.Count() ; i++ )
   653     for ( TInt i=0 ; i<aAddresses.Count() ; i++ )
   592         {
   654         {
   593         AddAddressL( *aAddresses[i], EFalse );
   655         AddAddressL( *aAddresses[i], EFalse );
   594         }
   656         }
   595     // Update editor text content after all the items have been added
   657 
   596     RepositionEntriesL( NULL );
   658     // Update editor text content after all the items have been added.
       
   659     SetCursorVisible( EFalse );
       
   660     const TInt count = iArray.Count();
       
   661     CNcsAifEntry* lastEntry = count ? iArray[count-1] : NULL;
       
   662     RepositionEntries( lastEntry );
       
   663     SetCursorVisible( ETrue );
   597     }
   664     }
   598 
   665 
   599 // -----------------------------------------------------------------------------
   666 // -----------------------------------------------------------------------------
   600 // CNcsAifEditor::GetAddressesL()
   667 // CNcsAifEditor::GetAddressesL()
   601 // -----------------------------------------------------------------------------
   668 // -----------------------------------------------------------------------------
   602 //   
   669 //   
   603 const RPointerArray<CNcsEmailAddressObject>& CNcsAifEditor::GetAddressesL()
   670 const RPointerArray<CNcsEmailAddressObject>& CNcsAifEditor::GetAddressesL()
   604     {
   671     {
   605 	// Clear the existing array since it may be out of sync
   672     // Clear the existing array since it may be out of sync
   606 	iAddressArray.Reset();
   673     iAddressArray.Reset();
   607 
   674 
   608 	for ( TInt i=0 ; i<iArray.Count() ; i++ ) 
   675     for ( TInt i=0; i<iArray.Count(); i++ ) 
   609         {
   676         {
   610 		iAddressArray.AppendL(&iArray[i]->Address());
   677         iAddressArray.AppendL( &iArray[i]->Address() );
   611         }
   678         }
   612 
   679 
   613 	return iAddressArray;
   680     return iAddressArray;
   614     }
   681     }
   615     
   682 
   616 // -----------------------------------------------------------------------------
   683 // -----------------------------------------------------------------------------
   617 // CNcsAifEditor::GetEntryAt()
   684 // CNcsAifEditor::GetEntryAt()
   618 // -----------------------------------------------------------------------------
   685 // -----------------------------------------------------------------------------
   619 //   
   686 //   
   620 CNcsAifEntry* CNcsAifEditor::GetEntryAt( 
   687 CNcsAifEntry* CNcsAifEditor::GetEntryAt( 
   708 // -----------------------------------------------------------------------------
   775 // -----------------------------------------------------------------------------
   709 //
   776 //
   710 void CNcsAifEditor::ParseNewAddressL()
   777 void CNcsAifEditor::ParseNewAddressL()
   711 	{
   778 	{
   712     FUNC_LOG;
   779     FUNC_LOG;
   713 	HBufC* text = GetNonEntryTextLC();
   780     HBufC* text = GetNonEntryTextLC();
   714 	__ASSERT_ALWAYS( text, Panic(EFSEmailUiNullPointerException) );
   781     __ASSERT_ALWAYS( text, Panic(EFSEmailUiNullPointerException) );
   715 
   782 
   716 	if ( text->Length() )
   783     if ( text->Length() )
   717 		{
   784         {
   718         // if changing focus leftover text is parsed to email
   785         // if changing focus leftover text is parsed to email
   719         // object - we don't need to add it anymore
   786         // object - we don't need to add it anymore
   720         iAddLeftover = EFalse;
   787         iAddLeftover = EFalse;
   721         // check if there is a name for the email address
   788         // check if there is a name for the email address
   722         HBufC* name = CFsDelayedLoader::InstanceL()->GetContactHandlerL()->GetLastSearchNameL( *text );
   789         HBufC* name = CFsDelayedLoader::InstanceL()->GetContactHandlerL()->GetLastSearchNameL( *text );
   723 	if ( name )
   790         if ( name )
   724 		{
   791             {
   725             CleanupStack::PushL( name );
   792             CleanupStack::PushL( name );
   726 		AddAddressL( *name, *text, ETrue );
   793             AddAddressL( *name, *text, ETrue );
   727 		CleanupStack::PopAndDestroy( name );
   794             CleanupStack::PopAndDestroy( name );
   728 		}
   795             }
   729 	else
   796         else
   730 		{
   797             {
   731 		AddAddressL( KNullDesC, *text );
   798             AddAddressL( KNullDesC, *text );
   732 		}
   799             }
   733 	    }
   800         }
   734 	
   801 
   735 	CleanupStack::PopAndDestroy(text);
   802     CleanupStack::PopAndDestroy(text);
   736 	}
   803 	}
   737 
   804 
   738 // -----------------------------------------------------------------------------
   805 // -----------------------------------------------------------------------------
   739 // CNcsAifEditor::GetNonEntryTextL()
   806 // CNcsAifEditor::GetNonEntryTextL()
   740 // This will extract any text that was entered that is not
   807 // This will extract any text that was entered that is not
   846 
   913 
   847 // -----------------------------------------------------------------------------
   914 // -----------------------------------------------------------------------------
   848 // CNcsAifEditor::AddAddressL()
   915 // CNcsAifEditor::AddAddressL()
   849 // -----------------------------------------------------------------------------
   916 // -----------------------------------------------------------------------------
   850 //
   917 //
   851 void CNcsAifEditor::AddAddressL( const CNcsEmailAddressObject& aAddress, TBool aUpdateEditorText /*= ETrue*/ )
   918 void CNcsAifEditor::AddAddressL( const CNcsEmailAddressObject& aAddress,
       
   919     TBool aUpdateEditorText /*= ETrue*/ )
   852     {
   920     {
   853     FUNC_LOG;
   921     FUNC_LOG;
   854     CNcsAifEntry* entry = CNcsAifEntry::NewL( aAddress );
   922     CNcsAifEntry* entry = CNcsAifEntry::NewL( aAddress );
   855     CleanupStack::PushL( entry );
   923     CleanupStack::PushL( entry );
   856     AddAddressL( entry, aUpdateEditorText );
   924     AddAddressL( entry, aUpdateEditorText );
   864     TBool aUpdateEditorText /*= ETrue*/ )
   932     TBool aUpdateEditorText /*= ETrue*/ )
   865     {
   933     {
   866     FUNC_LOG;
   934     FUNC_LOG;
   867     CNcsAifEntry* entry = CNcsAifEntry::NewL( aDisplayName, aEmail, aDisplayFull );
   935     CNcsAifEntry* entry = CNcsAifEntry::NewL( aDisplayName, aEmail, aDisplayFull );
   868     CleanupStack::PushL( entry );
   936     CleanupStack::PushL( entry );
   869 	AddAddressL( entry, aUpdateEditorText );
   937     AddAddressL( entry, aUpdateEditorText );
   870 	CleanupStack::Pop( entry );
   938     CleanupStack::Pop( entry );
   871     }
   939     }
   872 
   940 
   873 void CNcsAifEditor::AddAddressL( CNcsAifEntry* aNewEntry, TBool aUpdateEditorText )
   941 void CNcsAifEditor::AddAddressL( CNcsAifEntry* aNewEntry, TBool aUpdateEditorText )
   874     {
   942     {
   875     FUNC_LOG;
   943     FUNC_LOG;
   876 	TInt idx;
   944     TInt idx;
   877 	
   945 
   878 	// Check for duplicate display names
   946     // Check for duplicate display names
   879 	for ( idx=0 ; idx<iArray.Count() ; idx++ ) 
   947     for ( idx=0 ; idx<iArray.Count() ; idx++ ) 
   880         {
   948         {
   881 		if ( iArray[idx]->IsSameDN(*aNewEntry) ) 
   949         if ( iArray[idx]->IsSameDN(*aNewEntry) ) 
   882             {
   950             {
   883 			iArray[idx]->SetDupL();
   951             iArray[idx]->SetDupL();
   884 			aNewEntry->SetDupL();
   952             aNewEntry->SetDupL();
   885             }
   953             }
   886         }
   954         }
   887 
   955 
   888 	// Find the location where we need to insert the address.
   956     // Find the location where we need to insert the address.
   889 	// Browse from back to forth to make last index as default index. 
   957     // Browse from back to forth to make last index as default index. 
   890 	// This ensures items remain in correct order when populating field from
   958     // This ensures items remain in correct order when populating field from
   891 	// existing message.
   959     // existing message.
   892 	TInt cursorPos = CursorPos();
   960     TInt cursorPos = CursorPos();
   893     // if we are at the end of editor the address was
   961     // if we are at the end of editor the address was
   894     // added from MRU list or separator was typed in
   962     // added from MRU list or separator was typed in
   895     if ( cursorPos == Text()->DocumentLength() )
   963     if ( cursorPos == Text()->DocumentLength() )
   896         {
   964         {
   897         iAddLeftover = EFalse;
   965         iAddLeftover = EFalse;
   898         }
   966         }
   899 	
   967 
   900 	for ( idx = iArray.Count() ; idx > 0 ; idx-- ) 
   968     for ( idx = iArray.Count() ; idx > 0 ; idx-- ) 
   901         {
   969         {
   902 		if ( cursorPos >= iArray[idx-1]->End() ) break;
   970         if ( cursorPos >= iArray[idx-1]->End() ) break;
   903         }
   971         }
   904 	if ( idx == iArray.Count() ) 
   972     if ( idx == iArray.Count() ) 
   905         {
   973         {
   906 		// Tack the address onto the end of the array
   974         // Tack the address onto the end of the array
   907 		iArray.AppendL( aNewEntry );
   975         iArray.AppendL( aNewEntry );
   908         }
   976         }
   909 	else
   977     else
   910         {
   978         {
   911 		iArray.InsertL( aNewEntry, idx );
   979         iArray.InsertL( aNewEntry, idx );
   912         }
   980         }
   913 	
   981 
   914 	if ( aUpdateEditorText )
   982     if ( aUpdateEditorText )
   915 	    {
   983         {
   916 	    // Trap because we must not leave after we have taken the ownership of aNewEntry.
   984         // Trap because we must not leave after we have taken the ownership of
   917 	    // Otherwise douple deletion might happen.
   985         // aNewEntry. Otherwise douple deletion might happen.
   918 	    TRAP_IGNORE( RepositionEntriesL( aNewEntry ) );
   986         SetCursorVisible( EFalse );
   919 	    }
   987         RepositionEntries( aNewEntry );
       
   988         SetCursorVisible( ETrue );
       
   989         }
   920     }
   990     }
   921 
   991 
   922 // ---------------------------------------------------------------------------
   992 // ---------------------------------------------------------------------------
   923 // CNcsAifEditor::RecalculateEntryPositions()
   993 // CNcsAifEditor::RecalculateEntryPositions()
   924 // The text has changed, so recalculate the positions of the items.
   994 // The text has changed, so recalculate the positions of the items.
   964 		pos++; // for whitespace
  1034 		pos++; // for whitespace
   965 		}
  1035 		}
   966 	}
  1036 	}
   967 
  1037 
   968 // ---------------------------------------------------------------------------
  1038 // ---------------------------------------------------------------------------
       
  1039 // CNcsAifEditor::RepositionEntries()
       
  1040 // ---------------------------------------------------------------------------
       
  1041 //
       
  1042 TInt CNcsAifEditor::RepositionEntries( const CNcsAifEntry* aPosEntry )
       
  1043     {
       
  1044     FUNC_LOG;
       
  1045     TRAPD( err, RepositionEntriesL( aPosEntry ) );
       
  1046     return err;
       
  1047     }
       
  1048 
       
  1049 // ---------------------------------------------------------------------------
   969 // CNcsAifEditor::RepositionEntriesL()
  1050 // CNcsAifEditor::RepositionEntriesL()
   970 // ---------------------------------------------------------------------------
  1051 // ---------------------------------------------------------------------------
   971 //
  1052 //
   972 void CNcsAifEditor::RepositionEntriesL( const CNcsAifEntry* aPosEntry )
  1053 void CNcsAifEditor::RepositionEntriesL( const CNcsAifEntry* aPosEntry )
   973 	{
  1054     {
   974     FUNC_LOG;
  1055     FUNC_LOG;
   975 	TInt pos = 0;
  1056     TInt pos = 0;
   976 	CNcsAifEntry* entry;
  1057     CNcsAifEntry* entry;
   977 	for ( TInt i=0 ; i<iArray.Count() ; i++ ) 
  1058     for ( TInt i=0 ; i<iArray.Count() ; i++ ) 
   978 		{
  1059         {
   979 		entry = iArray[i];
  1060         entry = iArray[i];
   980 		pos = entry->SetPos( pos );
  1061         pos = entry->SetPos( pos );
   981 		pos++; // for whitespace
  1062         pos++; // for whitespace
   982 		}
  1063         }
   983 
  1064 
   984   // Reset the text
  1065     // Reset the text
   985 	HBufC* text = NULL;
  1066     HBufC* text = GetFormattedAddressListLC( iArray );
   986 	text = GetFormattedAddressListLC( iArray );
  1067     // fix for dissapearing text PWAN-82DNEJ
   987 	// fix for dissapearing text PWAN-82DNEJ	
  1068     //SetCursorPosL( 0, EFalse ); //In case the cursor pos is invalid
   988 	SetCursorPosL( 0, EFalse ); //In case the cursor pos is invalid
  1069 
   989 	
       
   990     if ( iAddLeftover )
  1070     if ( iAddLeftover )
   991         {
  1071         {
   992         TInt lengthBefore = Text()->DocumentLength();
  1072         TInt lengthBefore = Text()->DocumentLength();
   993         HBufC* textBefore = HBufC::NewLC( lengthBefore );
  1073         HBufC* textBefore = HBufC::NewLC( lengthBefore );
   994         TPtr ptrBefore = textBefore->Des();
  1074         TPtr ptrBefore = textBefore->Des();
   999                 KCharAddressDelimeterSemiColon ) + 1;
  1079                 KCharAddressDelimeterSemiColon ) + 1;
  1000         TPtrC leftover = ptrBefore.Mid( colon );
  1080         TPtrC leftover = ptrBefore.Mid( colon );
  1001         HBufC* newText = HBufC::NewLC( text->Length() + leftover.Length() );
  1081         HBufC* newText = HBufC::NewLC( text->Length() + leftover.Length() );
  1002         TPtr newTextPtr = newText->Des();
  1082         TPtr newTextPtr = newText->Des();
  1003         // add all email addresses
  1083         // add all email addresses
  1004         newTextPtr.Append( text->Des() );
  1084         newTextPtr.Append( *text );
  1005         // add the text that was after last email object
  1085         // add the text that was after last email object
  1006         newTextPtr.Append( leftover );
  1086         newTextPtr.Append( leftover );
  1007     
  1087 
  1008         SetTextL( newText );
  1088         SetTextL( newText );
  1009         CleanupStack::PopAndDestroy( newText );
  1089         CleanupStack::PopAndDestroy( newText );
  1010         CleanupStack::PopAndDestroy( textBefore );
  1090         CleanupStack::PopAndDestroy( textBefore );
  1011         }
  1091         }
  1012     else
  1092     else
  1013         {
  1093         {
  1014         SetTextL( text );
  1094         SetTextL( text );
  1015         }
  1095         }
       
  1096 
       
  1097     if ( !aPosEntry )
       
  1098         {
       
  1099         // Set cursor at the beginning of the document.
       
  1100         SetCursorPosL( 0, EFalse );
       
  1101         }
       
  1102     else
       
  1103         {
       
  1104         // Set the cursor at the end of the given entry 
       
  1105         SetCursorPosL( aPosEntry->End(), EFalse );
       
  1106         }
       
  1107 
  1016     CleanupStack::PopAndDestroy( text );
  1108     CleanupStack::PopAndDestroy( text );
  1017     HandleTextChangedL();
  1109     HandleTextChangedL();
  1018     
  1110     }
  1019     // Set the cursor at the end of the given entry 
       
  1020     if ( !aPosEntry )
       
  1021     	{
       
  1022 	    SetCursorPosL( 0, EFalse );
       
  1023     	}
       
  1024     else
       
  1025     	{
       
  1026     	SetCursorPosL( aPosEntry->End(), EFalse );
       
  1027     	}
       
  1028 	}
       
  1029 
  1111 
  1030 // ---------------------------------------------------------------------------
  1112 // ---------------------------------------------------------------------------
  1031 // CNcsAifEditor::CheckAndRemoveInvalidEntriesL()
  1113 // CNcsAifEditor::CheckAndRemoveInvalidEntriesL()
  1032 // ---------------------------------------------------------------------------
  1114 // ---------------------------------------------------------------------------
  1033 //
  1115 //
  1081 // ---------------------------------------------------------------------------
  1163 // ---------------------------------------------------------------------------
  1082 //
  1164 //
  1083 HBufC* CNcsAifEditor::GetLookupTextLC() const
  1165 HBufC* CNcsAifEditor::GetLookupTextLC() const
  1084     {
  1166     {
  1085     FUNC_LOG;
  1167     FUNC_LOG;
  1086 	HBufC* text = GetTextInHBufL();
  1168     HBufC* text = GetTextInHBufL();
  1087 	
  1169     CleanupStack::PushL( text );
  1088 	if (text == NULL) return NULL;
  1170     if ( text )
  1089 
  1171         {
  1090 	CleanupStack::PushL( text );
  1172         TPtr ptr( text->Des() );
  1091 	TPtr ptr( text->Des() );
  1173         TInt location = ptr.LocateReverse( KCharAddressDelimeterSemiColon );
  1092 	TInt location = ptr.LocateReverse( KCharAddressDelimeterSemiColon );
  1174         if ( location != KErrNotFound )
  1093 	if( location != KErrNotFound )
  1175             {
  1094         {
  1176             ptr = ptr.RightTPtr( ptr.Length() - location -1 );
  1095 		ptr = ptr.RightTPtr( ptr.Length() - location -1 );
  1177             ptr.TrimLeft();
  1096 		ptr.TrimLeft();
  1178             }
  1097         }
  1179         }
  1098 	return text;
  1180     return text;
  1099     }
  1181     }
  1100 
  1182 
  1101 // ---------------------------------------------------------------------------
  1183 // ---------------------------------------------------------------------------
  1102 // CNcsAifEditor::GetFormattedAddressListLC()
  1184 // CNcsAifEditor::GetFormattedAddressListLC()
  1103 // ---------------------------------------------------------------------------
  1185 // ---------------------------------------------------------------------------
  1105 HBufC* CNcsAifEditor::GetFormattedAddressListLC(
  1187 HBufC* CNcsAifEditor::GetFormattedAddressListLC(
  1106     RPointerArray<CNcsAifEntry>& aEntries,
  1188     RPointerArray<CNcsAifEntry>& aEntries,
  1107     TBool aDisplayList ) const
  1189     TBool aDisplayList ) const
  1108     {
  1190     {
  1109     FUNC_LOG;
  1191     FUNC_LOG;
  1110 	TInt length = CalculateAddressListLength( aEntries, aDisplayList );
  1192     TInt length = CalculateAddressListLength( aEntries, aDisplayList );
  1111 	if ( length <= 0 )
  1193     if ( length <= 0 )
  1112         {
  1194         {
  1113 		return HBufC::NewLC(0);
  1195         return HBufC::NewLC(0);
  1114         }
  1196         }
  1115     
  1197 
  1116 	HBufC* buf = HBufC::NewLC( length );
  1198     HBufC* buf = HBufC::NewLC( length );
  1117 	TPtr ptr = buf->Des();
  1199     TPtr ptr = buf->Des();
  1118     
  1200 
  1119 	TInt count = aEntries.Count();
  1201     TInt count = aEntries.Count();
  1120 	for ( TInt i = 0; i < count; i++ )
  1202     for ( TInt i = 0; i < count; i++ )
  1121         {
  1203         {
  1122         if ( aDisplayList )
  1204         if ( aDisplayList )
  1123             {
  1205             {
  1124             ptr.Append( aEntries[i]->DisplayString() );
  1206             ptr.Append( aEntries[i]->DisplayString() );
  1125             }
  1207             }
  1144 // ---------------------------------------------------------------------------
  1226 // ---------------------------------------------------------------------------
  1145 //
  1227 //
  1146 HBufC* CNcsAifEditor::GetFormattedAddressListL(
  1228 HBufC* CNcsAifEditor::GetFormattedAddressListL(
  1147     RPointerArray<CNcsAifEntry>& aEntries,
  1229     RPointerArray<CNcsAifEntry>& aEntries,
  1148     TBool aDisplayList ) const
  1230     TBool aDisplayList ) const
  1149 	{
  1231     {
  1150     FUNC_LOG;
  1232     FUNC_LOG;
  1151     HBufC* buf = GetFormattedAddressListLC( aEntries, aDisplayList );
  1233     HBufC* buf = GetFormattedAddressListLC( aEntries, aDisplayList );
  1152     CleanupStack::Pop( buf );
  1234     CleanupStack::Pop( buf );
  1153     return buf;
  1235     return buf;
  1154 	}
  1236     }
  1155 
  1237 
  1156 // ---------------------------------------------------------------------------
  1238 // ---------------------------------------------------------------------------
  1157 // CNcsAifEditor::CalculateAddressListLength()
  1239 // CNcsAifEditor::CalculateAddressListLength()
  1158 // ---------------------------------------------------------------------------
  1240 // ---------------------------------------------------------------------------
  1159 //
  1241 //
  1200 // ---------------------------------------------------------------------------
  1282 // ---------------------------------------------------------------------------
  1201 //
  1283 //
  1202 void CNcsAifEditor::UpdateAddressAutoCompletionL()
  1284 void CNcsAifEditor::UpdateAddressAutoCompletionL()
  1203     {
  1285     {
  1204     FUNC_LOG;
  1286     FUNC_LOG;
  1205 	HBufC* text = GetNonEntryTextLC();
  1287     HBufC* text = GetNonEntryTextLC();
  1206 	__ASSERT_ALWAYS( text, Panic(EFSEmailUiNullPointerException) );
  1288     __ASSERT_ALWAYS( text, Panic(EFSEmailUiNullPointerException) );
  1207 
  1289 
  1208 		iAddressPopupList->UpdatePopupContactListL( *text, EFalse );
  1290     iAddressPopupList->UpdatePopupContactListL( *text, EFalse );
  1209 		CleanupStack::PopAndDestroy( text );
  1291     CleanupStack::PopAndDestroy( text );
  1210         }
  1292     }
  1211 
  1293 
  1212 // ---------------------------------------------------------------------------
  1294 // ---------------------------------------------------------------------------
  1213 // CNcsAifEditor::UpdateAddressAutoCompletionL()
  1295 // CNcsAifEditor::UpdateAddressAutoCompletionL()
  1214 // ---------------------------------------------------------------------------
  1296 // ---------------------------------------------------------------------------
  1215 //
  1297 //
  1238 // ---------------------------------------------------------------------------
  1320 // ---------------------------------------------------------------------------
  1239 //
  1321 //
  1240 void CNcsAifEditor::UpdateAddressListAllL()
  1322 void CNcsAifEditor::UpdateAddressListAllL()
  1241     {
  1323     {
  1242     FUNC_LOG;
  1324     FUNC_LOG;
  1243 	iAddressPopupList->UpdatePopupContactListL( KNullDesC, ETrue );
  1325     iAddressPopupList->UpdatePopupContactListL( KNullDesC, ETrue );
  1244     }
  1326     }
  1245 
       
  1246 
  1327 
  1247 // ---------------------------------------------------------------------------
  1328 // ---------------------------------------------------------------------------
  1248 // Updates the duplicate markings in the entry array.
  1329 // Updates the duplicate markings in the entry array.
  1249 // ---------------------------------------------------------------------------
  1330 // ---------------------------------------------------------------------------
  1250 //
  1331 //
  1304 void CNcsAifEditor::HandleTextUpdateL()
  1385 void CNcsAifEditor::HandleTextUpdateL()
  1305     {
  1386     {
  1306     FUNC_LOG;
  1387     FUNC_LOG;
  1307     RecalculateEntryPositions();
  1388     RecalculateEntryPositions();
  1308     TCursorSelection textSelection = NonEntryTextAtPos( CursorPos() );
  1389     TCursorSelection textSelection = NonEntryTextAtPos( CursorPos() );
  1309     TBool newEntryCreated = EFalse;
       
  1310     if ( textSelection.Length() )
  1390     if ( textSelection.Length() )
  1311         {
  1391         {
  1312         // Check non-entry text for complete entries.
  1392         // Check non-entry text for complete entries.
  1313         newEntryCreated = HandleTextUpdateL( textSelection );
  1393         const TBool newEntriesAdded = HandleTextUpdateL( textSelection );
  1314         }
  1394         if ( newEntriesAdded )
  1315     
  1395             {
  1316     if ( newEntryCreated )
  1396             iAddressPopupList->ClosePopupContactListL();
  1317         {
  1397             iSizeObserver->UpdateFieldSizeL( ETrue );
  1318         iAddressPopupList->ClosePopupContactListL();
  1398             iPartialRemove = EFalse;
  1319         
  1399             }
  1320         // add line feed after new entry
  1400         else
  1321         TInt cursorPos( CursorPos() );
  1401             {
  1322         // related to PWAN-82DNEJ cursorPos shouldn't be 0 here
  1402             MoveNonEntryTextToDedicatedRowsL( CursorPos() );
  1323         if (cursorPos == 0)
  1403             }
  1324           {
  1404         textSelection = NonEntryTextAtPos( CursorPos() );
  1325           cursorPos = TextLength();
  1405         }
  1326           }
  1406     UpdateAddressAutoCompletionL( textSelection );
  1327           
       
  1328         if ( !iPartialRemove )
       
  1329             {
       
  1330             Text()->InsertL( cursorPos, TChar(CEditableText::ELineBreak) );
       
  1331             }
       
  1332         HandleTextChangedL();
       
  1333         SetCursorPosL( cursorPos + 1, EFalse );
       
  1334         iSizeObserver->UpdateFieldSizeL( ETrue );
       
  1335         iPartialRemove = EFalse;
       
  1336         }
       
  1337     else
       
  1338         {
       
  1339         UpdateAddressAutoCompletionL( textSelection );
       
  1340         }
       
  1341     }
  1407     }
  1342 
  1408 
  1343 // ---------------------------------------------------------------------------
  1409 // ---------------------------------------------------------------------------
  1344 // CNcsAifEditor::HandleTextUpdateL()
  1410 // CNcsAifEditor::HandleTextUpdateL()
  1345 // ---------------------------------------------------------------------------
  1411 // ---------------------------------------------------------------------------
  1348     {
  1414     {
  1349     FUNC_LOG;
  1415     FUNC_LOG;
  1350     iAddLeftover = ETrue;
  1416     iAddLeftover = ETrue;
  1351     TInt firstCharacter = aSelection.LowerPos();
  1417     TInt firstCharacter = aSelection.LowerPos();
  1352     TInt lastCharacter = aSelection.HigherPos();
  1418     TInt lastCharacter = aSelection.HigherPos();
  1353     
  1419 
  1354     // get the inputted text
  1420     // get the inputted text
  1355     TInt length = lastCharacter - firstCharacter;
  1421     const TInt length = lastCharacter - firstCharacter;
  1356     
  1422 
  1357     HBufC* text = HBufC::NewLC( length );
  1423     HBufC* text = HBufC::NewLC( length );
  1358     TPtr ptr = text->Des();
  1424     TPtr ptr = text->Des();
  1359     Text()->Extract( ptr, firstCharacter, length );
  1425     Text()->Extract( ptr, firstCharacter, length );
  1360     ptr.Trim();
  1426     ptr.Trim();
  1361     
  1427     
  1409                     }
  1475                     }
  1410                 addAddress = EFalse;
  1476                 addAddress = EFalse;
  1411                 }
  1477                 }
  1412             }
  1478             }
  1413         }
  1479         }
  1414     
  1480 
  1415     // add email that wasn't ended with semicolon
  1481     // add email that wasn't ended with semicolon
  1416     if ( lastSentinel != KErrNotFound )
  1482     if ( lastSentinel != KErrNotFound )
  1417         {
  1483         {
  1418         if ( lastSentinel < end && start < end )
  1484         if ( lastSentinel < end && start < end )
  1419             {
  1485             {
  1420             AddAddressL( KNullDesC(), ptr.Mid(start, end-start) );
  1486             AddAddressL( KNullDesC(), ptr.Mid(start, end-start) );
  1421             }
  1487             entriesFound = ETrue;
  1422         }
  1488             }
  1423     
  1489         }
       
  1490 
  1424     CleanupStack::PopAndDestroy( text );
  1491     CleanupStack::PopAndDestroy( text );
  1425         
       
  1426     return entriesFound;
  1492     return entriesFound;
  1427     }
  1493     }
  1428 
  1494 
  1429 // ---------------------------------------------------------------------------
  1495 // ---------------------------------------------------------------------------
       
  1496 // Moves inputted non-entry text to separate row
       
  1497 // ---------------------------------------------------------------------------
       
  1498 //
       
  1499 void CNcsAifEditor::MoveNonEntryTextToDedicatedRowsL( TUint aPosition )
       
  1500     {
       
  1501     // Get the non-entry text and whitespace at given location
       
  1502     TCursorSelection textSelection = NonEntryTextAndSpaceAtPos( aPosition );
       
  1503     const TInt start = textSelection.LowerPos();
       
  1504     const TInt end = textSelection.HigherPos();
       
  1505     const TInt length = end - start;
       
  1506 
       
  1507     const TChar lineBreak = TChar( CEditableText::ELineBreak );
       
  1508     const TChar paragraphDelimiter =
       
  1509         TChar( CEditableText::EParagraphDelimiter );
       
  1510 
       
  1511     // Make sure that the inputted non-entry text is not on the same lines
       
  1512     // with existing entries.
       
  1513     if ( length )
       
  1514         {
       
  1515         HBufC* text = HBufC::NewLC( length );
       
  1516         TPtr ptr = text->Des();
       
  1517         Text()->Extract( ptr, start, length );
       
  1518 
       
  1519         const TChar firstCharacter = TChar( ptr[0] );
       
  1520         const TChar lastCharacter = TChar( ptr[length-1] );
       
  1521         const TInt documentLength = Text()->DocumentLength();
       
  1522 
       
  1523         TBool textChanged = EFalse;
       
  1524 
       
  1525         if ( end < documentLength &&
       
  1526              lastCharacter != paragraphDelimiter &&
       
  1527              lastCharacter != lineBreak )
       
  1528             {
       
  1529             Text()->InsertL( end, lineBreak );
       
  1530             HandleTextChangedL();
       
  1531             textChanged = ETrue;
       
  1532             }
       
  1533 
       
  1534         if ( start > 0 && start < end &&
       
  1535              firstCharacter != paragraphDelimiter &&
       
  1536              firstCharacter != lineBreak )
       
  1537             {
       
  1538             Text()->InsertL( start, lineBreak );
       
  1539             SetCursorVisible( EFalse );
       
  1540             HandleTextChangedL();
       
  1541             SetCursorPosL( CursorPos() + 1, EFalse );
       
  1542             SetCursorVisible( ETrue );
       
  1543             textChanged = ETrue;
       
  1544             }
       
  1545 
       
  1546         if ( textChanged )
       
  1547             {
       
  1548             RecalculateEntryPositions();
       
  1549             }
       
  1550 
       
  1551         CleanupStack::PopAndDestroy( text );
       
  1552         }
       
  1553     }
       
  1554 
       
  1555 // ---------------------------------------------------------------------------
       
  1556 // Prepares for text entry to given cursor position making sure that the
       
  1557 // new text will not be entered on same row with existing 
       
  1558 // ---------------------------------------------------------------------------
       
  1559 //
       
  1560 void CNcsAifEditor::PrepareForTextInputL( TUint aPosition )
       
  1561     {
       
  1562     FUNC_LOG;
       
  1563     // Get the non-entry text and whitespace at given position.
       
  1564     TCursorSelection textSelection = NonEntryTextAndSpaceAtPos( aPosition );
       
  1565     const TInt start = textSelection.LowerPos();
       
  1566     const TInt end = textSelection.HigherPos();
       
  1567     const TInt length = end - start;
       
  1568 
       
  1569     const TChar lineBreak = TChar( CEditableText::ELineBreak );
       
  1570 
       
  1571     if ( start > 0 && ( !length || aPosition == start ) )
       
  1572         {
       
  1573         Text()->InsertL( start, lineBreak );
       
  1574         HandleTextChangedL();
       
  1575         SetCursorPosL( start + 1, EFalse );
       
  1576         }
       
  1577     }
       
  1578 
       
  1579 // ---------------------------------------------------------------------------
  1430 // Handles navigation event.
  1580 // Handles navigation event.
  1431 // ---------------------------------------------------------------------------
  1581 // ---------------------------------------------------------------------------
  1432 //
  1582 //
  1433 void CNcsAifEditor::HandleNavigationEventL()
  1583 void CNcsAifEditor::HandleNavigationEventL()
  1434     {
  1584     {
  1435     FUNC_LOG;
  1585     FUNC_LOG;
  1436     // Close the contact popup when cursor is moved withing the field to make it less distracting. 
  1586     // Close the contact popup when cursor is moved withing the field to make
  1437     // It's reopened when user types something.
  1587     // it less distracting. It's reopened when user types something.
  1438     iAddressPopupList->ClosePopupContactListL();
  1588     iAddressPopupList->ClosePopupContactListL();
  1439     }
  1589     }
  1440 
  1590 
  1441 // ---------------------------------------------------------------------------
  1591 // ---------------------------------------------------------------------------
  1442 // Gets the range of non-entry text at the given position.
  1592 // Gets the range of non-entry text at the given position.
  1443 // ---------------------------------------------------------------------------
  1593 // ---------------------------------------------------------------------------
  1444 //
  1594 //
  1445 TCursorSelection CNcsAifEditor::NonEntryTextAtPos( TUint aPosition ) const
  1595 TCursorSelection CNcsAifEditor::NonEntryTextAtPos( TUint aPosition ) const
       
  1596     {
       
  1597     FUNC_LOG;
       
  1598     // Get the range of non-entry text and whitespace at given position.
       
  1599     TCursorSelection text = NonEntryTextAndSpaceAtPos( aPosition );
       
  1600 
       
  1601     // Get the selected text to remove whitespace
       
  1602     const TInt length = text.Length();
       
  1603 
       
  1604     HBufC* selectedText = NULL;
       
  1605     TRAPD( err, selectedText = HBufC::NewL( length ) );
       
  1606 
       
  1607     if( err == KErrNone )
       
  1608         {
       
  1609         TPtr ptr = selectedText->Des();
       
  1610         Text()->Extract( ptr, text.LowerPos(), length );
       
  1611 
       
  1612         // trim from end
       
  1613         TInt index( length - 1 );
       
  1614 
       
  1615         while( index >= 0 && IsWhitespace( ptr[index--] ) )
       
  1616             {
       
  1617             text.iCursorPos--;
       
  1618             }
       
  1619 
       
  1620         // trim from begin
       
  1621         index = 0;
       
  1622 
       
  1623         while( index < length && IsWhitespace( ptr[index++] ) )
       
  1624             {
       
  1625             text.iAnchorPos++;
       
  1626             }
       
  1627 
       
  1628         delete selectedText;
       
  1629         selectedText = NULL;
       
  1630         }    
       
  1631 
       
  1632     return text;
       
  1633     }
       
  1634 
       
  1635 // ---------------------------------------------------------------------------
       
  1636 // Gets non-entry text including surrounding whitespace at given position.
       
  1637 // ---------------------------------------------------------------------------
       
  1638 //
       
  1639 TCursorSelection CNcsAifEditor::NonEntryTextAndSpaceAtPos(
       
  1640     TUint aPosition ) const
  1446     {
  1641     {
  1447     FUNC_LOG;
  1642     FUNC_LOG;
  1448     TCursorSelection text( TextLength(), 0 );
  1643     TCursorSelection text( TextLength(), 0 );
  1449     for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
  1644     for ( TInt ii = iArray.Count() - 1; ii >= 0; --ii )
  1450         {
  1645         {
  1465             text.iAnchorPos = iArray[ii]->HigherPos();
  1660             text.iAnchorPos = iArray[ii]->HigherPos();
  1466             break;
  1661             break;
  1467             }
  1662             }
  1468         }
  1663         }
  1469 
  1664 
  1470     // get the selected text to remove whitespace
       
  1471     TInt length( text.Length() );    
       
  1472     
       
  1473     HBufC* selectedText = NULL;
       
  1474     TRAPD( err, selectedText = HBufC::NewL( length ) );
       
  1475     
       
  1476     if( err == KErrNone )
       
  1477     	{
       
  1478 		TPtr ptr = selectedText->Des();
       
  1479 		Text()->Extract( ptr, text.LowerPos(), length );
       
  1480 		
       
  1481 		// trim from end
       
  1482 		TInt index( length - 1 );
       
  1483 		
       
  1484 		while( index >= 0 && IsWhitespace( ptr[index--] ) )
       
  1485 			{
       
  1486 			text.iCursorPos--;
       
  1487 			}
       
  1488 		
       
  1489 		// trim from begin
       
  1490 		index = 0;
       
  1491 		
       
  1492 		while( index < length && IsWhitespace( ptr[index++] ) )
       
  1493 			{
       
  1494 			text.iAnchorPos++;
       
  1495 			}
       
  1496 
       
  1497 		delete selectedText;
       
  1498 		selectedText = NULL;
       
  1499     	}    
       
  1500     	
       
  1501     return text;
  1665     return text;
  1502     }
  1666     }
  1503 
  1667 
  1504 // ---------------------------------------------------------------------------
  1668 // ---------------------------------------------------------------------------
  1505 // Gets the range of text immediatelly before given position that does not
  1669 // Gets the range of text immediatelly before given position that does not
  1538     return ( aCharacter == KCharAddressDelimeterSemiColon || 
  1702     return ( aCharacter == KCharAddressDelimeterSemiColon || 
  1539         aCharacter == KCharAddressDelimeterComma || aCharacter == KCharSpace );
  1703         aCharacter == KCharAddressDelimeterComma || aCharacter == KCharSpace );
  1540     }
  1704     }
  1541 
  1705 
  1542 // ---------------------------------------------------------------------------
  1706 // ---------------------------------------------------------------------------
       
  1707 // Checks whether given character is considered as line delimiter.
       
  1708 // ---------------------------------------------------------------------------
       
  1709 //
       
  1710 //
       
  1711 TBool CNcsAifEditor::IsDelimiter( TChar aCharacter ) const
       
  1712     {
       
  1713     FUNC_LOG;
       
  1714     return ( aCharacter == TChar( CEditableText::ELineBreak) || 
       
  1715              aCharacter == TChar( CEditableText::EParagraphDelimiter) );
       
  1716     }
       
  1717 
       
  1718 // ---------------------------------------------------------------------------
  1543 // Checks whether given character is considered as whitespace.
  1719 // Checks whether given character is considered as whitespace.
  1544 // ---------------------------------------------------------------------------
  1720 // ---------------------------------------------------------------------------
  1545 //
  1721 //
  1546 TBool CNcsAifEditor::IsWhitespace( TChar aCharacter ) const
  1722 TBool CNcsAifEditor::IsWhitespace( TChar aCharacter ) const
  1547     {
  1723     {
  1548     FUNC_LOG;
  1724     FUNC_LOG;
  1549     return ( aCharacter == KCharSpace || 
  1725     return ( aCharacter == KCharSpace || 
  1550     		 aCharacter == TChar(CEditableText::ELineBreak) || 
  1726              aCharacter == TChar(CEditableText::ELineBreak) || 
  1551     		 aCharacter == TChar(CEditableText::EParagraphDelimiter) );
  1727              aCharacter == TChar(CEditableText::EParagraphDelimiter) );
  1552     }
  1728     }
  1553 
  1729 
  1554 // ---------------------------------------------------------------------------
  1730 // ---------------------------------------------------------------------------
  1555 // Checks whether given event is considered as navigation event.
  1731 // Checks whether given event is considered as navigation event.
  1556 // ---------------------------------------------------------------------------
  1732 // ---------------------------------------------------------------------------
  1646         TInt cursorPos = CursorPos();
  1822         TInt cursorPos = CursorPos();
  1647         TPoint touchPoint( aPointerEvent.iPosition );
  1823         TPoint touchPoint( aPointerEvent.iPosition );
  1648 
  1824 
  1649         //adjust touch point to mach editor coordinates
  1825         //adjust touch point to mach editor coordinates
  1650         touchPoint.iX -= Position().iX;
  1826         touchPoint.iX -= Position().iX;
  1651         
  1827 
  1652         TInt pointerLineNbr = textLayout->GetLineNumber( textLayout->XyPosToDocPosL( touchPoint ));
  1828         TInt pointerLineNbr = textLayout->GetLineNumber( 
       
  1829             textLayout->XyPosToDocPosL( touchPoint ) );
  1653         TInt cursorLineNbr = textLayout->GetLineNumber( cursorPos );
  1830         TInt cursorLineNbr = textLayout->GetLineNumber( cursorPos );
  1654         
  1831 
  1655         
       
  1656         if ( pointerLineNbr != cursorLineNbr )
  1832         if ( pointerLineNbr != cursorLineNbr )
  1657             {
  1833             {
  1658             CompleteEntryL();
  1834             CompleteEntryL();
  1659             
  1835             
  1660             // We're moving to a new line.
  1836             // We're moving to a new line.
  1661             CNcsAifEntry* entry = NULL;
  1837             CNcsAifEntry* entry = GetEntryAt( CursorPos() );
  1662             entry = GetEntryAt( CursorPos() );
       
  1663             if ( entry )
  1838             if ( entry )
  1664                 {
  1839                 {
  1665                 SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
  1840                 SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
  1666                 }
  1841                 }
  1667             }    
  1842             }
  1668         }
  1843         }
  1669             
  1844 
  1670     CEikEdwin::HandlePointerEventL( aPointerEvent );
  1845     CEikEdwin::HandlePointerEventL( aPointerEvent );
       
  1846 
       
  1847     // Do not allow to insert cursor into the middle of some entry
       
  1848     CNcsAifEntry* entry = GetEntryAt( CursorPos() );
       
  1849     if ( entry )
       
  1850         {
       
  1851         SetSelectionL( entry->iCursorPos, entry->iAnchorPos );
       
  1852         }
  1671     }
  1853     }
  1672 
  1854 
  1673 
  1855 
  1674 // -----------------------------------------------------------------------------
  1856 // -----------------------------------------------------------------------------
  1675 // CNcsAifEditor::CompleteEntryL()
  1857 // CNcsAifEditor::CompleteEntryL()
  1676 // Adds semicolol to the of the entry
  1858 // Adds semicolon to the end of the entry.
  1677 // -----------------------------------------------------------------------------
  1859 // -----------------------------------------------------------------------------
  1678 //
  1860 //
  1679 void CNcsAifEditor::CompleteEntryL()
  1861 void CNcsAifEditor::CompleteEntryL()
  1680     {
  1862     {
  1681     // make sure there is really some text inputted 
  1863     // make sure there is really some text inputted 
  1682     TInt cursorPos( CursorPos() );
  1864     const TInt cursorPos = CursorPos();
  1683 
  1865 
  1684     TCursorSelection selection = NonEntryTextAtPos( cursorPos );
  1866     TCursorSelection selection = NonEntryTextAtPos( cursorPos );
  1685 
  1867     const TInt length =  selection.Length();
  1686     TInt length( selection.Length() );
  1868 
  1687 
  1869     if ( length > 0 && selection.LowerPos() >= 0 )
  1688     HBufC* text = HBufC::NewLC( length );
  1870         {
  1689     TPtr ptr = text->Des();
  1871         HBufC* text = HBufC::NewLC( length );
  1690 
  1872         TPtr ptr = text->Des();
  1691     if( selection.LowerPos() >= 0 )
  1873 
  1692         {
       
  1693         Text()->Extract( ptr, selection.LowerPos(), length );
  1874         Text()->Extract( ptr, selection.LowerPos(), length );
  1694         ptr.Trim();
  1875         ptr.Trim();
  1695         
  1876 
  1696         // complete the entry
  1877         // complete the entry
  1697         if( ptr.Length() > 0 )
  1878         if ( ptr.Length() > 0 )
  1698             {
  1879             {
  1699             Text()->InsertL( selection.HigherPos(), KCharAddressDelimeterSemiColon );
  1880             Text()->InsertL( selection.HigherPos(), KCharAddressDelimeterSemiColon );
  1700             HandleTextChangedL();
  1881             HandleTextChangedL();
  1701             HandleTextUpdateL( TCursorSelection(selection.LowerPos(), selection.HigherPos() + 1) );
  1882             HandleTextUpdateL( TCursorSelection( selection.LowerPos(),
  1702             }
  1883                 selection.HigherPos() + 1 ) );
  1703         }
  1884             }
  1704 
  1885 
  1705     CleanupStack::PopAndDestroy( text );
  1886         CleanupStack::PopAndDestroy( text );
  1706     }
  1887         }
       
  1888     }
       
  1889 
  1707 // End of File
  1890 // End of File
  1708 
  1891