messagingappbase/msgeditor/viewsrc/MsgAddressControlEditor.cpp
changeset 0 72b543305e3a
child 21 c6838af47512
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  MsgAddressControlEditor implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ========== INCLUDE FILES ================================
       
    21 
       
    22 #include <barsread.h>                      // for TResourceReader
       
    23 #include <eikenv.h>                        // for CEikonEnv
       
    24 #include <txtrich.h>                       // for CRichText
       
    25 #include <AknUtils.h>                      // for AknUtils
       
    26 #include <AknSettingCache.h>               // for SettingCache().InputLanguage()
       
    27 #include <AknsUtils.h>                     // for AknsUtils::GetCachedColor()
       
    28 #include <AknsConstants.h>                 // for KAknsIIDQsnHighlightColors and EAknsCIQsnHighlightColorsCG1
       
    29 
       
    30 #include <aknlayout.cdl.h> // LAF
       
    31 #include <txtetext.h>
       
    32 #include <fldinfo.h>
       
    33 
       
    34 #ifdef RD_TACTILE_FEEDBACK
       
    35 #include <touchfeedback.h>
       
    36 #endif 
       
    37 
       
    38 
       
    39 #include "MsgEditorCommon.h"               //
       
    40 #include "MsgAddressControlEditor.h"       // for CMsgAddressControlEditor
       
    41 #include "MsgAddressControlEditorField.h"  // for CMsgAddressControlEditorField and TMsgAddressControlEditorFieldFactory
       
    42 #include "MsgBaseControl.h"                // for TMsgEditPermissionFlags
       
    43 #include "MsgBaseControlObserver.h"        // for MMsgBaseControlObserver
       
    44 #include "MsgAddressControl.h"             // for permission flags
       
    45 #include "MsgEditorPanic.h"                // for MsgEditor panics
       
    46 #include "MsgEditor.hrh"                   // for EditPermission flags
       
    47 #include "MsgEditorKeyCatcher.h"           // for CMsgEditorKeyCatcher
       
    48 
       
    49 // ========== EXTERNAL DATA STRUCTURES =====================
       
    50 
       
    51 // ========== EXTERNAL FUNCTION PROTOTYPES =================
       
    52 
       
    53 // ========== CONSTANTS ====================================
       
    54 
       
    55 // ========== MACROS =======================================
       
    56 
       
    57 // ========== LOCAL CONSTANTS AND MACROS ===================
       
    58 
       
    59 // Highlighted field does not exist.
       
    60 const TInt KMsgHighlightedFieldPosNone = -1;
       
    61 // Current entry not defined.
       
    62 const TInt KMsgCurrentEntryNone        = -1;
       
    63 
       
    64 const TText KZeroWidthJoiner = 0x200D;
       
    65 const TText KLRMarker = 0x200E;
       
    66 const TText KRLMarker = 0x200F;
       
    67 
       
    68 // ========== MODULE DATA STRUCTURES =======================
       
    69 
       
    70 // ========== LOCAL FUNCTION PROTOTYPES ====================
       
    71 
       
    72 // ========== LOCAL FUNCTIONS ==============================
       
    73 
       
    74 // ========== MEMBER FUNCTIONS =============================
       
    75 
       
    76 // ---------------------------------------------------------
       
    77 // CMsgAddressControlEditor::CMsgAddressControlEditor
       
    78 //
       
    79 // Constructor.
       
    80 // ---------------------------------------------------------
       
    81 //
       
    82 CMsgAddressControlEditor::CMsgAddressControlEditor(
       
    83     const CCoeControl* aParent,
       
    84     TUint32& aFlags,
       
    85     MMsgBaseControlObserver* aBaseControlObserver )
       
    86     : CMsgExpandableControlEditor( aParent, aFlags, aBaseControlObserver ),
       
    87       iHighLightedFieldPos( KMsgHighlightedFieldPosNone ),
       
    88       iCurrentEntry( KMsgCurrentEntryNone )
       
    89     {
       
    90     }
       
    91 
       
    92 // ---------------------------------------------------------
       
    93 // CMsgAddressControlEditor::~CMsgAddressControlEditor
       
    94 //
       
    95 // Destructor.
       
    96 // ---------------------------------------------------------
       
    97 //
       
    98 CMsgAddressControlEditor::~CMsgAddressControlEditor()
       
    99     {
       
   100     delete iKeyCatcher;
       
   101     delete iAddressControlEditorFieldFactory;
       
   102     }
       
   103 
       
   104 // ---------------------------------------------------------
       
   105 // CMsgAddressControlEditor::ConstructL
       
   106 //
       
   107 // 2nd phase constructor.
       
   108 // ---------------------------------------------------------
       
   109 //
       
   110 void CMsgAddressControlEditor::ConstructL()
       
   111     {
       
   112     CMsgExpandableControlEditor::ConstructL();
       
   113     
       
   114     //To Dis-able Smiley support for address fields
       
   115     RemoveFlagFromUserFlags(EAvkonEnableSmileySupport);
       
   116     
       
   117     iFlags |= EMsgControlModeDoNotDrawFrameBgContext; 
       
   118     iKeyCatcher = new ( ELeave ) CMsgEditorKeyCatcher();
       
   119     iKeyCatcher->ConstructL( this );
       
   120 
       
   121     SetAllowUndo( EFalse );
       
   122     // Variation is done inside edwin
       
   123     SetPhoneNumberGrouping( ETrue );
       
   124     iCusPos = 0;
       
   125     }
       
   126 
       
   127 // ---------------------------------------------------------
       
   128 // CMsgAddressControlEditor::ExtractEntry
       
   129 //
       
   130 // Extracts an entry according to aEntryNumber and returns it in aEntryString.
       
   131 // ---------------------------------------------------------
       
   132 //
       
   133 void CMsgAddressControlEditor::ExtractEntry(
       
   134     TDes& aEntryString, TInt aEntryNumber )
       
   135     {
       
   136     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   137         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   138         Panic( EMsgInvalidEntryNumber ) );
       
   139 
       
   140     TInt entryLength = 0;
       
   141     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   142     iRichText->Extract( aEntryString, entryStart, entryLength - 1 );
       
   143     }
       
   144 
       
   145 // ---------------------------------------------------------
       
   146 // CMsgAddressControlEditor::ReadEntry
       
   147 //
       
   148 // Reads an entry aEntryNumber and returns pointer to it.
       
   149 // ---------------------------------------------------------
       
   150 //
       
   151 TPtrC CMsgAddressControlEditor::ReadEntry( TInt aEntryNumber ) const
       
   152     {
       
   153     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   154         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   155         Panic( EMsgInvalidEntryNumber ) );
       
   156 
       
   157     TInt entryLength = 0;
       
   158     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   159     return iRichText->Read( entryStart, entryLength - 1 );
       
   160     }
       
   161 
       
   162 // ---------------------------------------------------------
       
   163 // CMsgAddressControlEditor::EntryCount
       
   164 //
       
   165 // Returns number of entries.
       
   166 // ---------------------------------------------------------
       
   167 //
       
   168 TInt CMsgAddressControlEditor::EntryCount() const
       
   169     {
       
   170     return iRichText->ParagraphCount();
       
   171     }
       
   172 
       
   173 // ---------------------------------------------------------
       
   174 // CMsgAddressControlEditor::DeleteEntryL
       
   175 //
       
   176 // Deletes an entry aEntryNumber.
       
   177 // ---------------------------------------------------------
       
   178 //
       
   179 void CMsgAddressControlEditor::DeleteEntryL( TInt aEntryNumber )
       
   180     {
       
   181     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   182         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   183         Panic( EMsgInvalidEntryNumber ) );
       
   184 
       
   185     CancelFepTransaction();
       
   186     TBool setcursorpos(EFalse);
       
   187     TInt numOfEntries = iRichText->ParagraphCount();
       
   188     TInt entryLength = 0;
       
   189     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   190     if ( numOfEntries == aEntryNumber + 1 ) //entry to be deleted is the lowest one
       
   191         {
       
   192         if ( aEntryNumber != 0 ) // but not the only one
       
   193             {
       
   194             entryStart--;
       
   195             }
       
   196         else
       
   197             {
       
   198             entryLength--;
       
   199             }
       
   200         }
       
   201     
       
   202     if ( TextView() )
       
   203         {
       
   204         // Cursor position must not go beyond text end. Otherwise
       
   205         // panic will happen on text formatting.
       
   206         TInt newTextLength = TextLength() - entryLength;
       
   207         
       
   208         if ( CursorPos() > newTextLength )
       
   209             {
       
   210             SetCursorPosL( newTextLength, EFalse );
       
   211             iCusPos = newTextLength;
       
   212             setcursorpos = ETrue;
       
   213             }
       
   214         }
       
   215     
       
   216     iRichText->CancelInsertCharFormat();
       
   217     iRichText->DelSetInsertCharFormatL( entryStart, entryLength );
       
   218     if ( iTextView )
       
   219        {
       
   220         iTextView->HandleInsertDeleteL(
       
   221             TCursorSelection( entryStart, entryStart + entryLength ), entryLength, EFalse );
       
   222        }
       
   223      numOfEntries = iRichText->ParagraphCount();
       
   224      if( numOfEntries > 0 && numOfEntries != aEntryNumber && !setcursorpos)
       
   225         {
       
   226          TInt  txtlen = TextLength();
       
   227          TInt  curpos = CursorPos();                
       
   228          entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   229          curpos+= --entryLength;
       
   230          if ( TextView() )
       
   231             {
       
   232                 if(curpos < txtlen)
       
   233                 {
       
   234                     iCusPos = curpos;
       
   235                     SetCursorPosL( curpos, EFalse );   
       
   236                 }
       
   237               else
       
   238                 {
       
   239                     iCusPos =entryStart ;
       
   240                     SetCursorPosL( iCusPos, EFalse );   
       
   241                     ReportEdwinEventL( MEikEdwinObserver::EEventTextUpdate );
       
   242                 }        
       
   243             }
       
   244         }
       
   245  }
       
   246  // ---------------------------------------------------------
       
   247 // CMsgAddressControlEditor::GetCursorpos
       
   248 //
       
   249 // returns the current cursor position.
       
   250 // ---------------------------------------------------------
       
   251 //
       
   252 
       
   253 TInt CMsgAddressControlEditor::GetCursorpos() const
       
   254     {
       
   255         return iCusPos;
       
   256     }
       
   257     
       
   258 // ---------------------------------------------------------
       
   259 // CMsgAddressControlEditor::ClearEntryL
       
   260 //
       
   261 // Clears all the text of an entry aEntryNumber but not the paragraph delimiter.
       
   262 // ---------------------------------------------------------
       
   263 //
       
   264 void CMsgAddressControlEditor::ClearEntryL( TInt aEntryNumber, TBool aUpdate )
       
   265     {
       
   266     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   267         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   268         Panic( EMsgInvalidEntryNumber ) );
       
   269 
       
   270     TInt entryLength = 0;
       
   271     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   272     DeleteEntryCharsL( aEntryNumber, 0, entryLength );
       
   273     if ( iTextView && aUpdate )
       
   274         {
       
   275         iTextView->HandleInsertDeleteL(
       
   276             TCursorSelection( entryStart, entryStart ), --entryLength, EFalse );
       
   277         SetCursorPosAndCancelSelectionL( entryStart );
       
   278         }
       
   279     }
       
   280 
       
   281 // ---------------------------------------------------------
       
   282 // CMsgAddressControlEditor::DeleteAllL
       
   283 //
       
   284 // Clears the content of the editor. Updates also the scroll bars.
       
   285 // ---------------------------------------------------------
       
   286 //
       
   287 void CMsgAddressControlEditor::DeleteAllL()
       
   288     {
       
   289     CancelFepTransaction();
       
   290     iRichText->CancelInsertCharFormat();
       
   291     iRichText->Reset();
       
   292     if (iTextView)
       
   293         {
       
   294         SetAmountToFormatL( ETrue );
       
   295         SetCursorPosAndCancelSelectionL( 0 );
       
   296         }
       
   297     }
       
   298 
       
   299 // ---------------------------------------------------------
       
   300 // CMsgAddressControlEditor::DeleteEntryCharsL
       
   301 //
       
   302 // Deletes characters from aStartPos to aEndPos at entry aEntryNumber. Never
       
   303 // removes the paragraph delimiter.
       
   304 // ---------------------------------------------------------
       
   305 //
       
   306 void CMsgAddressControlEditor::DeleteEntryCharsL(
       
   307     TInt aEntryNumber, TInt aStartPos, TInt aEndPos)
       
   308     {
       
   309     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   310         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   311         Panic( EMsgInvalidEntryNumber ) );
       
   312     __ASSERT_DEBUG( ( aStartPos >= 0 ) && ( aStartPos <= aEndPos ),
       
   313         Panic( EMsgInvalidStartPos ) );
       
   314 
       
   315     CancelFepTransaction();
       
   316     TInt entryLength = 0;
       
   317     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   318     entryLength--;
       
   319     entryLength = ( aEndPos < entryLength )
       
   320         ? aEndPos - aStartPos
       
   321         : entryLength - aStartPos;
       
   322     entryStart += aStartPos;
       
   323     
       
   324     if ( TextView() )
       
   325         {
       
   326         // Cursor position must not go beyond text end. Otherwise
       
   327         // panic will happen on text formatting.
       
   328         TInt newTextLength = TextLength() - entryLength;
       
   329         
       
   330         if ( CursorPos() > newTextLength )
       
   331             {
       
   332             SetCursorPosL( newTextLength, EFalse );
       
   333             }
       
   334         }
       
   335     
       
   336     iRichText->CancelInsertCharFormat();
       
   337     iRichText->DelSetInsertCharFormatL( entryStart, entryLength );
       
   338     //clear the iTextView cache too
       
   339     if ( iTextView )
       
   340         {
       
   341         iTextView->HandleInsertDeleteL(
       
   342             TCursorSelection( entryStart, entryStart + entryLength ), entryLength, EFalse );
       
   343         SetCursorPosAndCancelSelectionL( entryStart );
       
   344         }
       
   345     }
       
   346 
       
   347 // ---------------------------------------------------------
       
   348 // CMsgAddressControlEditor::SetCursorPosAndCancelSelectionL
       
   349 //
       
   350 // Sets cursor position to aPos and cancels selection.
       
   351 // This is needed because Edwin/TextView does not do it as expected.
       
   352 // ---------------------------------------------------------
       
   353 //
       
   354 void CMsgAddressControlEditor::SetCursorPosAndCancelSelectionL( TInt aPos )
       
   355     {
       
   356     if ( iTextView )
       
   357         {
       
   358         CancelFepTransaction();
       
   359 
       
   360         iTextView->SetDocPosL( aPos, EFalse );
       
   361         ForceScrollBarUpdateL();
       
   362         }
       
   363     }
       
   364 
       
   365 // ---------------------------------------------------------
       
   366 // CMsgAddressControlEditor::InsertEntryL
       
   367 //
       
   368 // Inserts an entry to the location aEntryNumber with strings a text aName
       
   369 // and aAddress. Makes an entry as verified if aVerified = ETrue and validated
       
   370 // if aValidated = ETrue.
       
   371 // ---------------------------------------------------------
       
   372 //
       
   373 void CMsgAddressControlEditor::InsertEntryL(
       
   374     TInt aEntryNumber,
       
   375     const TDesC& aName,
       
   376     const TDesC& aAddress,
       
   377     TBool aVerified,
       
   378     TBool aValidated,
       
   379     const MVPbkContactLink* aContactLink )
       
   380     {
       
   381     __ASSERT_DEBUG( aEntryNumber >= 0 && 
       
   382                     aEntryNumber <= iRichText->ParagraphCount(),
       
   383                     Panic( EMsgInvalidEntryNumber ) );
       
   384 
       
   385     TChar semicolon = KSemicolon;
       
   386     TInt entryLength = 0;
       
   387     TInt numOfEntries = iRichText->ParagraphCount();
       
   388 
       
   389     TInt pos = TextLength();
       
   390     TChar ch = CharAtPos( pos - 1 );
       
   391 
       
   392     if ( ch == CEditableText::EParagraphDelimiter )
       
   393         {
       
   394         // last character is parag.delim. => decrease entry num.
       
   395         aEntryNumber--;
       
   396         }
       
   397     
       
   398     /*
       
   399      * Fix the split contact name issue::ECYU-7FPC93.
       
   400      * Replace any enter-key characters with space characters.
       
   401      */
       
   402 
       
   403     TBufC<KMaxContactLength> parsedName(aName.Left(KMaxContactLength));
       
   404     
       
   405     TInt enterKeyPos;
       
   406     TChar enterChar( CEditableText::EParagraphDelimiter );
       
   407     TChar spaceChar( CEditableText::ESpace );
       
   408     TPtr namePtr = parsedName.Des();
       
   409     TInt nameLength = parsedName.Length();
       
   410     
       
   411     enterKeyPos = namePtr.Locate(enterChar);
       
   412     while( enterKeyPos != KErrNotFound && enterKeyPos < nameLength )
       
   413         {
       
   414         namePtr[enterKeyPos] = spaceChar;
       
   415         enterKeyPos = namePtr.Locate(enterChar);
       
   416         }
       
   417 
       
   418     if ( aEntryNumber >= numOfEntries )
       
   419         {
       
   420         // entry appended to the end.
       
   421         iRichText->CancelInsertCharFormat();
       
   422         iRichText->InsertL( pos, CEditableText::EParagraphDelimiter );
       
   423         }
       
   424     else
       
   425         {
       
   426         // entry appended to the middle or beginning.
       
   427         iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   428         
       
   429         if ( entryLength - 1 )
       
   430             {
       
   431             InsertEntryBreakL( aEntryNumber, 0 );
       
   432             }
       
   433         }
       
   434 
       
   435     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   436     
       
   437     //ECYU-7FPC93:: Fix
       
   438     HBufC* string = CreateEntryStringLC( parsedName, aAddress, aVerified );
       
   439     //HBufC* string = CreateEntryStringLC( aName, aAddress, aVerified );
       
   440 
       
   441     if ( aVerified || aValidated )
       
   442         {
       
   443         // Setting up the field factory.
       
   444         iRichText->SetFieldFactory( iAddressControlEditorFieldFactory );
       
   445         
       
   446         CMsgAddressControlEditorField* field = 
       
   447             static_cast<CMsgAddressControlEditorField*>( 
       
   448                                         iRichText->NewTextFieldL( KMsgAddressControlEditorFieldUid ) );
       
   449 
       
   450         if ( field )
       
   451             {
       
   452             field->SetEntryStringL( *string );
       
   453             
       
   454             //ECYU-7FPC93:: Fix
       
   455             field->SetNameL( parsedName );
       
   456             //field->SetNameL( aName );
       
   457            
       
   458             field->SetAddressL( aAddress );
       
   459             field->SetVerified( aVerified );
       
   460             field->SetValidated( aValidated );
       
   461             field->SetContactLink( aContactLink );
       
   462 
       
   463             iRichText->InsertFieldL( entryStart, 
       
   464                                      field, 
       
   465                                      KMsgAddressControlEditorFieldUid );
       
   466                                      
       
   467             iRichText->UpdateFieldL( entryStart );
       
   468             }
       
   469         }
       
   470     else
       
   471         {
       
   472         if ( string->Length() > 0 )
       
   473             {
       
   474             iRichText->InsertL( entryStart, *string );
       
   475             }
       
   476         else
       
   477             {
       
   478             // This should not happen. Zero lenght contact name is being added. 
       
   479             // Insert semicolon only.
       
   480             if ( iAvkonEnv->SettingCache().InputLanguage() == ELangArabic )
       
   481                 {
       
   482                 semicolon = KArabicSemicolon;
       
   483                 }
       
   484                 
       
   485             iRichText->InsertL( entryStart, semicolon );
       
   486             }
       
   487         }
       
   488 
       
   489     if ( aEntryNumber >= numOfEntries )
       
   490         {
       
   491         if ( ch != semicolon &&
       
   492              ch != CEditableText::EParagraphDelimiter &&
       
   493              ch != KArabicSemicolon )
       
   494             {
       
   495             if ( iAvkonEnv->SettingCache().InputLanguage() == ELangArabic )
       
   496                 {
       
   497                 semicolon = KArabicSemicolon;
       
   498                 }
       
   499                 
       
   500             iRichText->InsertL( pos, semicolon );
       
   501             }
       
   502         }
       
   503         
       
   504     CleanupStack::PopAndDestroy();  // string
       
   505     }
       
   506     
       
   507 // ---------------------------------------------------------
       
   508 // CMsgAddressControlEditor::InsertEntryBreakL
       
   509 //
       
   510 // Inserts the paragraph delimiter at aPos on entry aEntryNumber.
       
   511 // ---------------------------------------------------------
       
   512 //
       
   513 void CMsgAddressControlEditor::InsertEntryBreakL( TInt aEntryNumber, TInt aPos )
       
   514     {
       
   515     __ASSERT_DEBUG( aEntryNumber >= 0 &&
       
   516                     aEntryNumber < iRichText->ParagraphCount(),
       
   517                     Panic( EMsgInvalidEntryNumber ) );
       
   518 
       
   519     TInt entryLength = 0;
       
   520     TInt insertPos = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   521     insertPos += aPos;
       
   522     iRichText->CancelInsertCharFormat();
       
   523     iRichText->InsertL( insertPos, CEditableText::EParagraphDelimiter );
       
   524     }
       
   525 
       
   526 // ---------------------------------------------------------
       
   527 // CMsgAddressControlEditor::EntryNumber
       
   528 //
       
   529 // Returs an entry number where aPos is on.
       
   530 // ---------------------------------------------------------
       
   531 //
       
   532 TInt CMsgAddressControlEditor::EntryNumber( TInt aPos ) const
       
   533     {
       
   534     __ASSERT_DEBUG( ( aPos >= 0 ) && ( aPos <= TextLength() ),
       
   535         Panic( EMsgDocPosOutOfRange ) );
       
   536 
       
   537     // first paragraph==0
       
   538     TInt paragraphNumber = iRichText->ParagraphNumberForPos( aPos );
       
   539     return paragraphNumber;
       
   540     }
       
   541 
       
   542 // ---------------------------------------------------------
       
   543 // CMsgAddressControlEditor::EntryLength
       
   544 //
       
   545 // Returns length of the entry aEntryNumber. Does not count paragraph delimiter.
       
   546 // ---------------------------------------------------------
       
   547 //
       
   548 TInt CMsgAddressControlEditor::EntryLength( TInt aEntryNumber ) const
       
   549     {
       
   550     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   551         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   552         Panic( EMsgInvalidEntryNumber ) );
       
   553 
       
   554     TInt entryLength = 0;
       
   555     iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   556     return entryLength - 1;
       
   557     }
       
   558 
       
   559 // ---------------------------------------------------------
       
   560 // CMsgAddressControlEditor::EntryStartPos
       
   561 //
       
   562 // Returns first character position on the entry aEntryNumber.
       
   563 // ---------------------------------------------------------
       
   564 //
       
   565 TInt CMsgAddressControlEditor::EntryStartPos( TInt aEntryNumber ) const
       
   566     {
       
   567     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   568         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   569         Panic( EMsgInvalidEntryNumber ) );
       
   570 
       
   571     TInt entryLength = 0;
       
   572     return iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   573     }
       
   574 
       
   575 // ---------------------------------------------------------
       
   576 // CMsgAddressControlEditor::FirstFieldPos
       
   577 //
       
   578 //
       
   579 // ---------------------------------------------------------
       
   580 //
       
   581 TInt CMsgAddressControlEditor::FirstFieldPos( TInt aCursorPos ) const
       
   582     {
       
   583     TFindFieldInfo fieldInfo;
       
   584 
       
   585     /*TBool ret =*/ iRichText->FindFields( fieldInfo, aCursorPos, 0 );
       
   586 
       
   587     return fieldInfo.iFirstFieldPos;
       
   588     }
       
   589 
       
   590 // ---------------------------------------------------------
       
   591 // CMsgAddressControlEditor::MoveCursorToEntryPosL
       
   592 //
       
   593 // Moves the cursor on an entry aEntryNumber to a position aPos. 0 == entry start.
       
   594 // ---------------------------------------------------------
       
   595 //
       
   596 void CMsgAddressControlEditor::MoveCursorToEntryPosL( TInt aEntryNumber, TInt aPos )
       
   597     {
       
   598     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   599         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   600         Panic( EMsgInvalidEntryNumber ) );
       
   601 
       
   602     TInt entryLength = 0;
       
   603     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   604     if ( entryLength - 1 < aPos )
       
   605         {
       
   606         aPos = entryLength - 1; // adjust the aPos if it happens to be too big
       
   607         }
       
   608     SetCursorPosAndCancelSelectionL( entryStart + aPos );
       
   609     }
       
   610 
       
   611 // ---------------------------------------------------------
       
   612 // CMsgAddressControlEditor::IsPosAtEntryBeginning
       
   613 //
       
   614 // Checks whether the cursor is at the beginning of the entry and returns ETrue
       
   615 // if it is, otherwise EFalse.
       
   616 // ---------------------------------------------------------
       
   617 //
       
   618 TBool CMsgAddressControlEditor::IsPosAtEntryBeginning( TInt aPos ) const
       
   619     {
       
   620     __ASSERT_DEBUG( ( aPos >= 0 ) && ( aPos <= TextLength() ),
       
   621         Panic( EMsgDocPosOutOfRange ) );
       
   622 
       
   623     TInt entryLength = 0;
       
   624     return ( iRichText->CharPosOfParagraph(
       
   625         entryLength, EntryNumber( aPos ) ) == aPos );
       
   626     }
       
   627 
       
   628 // ---------------------------------------------------------
       
   629 // CMsgAddressControlEditor::IsEntryVerified
       
   630 //
       
   631 // Check whether an entry aEntryNumber is verified or not and returns ETrue
       
   632 // if it is, otherwise EFalse.
       
   633 // ---------------------------------------------------------
       
   634 //
       
   635 TBool CMsgAddressControlEditor::IsEntryVerified( TInt aEntryNumber ) const
       
   636     {
       
   637     const CMsgAddressControlEditorField* field = Field( aEntryNumber );
       
   638 
       
   639     return ( field ? field->IsVerified() : EFalse );
       
   640     }
       
   641 
       
   642 // ---------------------------------------------------------
       
   643 // CMsgAddressControlEditor::IsPriorEntryVerified
       
   644 //
       
   645 // Checks whether an entry aEntryNumber-1 is verified and returns ETrue if
       
   646 // it is, otherwise EFalse.
       
   647 // ---------------------------------------------------------
       
   648 //
       
   649 TBool CMsgAddressControlEditor::IsPriorEntryVerified( TInt aEntryNumber ) const
       
   650     {
       
   651     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   652         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   653         Panic( EMsgInvalidEntryNumber ) );
       
   654 
       
   655     if ( aEntryNumber > 0 )
       
   656         {
       
   657         return IsEntryVerified( aEntryNumber - 1 );
       
   658         }
       
   659 
       
   660     return EFalse;
       
   661     }
       
   662 
       
   663 // ---------------------------------------------------------
       
   664 // CMsgAddressControlEditor::IsEntryValidated
       
   665 //
       
   666 // Check whether an entry aEntryNumber is validated or not and returns ETrue
       
   667 // if it is, otherwise EFalse.
       
   668 // ---------------------------------------------------------
       
   669 //
       
   670 TBool CMsgAddressControlEditor::IsEntryValidated( TInt aEntryNumber ) const
       
   671     {
       
   672     const CMsgAddressControlEditorField* field = Field( aEntryNumber );
       
   673 
       
   674     return ( field ? field->IsValidated() : EFalse );
       
   675     }
       
   676 
       
   677 // ---------------------------------------------------------
       
   678 // CMsgAddressControlEditor::IsFieldOnLeft
       
   679 //
       
   680 // Checks if there is a text field on the left hand side of the cursor at
       
   681 // position aPos and returns ETrue if it is, otherwise EFalse.
       
   682 // ---------------------------------------------------------
       
   683 //
       
   684 TBool CMsgAddressControlEditor::IsFieldOnLeft( TInt aPos ) const
       
   685     {
       
   686     if ( aPos > 0 && aPos <= TextLength() )
       
   687         {
       
   688         const CMsgAddressControlEditorField* field = FieldFromPos( aPos - 1 );
       
   689 
       
   690         return ( field ? field->IsVerified() : EFalse );
       
   691         }
       
   692     return EFalse;
       
   693     }
       
   694 
       
   695 // ---------------------------------------------------------
       
   696 // CMsgAddressControlEditor::IsFieldOnRight
       
   697 //
       
   698 // Checks if there is a text field on the right hand side of the cursor at position
       
   699 // aPos and returns ETrue if it is, otherwise EFalse.
       
   700 // ---------------------------------------------------------
       
   701 //
       
   702 TBool CMsgAddressControlEditor::IsFieldOnRight( TInt aPos ) const
       
   703     {
       
   704     if ( aPos >= 0 && aPos < TextLength() )
       
   705         {
       
   706         // Fixing Fixing "ESPI-63C45M - Messags: The contact named with one
       
   707         // characteronly cannot be deleted from ‘To’ field by ‘Clear’ key."
       
   708 
       
   709         const CMsgAddressControlEditorField* field = FieldFromPos( aPos );
       
   710 
       
   711         return ( field ? field->IsVerified() : EFalse );
       
   712         }
       
   713     return EFalse;
       
   714     }
       
   715 
       
   716 // ---------------------------------------------------------
       
   717 // CMsgAddressControlEditor::IsFieldOnPos
       
   718 //
       
   719 // Checks if there is a text field under the cursor at position
       
   720 // aPos and returns ETrue if it is, otherwise EFalse.
       
   721 // ---------------------------------------------------------
       
   722 //
       
   723 TBool CMsgAddressControlEditor::IsFieldOnPos( TInt aPos ) const
       
   724     {
       
   725     if ( aPos >= 0 && aPos < TextLength() )
       
   726         {
       
   727         const CMsgAddressControlEditorField* field = FieldFromPos( aPos );
       
   728 
       
   729         return ( field ? field->IsVerified() : EFalse );
       
   730         }
       
   731     return EFalse;
       
   732     }
       
   733 
       
   734 // ---------------------------------------------------------
       
   735 // CMsgAddressControlEditor::IsEntryEmpty
       
   736 //
       
   737 // Checks whether an entry aEntryNumber is empty.
       
   738 // ---------------------------------------------------------
       
   739 //
       
   740 TBool CMsgAddressControlEditor::IsEntryEmpty( TInt aEntryNumber ) const
       
   741     {
       
   742     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
   743         ( aEntryNumber < iRichText->ParagraphCount() ),
       
   744         Panic( EMsgInvalidEntryNumber ) );
       
   745 
       
   746     TInt entryLength = 0;
       
   747     iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
   748 
       
   749     return ( entryLength == 1 );
       
   750     }
       
   751 
       
   752 // ---------------------------------------------------------
       
   753 // CMsgAddressControlEditor::IsEntryRightToLeft
       
   754 //
       
   755 // ---------------------------------------------------------
       
   756 //
       
   757 TBool CMsgAddressControlEditor::IsEntryRightToLeft( TInt aEntryNumber ) const
       
   758     {
       
   759     TBool isRightToLeft( EFalse );
       
   760 
       
   761     const CMsgAddressControlEditorField* field = Field( aEntryNumber );
       
   762     if ( field )
       
   763         {
       
   764         TPtrC entryText = ReadEntry( aEntryNumber );
       
   765         if ( entryText.Length() > 0 )
       
   766             {
       
   767             if ( TBidiText::TextDirectionality( entryText ) ==
       
   768                 TBidiText::ERightToLeft ) 
       
   769                 {
       
   770                 isRightToLeft = ETrue;
       
   771                 }
       
   772             }
       
   773         } 
       
   774     return isRightToLeft;
       
   775     }
       
   776 
       
   777 // ---------------------------------------------------------
       
   778 // CMsgAddressControlEditor::CheckHighlightingL
       
   779 //
       
   780 // Turns entry as highlighted if the cursor is on the top of the verified
       
   781 // entry, otherwise turns highlighting off if there were any somewhere else.
       
   782 // ---------------------------------------------------------
       
   783 //
       
   784 void CMsgAddressControlEditor::CheckHighlightingL( TBool aCancelFep /*= ETrue*/ )
       
   785     {
       
   786     if ( !iTextView )
       
   787         {
       
   788         return ;
       
   789         }
       
   790 
       
   791     if ( aCancelFep && IsFocused())
       
   792         {
       
   793         CancelFepTransaction();
       
   794         }
       
   795 
       
   796     TInt cursorPos = CursorPos();
       
   797 
       
   798     if ( !IsReadOnly() && IsFieldOnPos( cursorPos ) )
       
   799         {
       
   800         TFindFieldInfo fieldInfo;
       
   801 
       
   802         if ( iRichText->FindFields( fieldInfo, cursorPos, 0 ) )
       
   803             {
       
   804             TCharFormat charFormat;
       
   805             TCharFormatMask applyMask;
       
   806             
       
   807             if ( iHighLightedFieldPos != fieldInfo.iFirstFieldPos )
       
   808                 {
       
   809                 if ( !( iFlags & EMsgControlModeShiftPressed ) )
       
   810                     {
       
   811                     TRgb highlightColor;
       
   812                     
       
   813                     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), 
       
   814                             highlightColor, 
       
   815                             KAknsIIDQsnHighlightColors,
       
   816                             EAknsCIQsnHighlightColorsCG1 );
       
   817 
       
   818                     charFormat.iFontPresentation.iHighlightColor = highlightColor;
       
   819                     applyMask.SetAttrib( EAttFontHighlightColor );
       
   820 
       
   821                     charFormat.iFontPresentation.iHighlightStyle =
       
   822                         TFontPresentation::EFontHighlightNormal;
       
   823                     applyMask.SetAttrib( EAttFontHighlightStyle );
       
   824                     
       
   825                     // Sets only the attributes specified to be set on mask.
       
   826                     iRichText->ApplyCharFormatL(
       
   827                         charFormat,
       
   828                         applyMask,
       
   829                         fieldInfo.iFirstFieldPos,
       
   830                         fieldInfo.iFirstFieldLen );
       
   831                     }
       
   832 
       
   833                 if ( iTextView )
       
   834                     { 
       
   835                     iTextView->HandleRangeFormatChangeL(
       
   836                         TCursorSelection(
       
   837                             fieldInfo.iFirstFieldPos,
       
   838                             fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen ),
       
   839                         EFalse );
       
   840                     }
       
   841 
       
   842                 if ( cursorPos != fieldInfo.iFirstFieldPos && 
       
   843                      !iHandlingPointerEvent )
       
   844                     {
       
   845                     MoveCursorToEntryPosL(EntryNumber( cursorPos ), 0 );
       
   846                     }
       
   847 
       
   848                 TurnHighlightingOffL( aCancelFep );
       
   849                 iHighLightedFieldPos = fieldInfo.iFirstFieldPos;
       
   850                 }
       
   851             }
       
   852         }
       
   853     else
       
   854         {
       
   855         if ( IsReadOnly() && iValidHighlightable )
       
   856 			{
       
   857             // Use "link highlight"
       
   858 			SetHighlightStyleL( EEikEdwinHighlightLink );
       
   859             SelectAllL();
       
   860             }
       
   861 		else
       
   862             {
       
   863             TurnHighlightingOffL( aCancelFep );
       
   864             if ( IsReadOnly() )
       
   865                 {
       
   866                 iTextView->SetDocPosL( cursorPos, ETrue );                    
       
   867                 }
       
   868             }
       
   869         }
       
   870     }
       
   871 
       
   872 // ---------------------------------------------------------
       
   873 // CMsgAddressControlEditor::TurnHighlightingOffL
       
   874 //
       
   875 // Turns highlighting off if it happens to be on aSelection.
       
   876 // ---------------------------------------------------------
       
   877 //
       
   878 void CMsgAddressControlEditor::TurnHighlightingOffL( TCursorSelection aSelection )
       
   879     {
       
   880     if ( !Selection().Length() ||
       
   881         ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ) )
       
   882         {
       
   883         return;
       
   884         }
       
   885 
       
   886     if ( IsFieldOnPos( iHighLightedFieldPos ) )
       
   887         {
       
   888         CancelFepTransaction();
       
   889 
       
   890         TInt selLowerPos = aSelection.LowerPos();
       
   891         // The higherPos is more close to the end of the text
       
   892         TInt selHigherPos = aSelection.HigherPos();
       
   893 
       
   894         TFindFieldInfo fieldInfo;
       
   895         iRichText->FindFields( fieldInfo, iHighLightedFieldPos, 0 );
       
   896 
       
   897         if ( ( selLowerPos >= iHighLightedFieldPos ) &&
       
   898             ( iHighLightedFieldPos + fieldInfo.iFirstFieldLen <= selHigherPos ) )
       
   899             {
       
   900             TurnHighlightingOffL();
       
   901             }
       
   902         }
       
   903     }
       
   904 
       
   905 // ---------------------------------------------------------
       
   906 // CMsgAddressControlEditor::TurnHighlightingOffL
       
   907 //
       
   908 // Turns highlighting off if such a highlighted text field is somewhere.
       
   909 // ---------------------------------------------------------
       
   910 //
       
   911 void CMsgAddressControlEditor::TurnHighlightingOffL( TBool aCancelFep /*= ETrue*/ )
       
   912     {
       
   913     TInt textLength = TextLength();
       
   914 
       
   915     if ( ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ) ||
       
   916         ( iHighLightedFieldPos > textLength ) )
       
   917         {
       
   918         return;
       
   919         }
       
   920 
       
   921     if ( aCancelFep )
       
   922         {
       
   923         CancelFepTransaction();
       
   924         }
       
   925 
       
   926     TInt cursorPos = CursorPos();
       
   927 
       
   928     if ( cursorPos == textLength )
       
   929         {
       
   930         if ( IsFieldOnPos( cursorPos - 1 ) )
       
   931             {
       
   932             // Remove the highlight from last cursor position only if
       
   933             // there is highlightable field. 
       
   934             TurnHighlightingOffFromPosL( cursorPos - 1 );
       
   935             }
       
   936         }
       
   937 
       
   938     TurnHighlightingOffFromPosL( iHighLightedFieldPos );
       
   939     }
       
   940 
       
   941 // ---------------------------------------------------------
       
   942 // CMsgAddressControlEditor::TurnHighlightingOffFromPosL
       
   943 //
       
   944 // Turns highlighting off from position aPos.
       
   945 // ---------------------------------------------------------
       
   946 //
       
   947 void CMsgAddressControlEditor::TurnHighlightingOffFromPosL( TInt aPos )
       
   948     {
       
   949     TInt textLength = TextLength();
       
   950 
       
   951     if ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ||
       
   952          aPos < 0 ||        
       
   953          aPos > textLength )
       
   954         {
       
   955         return;
       
   956         }
       
   957 
       
   958     TFindFieldInfo fieldInfo;
       
   959 
       
   960     if ( !iRichText->FindFields( fieldInfo, aPos, 0 ) )
       
   961         {
       
   962         // iHighLightedFieldPos is not updated correctly and hence, clear whole text
       
   963         fieldInfo.iFirstFieldPos = 0;
       
   964         fieldInfo.iFirstFieldLen = textLength;
       
   965         __ASSERT_DEBUG( EFalse, Panic( EMsgInvalidStartPos ) );
       
   966         }
       
   967     
       
   968     TCharFormat charFormat;
       
   969     TCharFormatMask applyMask;    
       
   970 
       
   971     // background color.
       
   972     charFormat.iFontPresentation.iHighlightColor = AKN_LAF_COLOR( 0 );
       
   973     applyMask.SetAttrib( EAttFontHighlightColor );
       
   974     
       
   975     charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNone;
       
   976     applyMask.SetAttrib( EAttFontHighlightStyle );
       
   977     
       
   978     // Sets only the attributes specified to be set on mask.
       
   979     iRichText->ApplyCharFormatL( charFormat,
       
   980                                  applyMask,
       
   981                                  fieldInfo.iFirstFieldPos,
       
   982                                  fieldInfo.iFirstFieldLen );
       
   983 
       
   984     if ( iTextView )
       
   985         {
       
   986         TCursorSelection selection( fieldInfo.iFirstFieldPos,
       
   987                                     fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen );
       
   988         iTextView->HandleRangeFormatChangeL( selection, EFalse );
       
   989         }
       
   990     
       
   991     if ( iHighLightedFieldPos == aPos )
       
   992         {
       
   993         // If highlight was removed from currently highlighted position 
       
   994         // reset highlighted field position.
       
   995         iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
       
   996         }
       
   997     }
       
   998 
       
   999 // ---------------------------------------------------------
       
  1000 // CMsgAddressControlEditor::CreateEntryStringLC
       
  1001 //
       
  1002 // Creates a suitable text string for the text field using strings aName and
       
  1003 // aAddress and return pointer to it. If aFormat == EFalse, this function does
       
  1004 // not format the string but takes only aAddess. If text string does not fit to
       
  1005 // view it clips it and adds ... to end of it. If text layout does not exist
       
  1006 // this function does not attempt to clip text string.
       
  1007 // ---------------------------------------------------------
       
  1008 //
       
  1009 
       
  1010 HBufC* CMsgAddressControlEditor::CreateEntryStringLC(
       
  1011     const TDesC& aName,
       
  1012     const TDesC& aAddress,
       
  1013     TBool aVerified /*= ETrue*/ )
       
  1014     {
       
  1015     HBufC* addressCopy = aAddress.AllocLC();
       
  1016     TPtr addrTPtr = addressCopy->Des();
       
  1017     AknTextUtils::DisplayTextLanguageSpecificNumberConversion( addrTPtr );
       
  1018     
       
  1019     if ( aVerified || IsReadOnly() )
       
  1020         {
       
  1021         TInt len = aName.Length();
       
  1022         if ( len == 0 )
       
  1023             {
       
  1024             len = addrTPtr.Length();
       
  1025             }
       
  1026 
       
  1027         // +2 for KZeroWidthJoiner and direction marker
       
  1028         HBufC* string = HBufC::NewLC( len + 2 );
       
  1029         TPtr strPtr = string->Des();
       
  1030 
       
  1031         if ( aName.Length() == 0 )
       
  1032             {
       
  1033             strPtr.Append( addrTPtr );
       
  1034             }
       
  1035         else
       
  1036             {
       
  1037             strPtr.Append( aName );
       
  1038             }
       
  1039 
       
  1040         TInt maxWidth = 0;
       
  1041 
       
  1042         if ( iTextView )
       
  1043             {
       
  1044             // We must have iTextView because LayoutWidth calls CursorPos.
       
  1045             maxWidth = LayoutWidth();
       
  1046             }
       
  1047 
       
  1048         if ( maxWidth > 0 )
       
  1049             {
       
  1050             const CFont* font = TextFont();
       
  1051 
       
  1052             if ( strPtr.Length() )
       
  1053                 {
       
  1054                 // Clip a little bit more than maxWidth to prevent wrapping.
       
  1055                 TInt clipWidth = Max( 0, maxWidth - 4 );
       
  1056                 TInt ellipsisWidth = font->CharWidthInPixels( KEllipsis );
       
  1057 
       
  1058                 TInt fits = font->TextCount( strPtr, clipWidth );
       
  1059 
       
  1060                 if ( fits < strPtr.Length() )
       
  1061                     {
       
  1062                     fits = font->TextCount( strPtr, clipWidth - ellipsisWidth );
       
  1063                     
       
  1064                     // Work out the text directionality before the truncation point.
       
  1065                     // First put the text in reverse order and then call
       
  1066                     // TBidiText::TextDirectionality. This effectively tells the
       
  1067                     // directionality of the last strongly directional character
       
  1068                     // in the text.
       
  1069                     HBufC* temp = strPtr.Left( fits ).AllocL();
       
  1070                     TPtr tempPtr = temp->Des();
       
  1071 
       
  1072                     TInt i = 0;
       
  1073                     TInt j = tempPtr.Length() - 1;
       
  1074                     while ( i < j )
       
  1075                         {
       
  1076                         TText t = tempPtr[i];
       
  1077                         tempPtr[i++] = tempPtr[j];
       
  1078                         tempPtr[j--] = t;
       
  1079                         }
       
  1080 
       
  1081                     TBidiText::TDirectionality dir = 
       
  1082                         TBidiText::TextDirectionality( tempPtr );
       
  1083 
       
  1084                     delete temp;
       
  1085 
       
  1086                     TText dirMarker = ( dir == TBidiText::ERightToLeft )
       
  1087                         ? KRLMarker
       
  1088                         : KLRMarker;
       
  1089 
       
  1090                     // Insert zero width joiner if necessary to get the correct glyph form
       
  1091                     // before truncation.
       
  1092 
       
  1093                     TText lastChar = strPtr[fits - 1];
       
  1094                     TText next = strPtr[fits];
       
  1095                     
       
  1096                     TInt ellipsisPos = fits;
       
  1097                     
       
  1098                     if ( CFont::CharactersJoin( lastChar, KZeroWidthJoiner ) &&
       
  1099                          CFont::CharactersJoin( lastChar, next ) )
       
  1100                         {
       
  1101                         strPtr[fits] = KZeroWidthJoiner;
       
  1102                         ellipsisPos++;
       
  1103                         }
       
  1104                     strPtr.SetMax();
       
  1105                     strPtr[ellipsisPos] = KEllipsis;
       
  1106                     // Inserting direction marker after the ellipsis ensures that
       
  1107                     // the ellipsis is shown on the correct side of the text
       
  1108                     // before it.
       
  1109                     strPtr[ellipsisPos + 1] = dirMarker;
       
  1110 
       
  1111                     strPtr.SetLength( ellipsisPos + 2 );
       
  1112                     }
       
  1113                 }
       
  1114             }
       
  1115 
       
  1116         HBufC* newString = strPtr.AllocL();
       
  1117         CleanupStack::PopAndDestroy( 2 );  // string, addressCopy
       
  1118 
       
  1119         CleanupStack::PushL(newString);
       
  1120         return newString;
       
  1121         }
       
  1122     else
       
  1123         {
       
  1124         HBufC* string = addrTPtr.AllocL();
       
  1125         CleanupStack::PopAndDestroy();  // addressCopy
       
  1126         CleanupStack::PushL( string );
       
  1127         return string;
       
  1128         }
       
  1129     }
       
  1130 
       
  1131 // ---------------------------------------------------------
       
  1132 // CMsgAddressControlEditor::ReBuildEntryStringsL
       
  1133 //
       
  1134 // Re-builds all the text strings. Goes through all the fields in the
       
  1135 // text and assigns a new string into them. After this we call UpdateAllFieldsL 
       
  1136 // to update all the fields and after this restores to cursor position
       
  1137 // to old position if it is valid or to the end of the text.
       
  1138 // ---------------------------------------------------------
       
  1139 //
       
  1140 void CMsgAddressControlEditor::ReBuildEntryStringsL()
       
  1141     {
       
  1142     const TInt textLength = TextLength();
       
  1143     TInt length = textLength;
       
  1144     TInt docPos = 0;
       
  1145     TFindFieldInfo fieldInfo;
       
  1146 
       
  1147     iCurrentEntry = EntryNumber( CursorPos() );
       
  1148 
       
  1149     while ( length > 0 &&
       
  1150             docPos < textLength &&
       
  1151             iRichText->FindFields( fieldInfo, docPos, length ) )
       
  1152         {
       
  1153         CMsgAddressControlEditorField* field =
       
  1154             const_cast<CMsgAddressControlEditorField*>( FieldFromPos( fieldInfo.iFirstFieldPos ) );
       
  1155 
       
  1156         HBufC* string = CreateEntryStringLC( *field->Name(), 
       
  1157                                              *field->Address(), 
       
  1158                                              field->IsVerified() );
       
  1159 
       
  1160         field->SetEntryStringL( *string );
       
  1161 
       
  1162         CleanupStack::PopAndDestroy( string );
       
  1163 
       
  1164         if ( fieldInfo.iFieldCountInRange == 0 ) // no more fields left within a range
       
  1165             {
       
  1166             break;
       
  1167             }
       
  1168 
       
  1169         docPos = fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen;
       
  1170         length = textLength - docPos;
       
  1171         }
       
  1172     
       
  1173     if ( IsFocused() )
       
  1174         {
       
  1175         CancelFepTransaction();
       
  1176         }
       
  1177     
       
  1178     TInt oldCursorPos( CursorPos() );
       
  1179 
       
  1180     // Sets cursor pos always to beginning
       
  1181     UpdateAllFieldsL();
       
  1182     
       
  1183     oldCursorPos = Min( oldCursorPos, TextLength() );
       
  1184     
       
  1185     // Restore the original cursor position if it was
       
  1186     // not out of the limit.
       
  1187     SetCursorPosL( oldCursorPos, EFalse );
       
  1188     }
       
  1189 
       
  1190 // ---------------------------------------------------------
       
  1191 // CMsgAddressControlEditor::Field
       
  1192 //
       
  1193 // Returns a field of the entry aEntryNumber. If there is no field on that entry,
       
  1194 // returns NULL.
       
  1195 // ---------------------------------------------------------
       
  1196 //
       
  1197 const CMsgAddressControlEditorField* CMsgAddressControlEditor::Field(
       
  1198     TInt aEntryNumber ) const
       
  1199     {
       
  1200     __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
       
  1201         ( aEntryNumber < iRichText->ParagraphCount() ),
       
  1202         Panic( EMsgInvalidEntryNumber ) );
       
  1203 
       
  1204     TInt entryLength = 0;
       
  1205     TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
       
  1206 
       
  1207     return FieldFromPos( entryStart );
       
  1208     }
       
  1209 
       
  1210 // ---------------------------------------------------------
       
  1211 // CMsgAddressControlEditor::CharAtPos
       
  1212 //
       
  1213 //
       
  1214 // ---------------------------------------------------------
       
  1215 //
       
  1216 TChar CMsgAddressControlEditor::CharAtPos( TInt aPos ) const
       
  1217     {
       
  1218     if ( aPos >= 0 && aPos < TextLength() )
       
  1219         {
       
  1220         TBuf<1> buf;
       
  1221         iText->Extract( buf, aPos, 1 );
       
  1222         return buf[0];
       
  1223         }
       
  1224     else
       
  1225         {
       
  1226         return 0;
       
  1227         }
       
  1228     }
       
  1229 
       
  1230 // ---------------------------------------------------------
       
  1231 // CMsgAddressControlEditor::PrepareForViewing
       
  1232 //
       
  1233 // Prepares control for viewing.
       
  1234 // ---------------------------------------------------------
       
  1235 //
       
  1236 void CMsgAddressControlEditor::PrepareForViewing()
       
  1237     {
       
  1238     if ( iCurrentEntry >= 0 )
       
  1239         {
       
  1240         TRAP_IGNORE( MoveCursorToEntryPosL(
       
  1241             iCurrentEntry, EntryLength( iCurrentEntry ) ) );
       
  1242 
       
  1243         iCurrentEntry = KMsgCurrentEntryNone;
       
  1244         }
       
  1245     }
       
  1246 
       
  1247 // ---------------------------------------------------------
       
  1248 // CMsgAddressControlEditor::PreInsertEditorFormattingL
       
  1249 //
       
  1250 //
       
  1251 // ---------------------------------------------------------
       
  1252 //
       
  1253 void CMsgAddressControlEditor::PreInsertEditorFormattingL( const TKeyEvent& aKeyEvent )
       
  1254     {
       
  1255     if ( IsFocused() && !IsReadOnly() )
       
  1256         {    
       
  1257         TBool modified = EFalse;
       
  1258         TInt editPos = CursorPos();
       
  1259         
       
  1260         // No preinserting is done in a case edit position is over
       
  1261         // text length (should not be possible) or if delete key is pressed.
       
  1262         if ( editPos > TextLength() ||
       
  1263              aKeyEvent.iCode == EKeyDelete )
       
  1264             {
       
  1265             return;
       
  1266             }
       
  1267         
       
  1268         TInt entryNumber = EntryNumber( editPos );
       
  1269         TInt startPos = FirstFieldPos( editPos );
       
  1270         TInt endPos = startPos + EntryLength( entryNumber );
       
  1271         
       
  1272         if ( startPos < editPos && editPos < endPos && 
       
  1273              IsEntryVerified( entryNumber ) )
       
  1274             {
       
  1275             // Cursor is in the middle of verified entry, se inserting not possible.
       
  1276             return;
       
  1277             }
       
  1278             
       
  1279         TChar currentChar = CharAtPos( editPos );
       
  1280         TChar previousChar = CharAtPos( editPos - 1 );
       
  1281         
       
  1282         if ( IsFieldOnLeft( editPos + 1 ) ) // looking on the right, but before the key is inserted
       
  1283             {
       
  1284             // user is trying to add character to left of field:
       
  1285             // insert paragraph delimiter in front of the field,
       
  1286             // and in front of that a semicolon.
       
  1287             iTextView->SetDocPosL( editPos, EFalse );
       
  1288             iRichText->CancelInsertCharFormat();
       
  1289             InsertParagraphL( editPos );
       
  1290             InsertSemicolonL( editPos );
       
  1291             modified = ETrue;
       
  1292             }
       
  1293         else if ( IsFieldOnLeft( editPos ) )
       
  1294             {
       
  1295             // user is trying to add character to right of field:
       
  1296             // insert semicolon after the field if there isn't one already,
       
  1297             // and after that a paragraph delimiter.
       
  1298             iTextView->SetDocPosL( editPos, EFalse );
       
  1299             iRichText->CancelInsertCharFormat();
       
  1300             if ( currentChar != KSemicolon && currentChar != KArabicSemicolon )
       
  1301                 {
       
  1302                 InsertSemicolonL( editPos );
       
  1303                 }
       
  1304             InsertParagraphL( ++editPos );
       
  1305             editPos++;
       
  1306             modified = ETrue;
       
  1307             }
       
  1308         else if ( ( previousChar == KSemicolon || 
       
  1309                     previousChar == KArabicSemicolon  ) &&
       
  1310                   IsFieldOnLeft( editPos - 1 ) )
       
  1311             {
       
  1312             // user is trying to add character to right of semicolon
       
  1313             // and there is field right next to it:
       
  1314             // insert a paragraph delimiter after semicolon.
       
  1315             iTextView->SetDocPosL( editPos, EFalse );
       
  1316             iRichText->CancelInsertCharFormat();
       
  1317             InsertParagraphL( editPos );
       
  1318             editPos++;
       
  1319             modified = ETrue;
       
  1320             }
       
  1321             
       
  1322         if ( modified )
       
  1323             {
       
  1324             CheckHighlightingL( EFalse );
       
  1325 
       
  1326             TInt len = TextLength();
       
  1327             if ( editPos > len )
       
  1328                 {
       
  1329                 editPos = len;
       
  1330                 }
       
  1331 
       
  1332             iTextView->SetDocPosL( editPos, EFalse );
       
  1333 
       
  1334             TViewYPosQualifier yPosQualifier;
       
  1335             yPosQualifier.SetFillScreen();
       
  1336             yPosQualifier.SetMakeLineFullyVisible();
       
  1337             iTextView->HandleGlobalChangeL( yPosQualifier );
       
  1338 
       
  1339             iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
       
  1340             }
       
  1341         }
       
  1342     }
       
  1343 
       
  1344 // ---------------------------------------------------------
       
  1345 // CMsgAddressControlEditor::PostInsertEditorFormattingL
       
  1346 //
       
  1347 //
       
  1348 // ---------------------------------------------------------
       
  1349 //
       
  1350 void CMsgAddressControlEditor::PostInsertEditorFormattingL( TBool aDuplicateEvent )
       
  1351     {
       
  1352     if ( IsFocused() && !IsReadOnly() )
       
  1353         {
       
  1354         TInt editPos = CursorPos();
       
  1355         if ( editPos > TextLength() )
       
  1356             {
       
  1357             return;
       
  1358             }
       
  1359         TChar prevChar = CharAtPos( editPos - 1 );
       
  1360 
       
  1361         if ( !aDuplicateEvent && 
       
  1362              ( prevChar == KSemicolon || prevChar == KArabicSemicolon  ) )
       
  1363             {
       
  1364             // user is at the end of a line, after a semicolon:
       
  1365             // paragraph delimiter after semicolon.
       
  1366             iTextView->SetDocPosL( editPos, EFalse );
       
  1367             iRichText->CancelInsertCharFormat();
       
  1368             InsertParagraphL( editPos++ );
       
  1369                 
       
  1370             TInt len = TextLength();
       
  1371             if ( editPos > len )
       
  1372                 {
       
  1373                 editPos = len;
       
  1374                 }
       
  1375 
       
  1376             iTextView->SetDocPosL( editPos, EFalse );
       
  1377 
       
  1378             TViewYPosQualifier yPosQualifier;
       
  1379             yPosQualifier.SetFillScreen();
       
  1380             yPosQualifier.SetMakeLineFullyVisible();
       
  1381             iTextView->HandleGlobalChangeL( yPosQualifier );
       
  1382 
       
  1383             iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
       
  1384             }
       
  1385         }
       
  1386     }
       
  1387 
       
  1388 // ---------------------------------------------------------
       
  1389 // CMsgAddressControlEditor::CheckEditPermission
       
  1390 //
       
  1391 // Does edit permission check and returns its result.
       
  1392 // ---------------------------------------------------------
       
  1393 //
       
  1394 TUint32 CMsgAddressControlEditor::CheckEditPermission() const
       
  1395     {
       
  1396     TUint32 editPermission = CMsgBaseControl::EMsgEditNone;
       
  1397     TInt textLength = TextLength();
       
  1398     TCursorSelection selection = iTextView->Selection();
       
  1399 
       
  1400     if ( selection.Length() )
       
  1401         {
       
  1402         TInt selLowerPos = selection.LowerPos();
       
  1403         // The higherPos is more close to the end of the text
       
  1404         TInt selHigherPos = selection.HigherPos();
       
  1405         TFindFieldInfo fieldInfoLower;
       
  1406         TFindFieldInfo fieldInfoHigher;
       
  1407         TBool lowerPosOnField(
       
  1408             iRichText->FindFields( fieldInfoLower, selLowerPos, 0 ) );
       
  1409         TBool higherPosOnField(
       
  1410             iRichText->FindFields( fieldInfoHigher, selHigherPos, 0 ) );
       
  1411 
       
  1412         if ( lowerPosOnField && higherPosOnField )
       
  1413             {
       
  1414             // Both the lowerPos and the higherPos are on a field
       
  1415             if ( IsPosAtEntryBeginning( selLowerPos ) &&
       
  1416                 IsPosAtEntryBeginning( selHigherPos ) )
       
  1417                 {
       
  1418                 // Both positions are at the beginning of the fields
       
  1419                 editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter
       
  1420                     | CMsgAddressControl::EMsgEditBackspace
       
  1421                     | CMsgAddressControl::EMsgEditDelete
       
  1422                     | CMsgBaseControl::EMsgEditCut;
       
  1423                 }
       
  1424             }
       
  1425         else if ( lowerPosOnField )
       
  1426             {
       
  1427             if ( IsPosAtEntryBeginning( selLowerPos ) )
       
  1428                 {
       
  1429                 editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter
       
  1430                     | CMsgAddressControl::EMsgEditBackspace
       
  1431                     | CMsgAddressControl::EMsgEditCharInsert
       
  1432                     | CMsgAddressControl::EMsgEditDelete
       
  1433                     | CMsgBaseControl::EMsgEditCut
       
  1434                     | CMsgBaseControl::EMsgEditPaste;
       
  1435                 }
       
  1436             }
       
  1437         else if ( higherPosOnField )
       
  1438             {
       
  1439             if ( IsPosAtEntryBeginning( selHigherPos ) )
       
  1440                 {
       
  1441                 editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
       
  1442                 }
       
  1443             }
       
  1444         else if ( IsFieldOnLeft( selLowerPos ) )
       
  1445             {
       
  1446             // Neither position are on a field but the lower pos is
       
  1447             // just next to a field on the right side
       
  1448             editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
       
  1449             }
       
  1450         else
       
  1451             {
       
  1452             // Neither position are on a field
       
  1453             editPermission |= CMsgAddressControl::EMsgEditCharInsert
       
  1454                 | CMsgAddressControl::EMsgEditParagraphDelimiter
       
  1455                 | CMsgAddressControl::EMsgEditBackspace
       
  1456                 | CMsgAddressControl::EMsgEditDelete
       
  1457                 | CMsgBaseControl::EMsgEditCut
       
  1458                 | CMsgBaseControl::EMsgEditPaste;
       
  1459             }
       
  1460 
       
  1461         // Copy is always possible
       
  1462         editPermission |= CMsgBaseControl::EMsgEditCopy;
       
  1463 
       
  1464         // BackspaceMove and RemoveEntry are never possible when selection is on
       
  1465         editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
       
  1466         editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1467 
       
  1468         editPermission |=
       
  1469             (selHigherPos - selLowerPos) == textLength ?
       
  1470             CMsgBaseControl::EMsgEditUnSelectAll : 0;
       
  1471         }
       
  1472     else
       
  1473         {
       
  1474         // Selection is off
       
  1475         TInt cursorPos = CursorPos();
       
  1476         TBool posAtEntryBeginning = IsPosAtEntryBeginning( cursorPos );
       
  1477         TChar ch = CharAtPos( cursorPos - 1 );
       
  1478         TChar nextCh = CharAtPos( cursorPos );
       
  1479 
       
  1480         if ( ch == CEditableText::EParagraphDelimiter )
       
  1481             {
       
  1482             ch = CharAtPos( cursorPos - 2 );
       
  1483             }
       
  1484 
       
  1485         TInt entryAtPos = EntryNumber( cursorPos );
       
  1486 
       
  1487         if ( IsFieldOnPos( cursorPos ) && !posAtEntryBeginning )
       
  1488             {
       
  1489             // The cursor is in a field. No edit actions are allowed.
       
  1490             editPermission = (TUint32) CMsgBaseControl::EMsgEditNone;
       
  1491             }
       
  1492         else if ( IsFieldOnLeft( cursorPos ) && !posAtEntryBeginning )
       
  1493             {
       
  1494             // The cursor is not on a field but just next to it on the right
       
  1495             // side. Only the paragraph delimiter can be inserted or the field
       
  1496             // can be removed by the backspace.
       
  1497             editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
       
  1498             editPermission |= CMsgAddressControl::EMsgEditRemoveEntry;
       
  1499             editPermission |= CMsgAddressControl::EMsgEditCharInsert;
       
  1500             // This should check also a situation when next entry is empty
       
  1501             // and when delete is also possible.
       
  1502             }
       
  1503         else if ( ( ch == KSemicolon || ch == KArabicSemicolon 
       
  1504                 || IsPriorEntryVerified( entryAtPos ) ) && posAtEntryBeginning )
       
  1505             {
       
  1506             // The cursor is not in a field but just below it at the
       
  1507             // beginning of the line.
       
  1508             if ( IsEntryEmpty( entryAtPos ) )
       
  1509                 {
       
  1510                 // Current entry is empty. RemoveEntry and BackspaceMove
       
  1511                 // the edit actions are not allowed.
       
  1512                 editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
       
  1513                 editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
       
  1514                 editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1515                 }
       
  1516             else
       
  1517                 {
       
  1518                 // Pressing the backspace button is allowed but no char
       
  1519                 // removal i.e the BackspaceMove is allowed.
       
  1520                 editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
       
  1521                 editPermission &= ~CMsgAddressControl::EMsgEditBackspace;
       
  1522                 editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1523                 }
       
  1524             }
       
  1525         else
       
  1526             {
       
  1527             // The cursor is somewhere else but in a field or next to it on
       
  1528             // the right side. All but the RemoveEntry and BackspaceMove the
       
  1529             // edit actions are allowed.
       
  1530             editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
       
  1531             editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
       
  1532             editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1533             }
       
  1534 
       
  1535         if ( IsFieldOnRight( cursorPos ) )
       
  1536             {
       
  1537             // Field immediatelly on right side of curser. Delete and RemoveEntry
       
  1538             // are allowed.
       
  1539             editPermission |= CMsgAddressControl::EMsgEditDelete;
       
  1540             editPermission |= CMsgAddressControl::EMsgEditRemoveEntry;
       
  1541             }
       
  1542         else if ( IsFieldOnRight( cursorPos + 1) && 
       
  1543                   nextCh == CEditableText::EParagraphDelimiter )
       
  1544             {
       
  1545             // The cursor is not in a field but just above it at the
       
  1546             // end of the line.
       
  1547             if ( IsEntryEmpty( entryAtPos ) )
       
  1548                 {
       
  1549                 // Current entry is empty. RemoveEntry are not allowed.
       
  1550                 editPermission |= CMsgAddressControl::EMsgEditDelete;
       
  1551                 editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1552                 }
       
  1553             else
       
  1554                 {
       
  1555                 // Current entry is not empty. Delete is not allowed.
       
  1556                 editPermission &= ~CMsgAddressControl::EMsgEditDelete;
       
  1557                 }
       
  1558             }
       
  1559 
       
  1560         // Copy is never allowed when selection is off.
       
  1561         editPermission &= ~CMsgBaseControl::EMsgEditCopy;
       
  1562         // Cut is never allowed when selection is off.
       
  1563         editPermission &= ~CMsgBaseControl::EMsgEditCut;
       
  1564         // UnSelectAll is never allowed when selection is off.
       
  1565         editPermission &= ~CMsgBaseControl::EMsgEditUnSelectAll;
       
  1566         }
       
  1567 
       
  1568     editPermission &= ~CMsgBaseControl::EMsgEditUndo; // Undo is never allowed.
       
  1569 
       
  1570     if ( textLength )
       
  1571         {
       
  1572         editPermission |= CMsgBaseControl::EMsgEditSelectAll;
       
  1573         }
       
  1574     else
       
  1575         {
       
  1576         editPermission &= ~CMsgBaseControl::EMsgEditSelectAll;
       
  1577         }
       
  1578 
       
  1579     if ( IsReadOnly() )
       
  1580         {
       
  1581         editPermission &= ~CMsgBaseControl::EMsgEditPaste;
       
  1582         editPermission &= ~CMsgBaseControl::EMsgEditCut;
       
  1583         editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
       
  1584         editPermission &= ~CMsgAddressControl::EMsgEditParagraphDelimiter;
       
  1585         editPermission &= ~CMsgAddressControl::EMsgEditCharInsert;
       
  1586         }
       
  1587 
       
  1588     return editPermission;
       
  1589     }
       
  1590 
       
  1591 // ---------------------------------------------------------
       
  1592 // CMsgAddressControlEditor::ConstructFromResourceL
       
  1593 //
       
  1594 // Creates this control from resource.
       
  1595 // ---------------------------------------------------------
       
  1596 //
       
  1597 void CMsgAddressControlEditor::ConstructFromResourceL( TResourceReader& aReader )
       
  1598     {
       
  1599     // This used to be font id. Not used anymore. Have to read it, though.
       
  1600     /*TInt fontId =*/ aReader.ReadInt32();
       
  1601 
       
  1602     ConstructL();
       
  1603 
       
  1604     iAddressControlEditorFieldFactory =
       
  1605         new ( ELeave ) TMsgAddressControlEditorFieldFactory();
       
  1606 
       
  1607     if ( !IsReadOnly() )
       
  1608         {
       
  1609         ReadAknResourceL( aReader );
       
  1610         }
       
  1611     }
       
  1612 
       
  1613 // ---------------------------------------------------------
       
  1614 // CMsgAddressControlEditor::SetAndGetSizeL
       
  1615 //
       
  1616 // Calculates and sets the size of the control and returns new size as
       
  1617 // reference aSize. Sets maximum height for editor to be maximum
       
  1618 // body height. If our height has already been set then uses the current
       
  1619 // one since edwin will decide internally what is the correct height and
       
  1620 // report this through HandleEdwinSizeEventL observer interface. 
       
  1621 // After all this finally set the size to 
       
  1622 // edwin. This might cause reformatting so after this we need to check
       
  1623 // whether we are band formatting and set the size to maximum body height
       
  1624 // if we are since edwin will not report height change through HandleEdwinSizeEventL
       
  1625 // when band formatting is enabled.
       
  1626 // ---------------------------------------------------------
       
  1627 //
       
  1628 void CMsgAddressControlEditor::SetAndGetSizeL( TSize& aSize )
       
  1629     {
       
  1630     TSize controlSize( aSize );
       
  1631     
       
  1632     if ( iSize.iHeight > 0 )
       
  1633         {
       
  1634         controlSize.iHeight = iSize.iHeight;
       
  1635         }
       
  1636 
       
  1637     CMsgExpandableControlEditor::SetAndGetSizeL( aSize );
       
  1638     
       
  1639     // Make sure that if we are band formatting editor size is set
       
  1640     // to maximum body height. Will not do any harm resetting this
       
  1641     // even if we already are at maximum body height.
       
  1642     if ( TextLayout() && TextLayout()->IsFormattingBand() )
       
  1643         {
       
  1644         controlSize.iHeight = MaximumHeight();
       
  1645         SetSizeWithoutNotification( controlSize );
       
  1646         }
       
  1647     
       
  1648     aSize = iSize;
       
  1649     }
       
  1650 
       
  1651 // ---------------------------------------------------------
       
  1652 // CMsgAddressControlEditor::OfferKeyEventL
       
  1653 //
       
  1654 // Handles key event.
       
  1655 // ---------------------------------------------------------
       
  1656 //
       
  1657 TKeyResponse CMsgAddressControlEditor::OfferKeyEventL(
       
  1658     const TKeyEvent& aKeyEvent, TEventCode aType )
       
  1659     {
       
  1660     if ( IsReadOnly() && 
       
  1661         aKeyEvent.iCode == EKeyUpArrow &&
       
  1662         iValidHighlightable )
       
  1663         {
       
  1664         return EKeyWasConsumed;
       
  1665         }
       
  1666     return CMsgExpandableControlEditor::OfferKeyEventL( aKeyEvent, aType );
       
  1667     }
       
  1668 
       
  1669 // ---------------------------------------------------------
       
  1670 // CMsgAddressControlEditor::HandlePointerEventL
       
  1671 //
       
  1672 // Handles pointer events. Sets handling pointer event flag on during
       
  1673 // edwin pointer event handling so that callbacks from edwin can
       
  1674 // use this information. 
       
  1675 // In readonly mode:
       
  1676 // On button down event when automatic find is
       
  1677 // activated stores the previously focused field if there is one. 
       
  1678 // On button up event checks whether same field is still focused. 
       
  1679 // If user has tapped already focused field again selection key menu
       
  1680 // is launched by simulating key event into it.
       
  1681 // In non-readonly mode:
       
  1682 // If user taps in the middle of validated recipient field cursor
       
  1683 // is moved to the beginning of that field if it is not already located
       
  1684 // there. Also highlight is checked.
       
  1685 // ---------------------------------------------------------
       
  1686 //
       
  1687 #ifdef RD_SCALABLE_UI_V2
       
  1688 void CMsgAddressControlEditor::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
  1689     {
       
  1690     iHandlingPointerEvent = ETrue;
       
  1691     
       
  1692     TBool forwardRequest( ETrue );
       
  1693     
       
  1694     if ( IsReadOnly() )
       
  1695         {
       
  1696         if ( iValidHighlightable && 
       
  1697              ( aPointerEvent.iType == TPointerEvent::EButton1Down ||
       
  1698                aPointerEvent.iType == TPointerEvent::EButton1Up ) )
       
  1699             {
       
  1700             TPoint tapPoint( aPointerEvent.iPosition );
       
  1701             TInt docPos( TextView()->XyPosToDocPosL( tapPoint ) );
       
  1702             
       
  1703             const CMsgAddressControlEditorField* currentField = FieldFromPos( docPos );
       
  1704                 
       
  1705             if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
       
  1706                 {
       
  1707                 iPreviousField = currentField;
       
  1708                             
       
  1709                 if ( iPreviousField &&
       
  1710                      !iPreviousField->IsVerified() )
       
  1711                     {
       
  1712                     iPreviousField = NULL;
       
  1713                     }
       
  1714                 else
       
  1715                     {
       
  1716                     forwardRequest = EFalse;
       
  1717                     }
       
  1718                 }
       
  1719             else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
       
  1720                 {
       
  1721                 if ( currentField &&
       
  1722                      iPreviousField == currentField )
       
  1723                     {
       
  1724                     TKeyEvent event;
       
  1725                     event.iCode = EKeyDevice3;
       
  1726                     event.iScanCode = EStdKeyDevice3;
       
  1727                     event.iModifiers = 0;
       
  1728                     event.iRepeats = 0;
       
  1729                     
       
  1730                     iCoeEnv->WsSession().SimulateKeyEvent( event );
       
  1731                     
       
  1732                     forwardRequest = EFalse;
       
  1733                     }
       
  1734                 }
       
  1735             }
       
  1736         }
       
  1737     else
       
  1738         {
       
  1739         if ( aPointerEvent.iType == TPointerEvent::EButton1Down ||
       
  1740              aPointerEvent.iType == TPointerEvent::EButton1Up )
       
  1741             {
       
  1742             TPoint tapPoint( aPointerEvent.iPosition );
       
  1743             TInt docPos( TextView()->XyPosToDocPosL( tapPoint ) );
       
  1744             
       
  1745             const CMsgAddressControlEditorField* currentField = FieldFromPos( docPos );
       
  1746             
       
  1747             if ( currentField &&
       
  1748                  currentField->IsVerified() )
       
  1749                 {
       
  1750               //  forwardRequest = EFalse;
       
  1751                 TInt entryStartPos = EntryStartPos( EntryNumber( docPos ) );
       
  1752                 if ( entryStartPos != CursorPos() )
       
  1753                     {
       
  1754                     SetCursorPosL( entryStartPos, EFalse );
       
  1755                     CheckHighlightingL();
       
  1756                     }                    
       
  1757                 }
       
  1758             }
       
  1759         }
       
  1760         
       
  1761     if ( forwardRequest )
       
  1762         {
       
  1763         CMsgExpandableControlEditor::HandlePointerEventL( aPointerEvent );
       
  1764         }
       
  1765 #ifdef RD_TACTILE_FEEDBACK         
       
  1766     else if(aPointerEvent.iType == TPointerEvent::EButton1Down)
       
  1767         {                                
       
  1768         MTouchFeedback* feedback = MTouchFeedback::Instance();
       
  1769         if ( feedback )
       
  1770             {
       
  1771             feedback->InstantFeedback( this, ETouchFeedbackBasic );
       
  1772             }
       
  1773         }
       
  1774 #endif        
       
  1775             
       
  1776     iHandlingPointerEvent = EFalse;
       
  1777     }
       
  1778 #else
       
  1779 void CMsgAddressControlEditor::HandlePointerEventL( const TPointerEvent& /*aPointerEvent*/ )
       
  1780     {
       
  1781     }
       
  1782 #endif // RD_SCALABLE_UI_V2
       
  1783 
       
  1784 // ---------------------------------------------------------
       
  1785 // CMsgAddressControlEditor::HandleResourceChange
       
  1786 //
       
  1787 // During layout switching if editor contains text highlight is
       
  1788 // turned off and entry string are rebuild as width of the editor
       
  1789 // might have changed. Also underlining is checked.
       
  1790 // ---------------------------------------------------------
       
  1791 //
       
  1792 void CMsgAddressControlEditor::HandleResourceChange( TInt aType )
       
  1793     {
       
  1794     if ( aType == KEikDynamicLayoutVariantSwitch )
       
  1795         {
       
  1796         CMsgExpandableControlEditor::HandleResourceChange( aType );
       
  1797     
       
  1798 	    //SKIM-7NKC4B
       
  1799         /*if ( TextLength() > 0 )
       
  1800             {
       
  1801             TRAP_IGNORE( 
       
  1802                 {
       
  1803                 TurnHighlightingOffL();
       
  1804                 ReBuildEntryStringsL();
       
  1805             
       
  1806                 CheckUnderliningL();
       
  1807                 
       
  1808                 if ( IsFocused() )
       
  1809                     {
       
  1810                     CheckHighlightingL( EFalse );
       
  1811                     }
       
  1812                 } );
       
  1813             }
       
  1814 	    */
       
  1815         }
       
  1816     else
       
  1817         {
       
  1818         CMsgExpandableControlEditor::HandleResourceChange( aType );
       
  1819         }
       
  1820     }
       
  1821 
       
  1822 // ---------------------------------------------------------
       
  1823 // CMsgAddressControlEditor::InsertParagraphL
       
  1824 //
       
  1825 //
       
  1826 // ---------------------------------------------------------
       
  1827 //
       
  1828 void CMsgAddressControlEditor::InsertParagraphL( TInt aPos )
       
  1829     {
       
  1830     iRichText->InsertL( aPos, CEditableText::EParagraphDelimiter );
       
  1831     iTextView->HandleCharEditL( CTextLayout::EFParagraphDelimiter );
       
  1832     }
       
  1833 
       
  1834 // ---------------------------------------------------------
       
  1835 // CMsgAddressControlEditor::InsertSemicolonL
       
  1836 //
       
  1837 //
       
  1838 // ---------------------------------------------------------
       
  1839 //
       
  1840 void CMsgAddressControlEditor::InsertSemicolonL( TInt aPos )
       
  1841     {
       
  1842     TInt langcode = CAknEnv::Static()->SettingCache().InputLanguage();
       
  1843     TChar semicolon = ( langcode == ELangArabic )
       
  1844         ? KArabicSemicolon
       
  1845         : KSemicolon; 
       
  1846 
       
  1847     iRichText->InsertL( aPos, semicolon );
       
  1848     iTextView->HandleCharEditL( CTextLayout::EFCharacterInsert );
       
  1849     }
       
  1850 
       
  1851 // ---------------------------------------------------------
       
  1852 // CMsgAddressControlEditor::CcpuPasteL
       
  1853 //
       
  1854 //
       
  1855 // ---------------------------------------------------------
       
  1856 //
       
  1857 void CMsgAddressControlEditor::CcpuPasteL()
       
  1858     {
       
  1859     TInt cursorPos = CursorPos();
       
  1860     TChar ch = CharAtPos ( cursorPos );
       
  1861 
       
  1862     if ( ch == KSemicolon || ch == KArabicSemicolon )
       
  1863         {
       
  1864         iRichText->CancelInsertCharFormat();
       
  1865         iRichText->InsertL(cursorPos, CEditableText::EParagraphDelimiter);
       
  1866         iTextView->HandleCharEditL( CTextLayout::EFParagraphDelimiter );
       
  1867         }
       
  1868 
       
  1869     CMsgExpandableControlEditor::CcpuPasteL();
       
  1870     }
       
  1871 
       
  1872 // ---------------------------------------------------------
       
  1873 // CMsgAddressControlEditor::SetAddressFieldAutoHighlight
       
  1874 //
       
  1875 //
       
  1876 // ---------------------------------------------------------
       
  1877 //
       
  1878 void CMsgAddressControlEditor::SetAddressFieldAutoHighlight( TBool aValidHighlightable )
       
  1879     {
       
  1880     if ( iValidHighlightable != aValidHighlightable && !aValidHighlightable )
       
  1881         {
       
  1882         // Automatic find turned off -> cancel selection
       
  1883         TRAP_IGNORE( ClearSelectionL() );
       
  1884         }
       
  1885     iValidHighlightable = aValidHighlightable;
       
  1886     
       
  1887     TRAP_IGNORE( CheckUnderliningL() );
       
  1888     }
       
  1889 
       
  1890 // ---------------------------------------------------------
       
  1891 // CMsgAddressControlEditor::CheckUnderliningL
       
  1892 //
       
  1893 //
       
  1894 // ---------------------------------------------------------
       
  1895 //
       
  1896 void CMsgAddressControlEditor::CheckUnderliningL()
       
  1897     {
       
  1898     TInt textLength = TextLength();
       
  1899     TInt length = textLength;
       
  1900     TInt docPos = 0;
       
  1901     TFindFieldInfo fieldInfo;
       
  1902         
       
  1903     while ( length > 0 &&
       
  1904             docPos < textLength &&
       
  1905             iRichText->FindFields( fieldInfo, docPos, length ) )
       
  1906         {
       
  1907         TCharFormat currentCharFormat;
       
  1908         TCharFormatMask currentCharMask;
       
  1909         
       
  1910         TCharFormat newCharFormat;
       
  1911         TCharFormatMask newCharMask;
       
  1912         
       
  1913         iRichText->GetCharFormat( currentCharFormat,
       
  1914                                   currentCharMask,
       
  1915                                   fieldInfo.iFirstFieldPos,
       
  1916                                   fieldInfo.iFirstFieldLen );
       
  1917         
       
  1918         if ( iValidHighlightable )
       
  1919             {
       
  1920             if ( currentCharFormat.iFontPresentation.iUnderline != EUnderlineOn )
       
  1921                 {
       
  1922                 newCharFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
  1923                 newCharMask.SetAttrib( EAttFontUnderline );
       
  1924                 }
       
  1925             }
       
  1926         else
       
  1927             {
       
  1928             if ( currentCharFormat.iFontPresentation.iUnderline != EUnderlineOff )
       
  1929                 {
       
  1930                 newCharFormat.iFontPresentation.iUnderline = EUnderlineOff;
       
  1931                 newCharMask.SetAttrib( EAttFontUnderline );
       
  1932                 }
       
  1933             }
       
  1934         
       
  1935         if ( newCharMask.AttribIsSet( EAttFontUnderline ) )
       
  1936             {
       
  1937             iRichText->ApplyCharFormatL( newCharFormat,
       
  1938                                          newCharMask,
       
  1939                                          fieldInfo.iFirstFieldPos,
       
  1940                                          fieldInfo.iFirstFieldLen );
       
  1941             }
       
  1942         
       
  1943         if ( fieldInfo.iFieldCountInRange == 0 ) // no more fields left within a range
       
  1944             {
       
  1945             break;
       
  1946             }
       
  1947         
       
  1948         docPos = fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen;
       
  1949         length = textLength - docPos;
       
  1950         }
       
  1951     }
       
  1952 
       
  1953 // ---------------------------------------------------------
       
  1954 // CMsgAddressControlEditor::PrepareForReadOnlyL
       
  1955 // ---------------------------------------------------------
       
  1956 //
       
  1957 void CMsgAddressControlEditor::PrepareForReadOnlyL( TBool aReadOnly )
       
  1958     {
       
  1959     if ( IsReadOnly() == aReadOnly )
       
  1960         {
       
  1961         return;
       
  1962         }
       
  1963 
       
  1964     if ( aReadOnly )
       
  1965         {
       
  1966 #ifdef RD_SCALABLE_UI_V2
       
  1967         SetHighlightStyleL( EEikEdwinHighlightLink );
       
  1968 #endif   
       
  1969         
       
  1970         SetWordWrapL( EFalse );
       
  1971         if ( AddressFieldAutoHighlight() )
       
  1972             {
       
  1973             SelectAllL(); // for automatic highlight
       
  1974             }
       
  1975         }
       
  1976     
       
  1977     CMsgExpandableControlEditor::PrepareForReadOnlyL( aReadOnly );
       
  1978     }
       
  1979 
       
  1980 //  End of File