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