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 // --------------------------------------------------------------------------- |
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 |
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. |
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 |
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 // |
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 // --------------------------------------------------------------------------- |
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 { |
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 |