wvuing/wvuiave/AppSrc/CCARichTextContainer.cpp
changeset 0 094583676ce7
equal deleted inserted replaced
-1:000000000000 0:094583676ce7
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Rich text container
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "CCARichTextContainer.h"
       
    22 #include    "CCAMessageWrapper.h"
       
    23 #include    "MCATextView.h"
       
    24 #include    "ChatDebugAssert.h"
       
    25 #include    "IMUtils.h"
       
    26 //#include    "IMPSCspAllErrors.h"
       
    27 #include    "IMNoteMapper.h"
       
    28 #include    "ChatDefinitions.h"
       
    29 #include    "ChatDebugPrint.h"
       
    30 #include    "IMUtils.h"
       
    31 #include    "MCAStoredContacts.h"
       
    32 #include    "CCAStorageManagerFactory.h"
       
    33 #include    "CCAAppSettingsSAPExt.h"
       
    34 
       
    35 #include    "CCAPicture.h"
       
    36 #include    "ccaappui.h"
       
    37 //#include    "ccaengine.h"
       
    38 #include    "MCAConversationMessage.h"
       
    39 #include    "MCAMessageUtils.h"
       
    40 #include    "MCAContentProcessor.h"
       
    41 #include    "CCAContentMessage.h"
       
    42 #include    "CCAMessageExtensionsHandler.h"
       
    43 #include    "impsbuilddefinitions.h"
       
    44 
       
    45 #include    <chatNG.rsg>
       
    46 #include    <AknIconUtils.h>
       
    47 #include    <txtrich.h>     // CRichtText
       
    48 #include    <AknUtils.h>
       
    49 #include    <aknsettingcache.h>
       
    50 #include    <aknenv.h>
       
    51 #include    <aknconsts.h>
       
    52 #include    <finditemengine.h>
       
    53 #include    <gulicon.h>
       
    54 #include    <barsread.h> // resourcereader
       
    55 #include    <stringloader.h>
       
    56 #include 	<CAVariationNG.rsg>
       
    57 
       
    58 #include    <aknsdrawutils.h>
       
    59 #include    <aknsutils.h>
       
    60 #include    <aknutils.h>
       
    61 
       
    62 #include	"MCASettingsPC.h"
       
    63 #include	"MCAMsgAddedToRichTxtCtrlObserver.h"
       
    64 
       
    65 #include	"MCAProcessManager.h"
       
    66 #include	"MCAGroupPC.h"
       
    67 #include    "IMUtils.h"
       
    68 
       
    69 #include <AknLayoutScalable_Apps.cdl.h>
       
    70 #include "TCAChatListBoxLayout.h"
       
    71 
       
    72 // The Settings have been moved to Cenrep (also retained in the Resource file),
       
    73 // so the enums for keys and central repository header is added here
       
    74 #include 	"VariantKeys.h"
       
    75 
       
    76 
       
    77 // CONSTANTS
       
    78 const TInt KChatHighlightColor = 244;
       
    79 const TInt KPixelsBetweenLines = 8;      // pixels between text lines
       
    80 const TInt KTimeStampMaxLength = 15;     // max length of timestamp text
       
    81 const TInt KUnicodeRLM         = 0x200F; // Right-to-Left Mark
       
    82 const TInt KUnicodeLRM         = 0x200E; // Left-to-Right Mark
       
    83 const TInt KMaxLength          = 10;    // Max Length for user identity
       
    84 _LIT( KSeparator, ": " );
       
    85 
       
    86 
       
    87 // ============================ MEMBER FUNCTIONS ===============================
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // CCARichTextContainer::CCARichTextContainer
       
    91 // C++ default constructor can NOT contain any code, that
       
    92 // might leave.
       
    93 // -----------------------------------------------------------------------------
       
    94 //
       
    95 CCARichTextContainer::CCARichTextContainer( MCAAppUi& aAppUi,
       
    96                                             MCASettingsPC& aSettingsPC,
       
    97                                             MCATextView& aTextView,
       
    98                                             CCAMessageExtensionsHandler& aExtensionsHandler,
       
    99                                             CGulIcon*& aFromMe,
       
   100                                             CGulIcon*& aToMe,
       
   101                                             CGulIcon*& aUnsupported,
       
   102                                             CGulIcon*& aCorrupted,
       
   103                                             MGraphicsDeviceMap& aMap,
       
   104                                             TBool aScrollOver,
       
   105                                             MCAMsgAddedToRichTxtCtrlObserver* aAddMsgObserver
       
   106                                           )
       
   107         : iAppUi( aAppUi ),
       
   108         iSettings( aSettingsPC ),
       
   109         iTextView( aTextView ),
       
   110         iFromMe( aFromMe ),
       
   111         iToMe( aToMe ),
       
   112         iUnsupported( aUnsupported ),
       
   113         iCorrupted( aCorrupted ),
       
   114         iItemHighlight( ETrue ),
       
   115         iHighlightState( ENoHighlight ),
       
   116         iExtensionsHandler( aExtensionsHandler ),
       
   117         iMap( aMap ),
       
   118         iScrollOver( aScrollOver ),
       
   119         iAddMsgObserver( aAddMsgObserver )
       
   120     {
       
   121     iThumbSize = TSize( 42, 36 );
       
   122     iMessagesDeleted = EFalse;
       
   123     }
       
   124 
       
   125 // -----------------------------------------------------------------------------
       
   126 // CCARichTextContainer::ConstructL
       
   127 // Symbian 2nd phase constructor can leave.
       
   128 // -----------------------------------------------------------------------------
       
   129 //
       
   130 void CCARichTextContainer::ConstructL()
       
   131     {
       
   132     iAppUi.AddLayoutChangeObserver( this );
       
   133 
       
   134     // setup layout
       
   135     TAknLayoutId layoutId;
       
   136     CAknEnv::Static()->GetCurrentLayoutId( layoutId );
       
   137 
       
   138     AknIconUtils::SetSize( iCorrupted->Bitmap(), iThumbSize );
       
   139     AknIconUtils::SetSize( iUnsupported->Bitmap(), iThumbSize );
       
   140 
       
   141     // get icon settings
       
   142     iOwnMsgIcon = IMUtils::IntResourceValueL(
       
   143                       RSC_CHAT_VARIATION_OWN_MSG_ICON );
       
   144 
       
   145     iMsgIcon = IMUtils::IntResourceValueL(
       
   146                    RSC_CHAT_VARIATION_MSG_ICON );
       
   147 
       
   148     CCAAppUi* appUI = static_cast <CCAAppUi*> ( CCoeEnv::Static()->AppUi() );
       
   149 
       
   150     //Removed the ownership of iConnUI from this file and made it a reference
       
   151     //APPUI owns this connection UI instance and shares the same with this component.
       
   152     // get user-defined colors from SAP settings
       
   153     CCAAppSettingsSAPExt* SAPExtension = CCAAppSettingsSAPExt::NewLC( appUI->ConnectionUI() );
       
   154     TInt ownCol( SAPExtension->IntValueL( KIMOwnMessageColourKey ) );
       
   155     TInt otherCol( SAPExtension->IntValueL( KIMOthersMessageColourKey ) );
       
   156     CleanupStack::PopAndDestroy( SAPExtension );
       
   157 
       
   158     // Check timestamp setting
       
   159     iShowTimeStamps = iSettings.GetBoolValuePC( TEnumsPC::EShowTimeStamps, NULL );
       
   160 
       
   161     if ( ownCol != KErrNotFound )
       
   162         {
       
   163         iOwnMsgColorInUse = ETrue;
       
   164         iOwnMsgColor = ownCol;
       
   165         }
       
   166     if ( otherCol != KErrNotFound )
       
   167         {
       
   168         iMsgColorInUse = ETrue;
       
   169         iMsgColor = otherCol;
       
   170         }
       
   171 
       
   172     // check resource colours
       
   173     // The default colours settings is present only in the variation resource file. so we use IntResourceValueFromRssL instead of IntResourceValueL
       
   174     TBool defaultColors = IMUtils::IntResourceValueFromRssL(
       
   175                               RSC_CHAT_DEFAULT_MESSAGE_COLORS );
       
   176     iColorWholeMessage = IMUtils::IntResourceValueFromRssL(
       
   177                              RSC_CHAT_COLOR_WHOLE_MESSAGE );
       
   178 
       
   179     if ( !defaultColors && !iMsgColorInUse )
       
   180         {
       
   181         // user-defined color not defined and resource colour in use
       
   182         TResourceReader reader;
       
   183         // Since the color settings is not part of Cenrep, the ID is changed to denote the same.
       
   184         CCoeEnv::Static()->CreateResourceReaderLC( reader,
       
   185                                                    RSC_CHAT_MESSAGE_COLOR );
       
   186         TUint8 red( reader.ReadUint8() );
       
   187         TUint8 green( reader.ReadUint8() );
       
   188         TUint8 blue( reader.ReadUint8() );
       
   189         iMsgColor = TRgb( red, green, blue );
       
   190         iMsgColorInUse = ETrue;
       
   191         CleanupStack::PopAndDestroy(); // reader
       
   192         }
       
   193 
       
   194     if ( !defaultColors && !iOwnMsgColorInUse )
       
   195         {
       
   196         // user-defined color not defined and resource colour in use
       
   197         TResourceReader reader;
       
   198         // Since the color settings is not part of Cenrep, the ID is changed to denote the same.
       
   199         CCoeEnv::Static()->CreateResourceReaderLC( reader,
       
   200                                                    RSC_CHAT_OWN_MESSAGE_COLOR );
       
   201         TUint8 red( reader.ReadUint8() );
       
   202         TUint8 green( reader.ReadUint8() );
       
   203         TUint8 blue( reader.ReadUint8() );
       
   204         iOwnMsgColor = TRgb( red, green, blue );
       
   205         iOwnMsgColorInUse = ETrue;
       
   206         CleanupStack::PopAndDestroy(); // reader
       
   207         }
       
   208 
       
   209     CHAT_DP( D_CHAT_LIT( " msgColor red=%d, green=%d, blue=%d" ),
       
   210              iMsgColor.Red(), iMsgColor.Green(), iMsgColor.Blue() );
       
   211     CHAT_DP( D_CHAT_LIT( " ownMsgColor red=%d, green=%d, blue=%d" ),
       
   212              iOwnMsgColor.Red(), iOwnMsgColor.Green(), iOwnMsgColor.Blue() );
       
   213 
       
   214     iPrimaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimaryFont,
       
   215                                                NULL );
       
   216     iSecondaryFont = AknLayoutUtils::FontFromId( EAknLogicalFontPrimarySmallFont,
       
   217                                                  NULL );
       
   218 
       
   219     CParaFormat paraFormat;
       
   220     TParaFormatMask paraFormatMask;
       
   221     paraFormat.iLanguage = CAknEnv::Static()->SettingCache().InputLanguage();
       
   222     paraFormatMask.SetAttrib( EAttParaLanguage );
       
   223 
       
   224     paraFormat.iFillColor = KRgbWhite;
       
   225     paraFormatMask.SetAttrib( EAttFillColor );
       
   226 
       
   227     paraFormat.iLeftMarginInTwips = 100;
       
   228     paraFormat.iIndentInTwips = -100;
       
   229     paraFormatMask.SetAttrib( EAttLeftMargin );
       
   230     paraFormatMask.SetAttrib( EAttIndent );
       
   231 
       
   232     // Create zoom factor object
       
   233     TZoomFactor devicemap( CCoeEnv::Static()->ScreenDevice() );
       
   234     devicemap.SetZoomFactor( TZoomFactor::EZoomOneToOne );
       
   235 
       
   236     // Get the line hight and font height
       
   237     TRect mainPaneRect;
       
   238     TAknLayoutRect lineRect;
       
   239     TAknLayoutRect layoutRect;
       
   240 
       
   241     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPaneRect );
       
   242     TAknWindowLineLayout readingPane = AknLayoutScalable_Apps::im_reading_pane( TChatListBoxLayout::EWithoutEditor );
       
   243     layoutRect.LayoutRect( mainPaneRect, readingPane );
       
   244 
       
   245     TAknWindowLineLayout lineLayout = AknLayoutScalable_Apps::list_im_single_pane( 0 );
       
   246     lineRect.LayoutRect( layoutRect.Rect(), lineLayout );
       
   247     TInt lineHeight = lineRect.Rect().Height();
       
   248 
       
   249     TAknLayoutText text;
       
   250     text.LayoutText( layoutRect.Rect(),
       
   251                      AknLayoutScalable_Apps::list_single_im_pane_t1( 0 ).LayoutLine() );
       
   252 
       
   253     // Set line space
       
   254     paraFormat.iLineSpacingControl = CParaFormat::ELineSpacingExactlyInTwips;
       
   255     paraFormatMask.SetAttrib( EAttLineSpacingControl );
       
   256 
       
   257     paraFormat.iLineSpacingInTwips = devicemap.VerticalPixelsToTwips( lineHeight );
       
   258     paraFormatMask.SetAttrib( EAttLineSpacing );
       
   259 
       
   260     TCharFormat charFormat;
       
   261     TCharFormatMask charFormatMask;
       
   262     charFormat.iFontSpec = iSecondaryFont->FontSpecInTwips();
       
   263     // Set font height
       
   264     charFormat.iFontSpec.iHeight = devicemap.VerticalPixelsToTwips( text.TextRect().Height() );
       
   265     charFormatMask.SetAttrib( EAttFontTypeface );
       
   266     charFormatMask.SetAttrib( EAttFontHeight );
       
   267 
       
   268     // Text color
       
   269     TRgb defaultSkinTextColor( KRgbBlack );
       
   270     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
       
   271                                defaultSkinTextColor,
       
   272                                KAknsIIDQsnTextColors,
       
   273                                EAknsCIQsnTextColorsCG6 );
       
   274 
       
   275     //Store the default masg color
       
   276     iDefaultMsgColor =  defaultSkinTextColor;
       
   277 
       
   278     charFormat.iFontPresentation.iTextColor = defaultSkinTextColor;
       
   279     charFormatMask.SetAttrib( EAttColor );
       
   280 
       
   281     charFormat.iFontPresentation.iPictureAlignment =
       
   282         TFontPresentation::EAlignTop;
       
   283     charFormatMask.SetAttrib( EAttFontPictureAlignment );
       
   284 
       
   285     charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
       
   286     charFormatMask.SetAttrib( EAttFontStrokeWeight );
       
   287 
       
   288 
       
   289     iParaFormatLayer = CParaFormatLayer::NewL( &paraFormat, paraFormatMask );
       
   290     iCharFormatLayer = CCharFormatLayer::NewL( charFormat, charFormatMask );
       
   291 
       
   292     iRichText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer );
       
   293     }
       
   294 
       
   295 // -----------------------------------------------------------------------------
       
   296 // CCARichTextContainer::NewL
       
   297 // Two-phased constructor.
       
   298 // -----------------------------------------------------------------------------
       
   299 //
       
   300 CCARichTextContainer* CCARichTextContainer::NewL(
       
   301     MCAAppUi& aAppUi,
       
   302     MCASettingsPC& aSettingsPC,
       
   303     MCATextView& aTextView,
       
   304     CCAMessageExtensionsHandler& aExtensionsHandler,
       
   305     CGulIcon*& aFromMe,
       
   306     CGulIcon*& aToMe,
       
   307     CGulIcon*& aUnsupported,
       
   308     CGulIcon*& aCorrupted,
       
   309     MGraphicsDeviceMap& aMap,
       
   310     TBool aScrollOver /*= ETrue*/,
       
   311     MCAMsgAddedToRichTxtCtrlObserver* aAddMsgObserver /*= NULL*/
       
   312 )
       
   313     {
       
   314     CCARichTextContainer* self = new( ELeave ) CCARichTextContainer(
       
   315         aAppUi,
       
   316         aSettingsPC,
       
   317         aTextView,
       
   318         aExtensionsHandler, aFromMe, aToMe,
       
   319         aUnsupported, aCorrupted,
       
   320         aMap,
       
   321         aScrollOver, aAddMsgObserver
       
   322     );
       
   323 
       
   324     CleanupStack::PushL( self );
       
   325     self->ConstructL();
       
   326     CleanupStack::Pop( self );
       
   327     return self;
       
   328     }
       
   329 
       
   330 
       
   331 // Destructor
       
   332 CCARichTextContainer::~CCARichTextContainer()
       
   333     {
       
   334     delete iParaFormatLayer;
       
   335     delete iCharFormatLayer;
       
   336     delete iRichText;
       
   337     iMessages.ResetAndDestroy();
       
   338     iAppUi.RemoveLayoutChangeObserver( this );
       
   339     }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // CCARichTextContainer::SelectedMessage
       
   343 // (other items were commented in a header).
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 MCAConversationMessage* CCARichTextContainer::SelectedMessage()
       
   347     {
       
   348     if ( iHighlightState != ENoHighlight )
       
   349         {
       
   350         return &( iMessages[iSelected]->Message() );
       
   351         }
       
   352     else
       
   353         {
       
   354         return NULL;
       
   355         }
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // CCARichTextContainer::SelectedItem
       
   360 // (other items were commented in a header).
       
   361 // -----------------------------------------------------------------------------
       
   362 //
       
   363 HBufC* CCARichTextContainer::SelectedItemL()
       
   364     {
       
   365     if ( iHighlightState == EItemSelected )
       
   366         {
       
   367         TCursorSelection curSel( iMessages[iSelected]->Selection() );
       
   368 
       
   369         // calculate item highlight position
       
   370         TCursorSelection itemSel(
       
   371             iMessages[iSelected]->Highlights()[iSelectedItem] );
       
   372 
       
   373         TInt messageStart( curSel.LowerPos() );
       
   374         curSel.iAnchorPos = itemSel.iAnchorPos + messageStart;
       
   375         curSel.iCursorPos = itemSel.iCursorPos + messageStart;
       
   376 
       
   377         HBufC* text = HBufC::NewMaxL( curSel.Length() );
       
   378         TPtr ptr( text->Des() );
       
   379         iRichText->Extract(	ptr, curSel.LowerPos(), curSel.Length() );
       
   380         return text;
       
   381         }
       
   382     else
       
   383         {
       
   384         return KNullDesC().AllocL();
       
   385         }
       
   386     }
       
   387 
       
   388 // -----------------------------------------------------------------------------
       
   389 // CCARichTextContainer::SelectedItemType
       
   390 // (other items were commented in a header).
       
   391 // -----------------------------------------------------------------------------
       
   392 //
       
   393 TInt CCARichTextContainer::SelectedItemType()
       
   394     {
       
   395     if ( iHighlightState == EItemSelected )
       
   396         {
       
   397         return iMessages[iSelected]->HighlightTypes()[iSelectedItem];
       
   398         }
       
   399     else
       
   400         {
       
   401         return KErrNotFound;
       
   402         }
       
   403     }
       
   404 
       
   405 // -----------------------------------------------------------------------------
       
   406 // CCARichTextContainer::RichText
       
   407 // (other items were commented in a header).
       
   408 // -----------------------------------------------------------------------------
       
   409 //
       
   410 MLayDoc* CCARichTextContainer::TextLayout()
       
   411     {
       
   412     return iRichText;
       
   413     }
       
   414 
       
   415 
       
   416 // -----------------------------------------------------------------------------
       
   417 // CCARichTextContainer::MoveHighlightL
       
   418 // (other items were commented in a header).
       
   419 // -----------------------------------------------------------------------------
       
   420 //
       
   421 TInt CCARichTextContainer::MoveHighlightL( THighlightMovement aDirection )
       
   422     {
       
   423     __CHAT_ASSERT_DEBUG( aDirection == EPrevious || aDirection == ENext );
       
   424     TBool up( aDirection == EPrevious );
       
   425     TInt messageCount( iMessages.Count() );
       
   426     if ( messageCount == 0 )
       
   427         {
       
   428         // no messages, nothing to highlight
       
   429         DisableHighlightL();
       
   430         return KErrNotFound;
       
   431         }
       
   432 
       
   433     __CHAT_ASSERT_DEBUG( iSelected >= 0 && iSelected < messageCount );
       
   434     TInt highlightCount( iMessages[iSelected]->Highlights().Count() );
       
   435 
       
   436     if ( !iItemHighlight )
       
   437         {
       
   438         // if item highlighting is not on, clear the item count
       
   439         highlightCount = 0;
       
   440         }
       
   441 
       
   442     // if message is highlighted, but it doesn't fit to screen
       
   443     // scroll it line by line
       
   444     if ( iHighlightState == EMessageTop || iHighlightState == EMessageBottom )
       
   445         {
       
   446         TCursorSelection& sel = iMessages[iSelected]->Selection();
       
   447         if ( up )
       
   448             {
       
   449             // up
       
   450             if ( !iTextView.IsVisible( sel.LowerPos() ) )
       
   451                 {
       
   452                 // we're scrolling up and top line is not shown,
       
   453                 // so scroll messages down by one line
       
   454                 iTextView.ScrollLinesL( 1 );
       
   455                 return KErrNone;
       
   456                 }
       
   457             }
       
   458         else if ( !iTextView.IsVisible( sel.HigherPos() ) )
       
   459             {
       
   460             // we're scrolling down and bottom line is not shown,
       
   461             // so scroll messages up by one line
       
   462             iTextView.ScrollLinesL( -1 );
       
   463             return KErrNone;
       
   464             }
       
   465         }
       
   466 
       
   467     // update highlight position
       
   468     switch ( iHighlightState )
       
   469         {
       
   470         case ENoHighlight:  // no highlight, select last  or first message
       
   471             {
       
   472             if ( up )
       
   473                 {
       
   474                 iSelected = messageCount - 1;
       
   475 
       
   476                 // Get highlight count of prev message
       
   477                 // if item highlighting is on
       
   478                 if ( iItemHighlight )
       
   479                     {
       
   480                     highlightCount = iMessages[iSelected]->Highlights().Count();
       
   481                     }
       
   482 
       
   483                 if ( highlightCount > 0 )
       
   484                     {
       
   485                     // highlight items inside last message (if any)
       
   486                     iHighlightState = EItemSelected;
       
   487                     iSelectedItem = highlightCount - 1;
       
   488                     }
       
   489                 else
       
   490                     {
       
   491                     // bottom of last message
       
   492                     iHighlightState = EMessageBottom;
       
   493                     }
       
   494                 }
       
   495             else
       
   496                 {
       
   497                 // top of first message
       
   498                 iHighlightState = EMessageTop;
       
   499                 iSelected = 0;
       
   500                 }
       
   501             break;
       
   502             }
       
   503         case EItemSelected: // highlighting items
       
   504             {
       
   505             if ( up )
       
   506                 {
       
   507                 // up, previous item
       
   508                 --iSelectedItem;
       
   509                 if ( iSelectedItem < 0 )
       
   510                     {
       
   511                     // end of highlights, focus message
       
   512                     iHighlightState = EMessageTop;
       
   513                     }
       
   514                 }
       
   515             else
       
   516                 {
       
   517                 // down, next item
       
   518                 ++iSelectedItem;
       
   519                 if ( iSelectedItem >= highlightCount )
       
   520                     {
       
   521                     // end of highlights
       
   522                     if ( iSelected < messageCount - 1 )
       
   523                         {
       
   524                         // focus next message
       
   525                         ++iSelected;
       
   526                         iHighlightState = EMessageTop;
       
   527                         }
       
   528                     else if ( iScrollOver )
       
   529                         {
       
   530                         // going down from last message,
       
   531                         // disable highlight so editor can take the focus
       
   532                         DisableHighlightL();
       
   533                         return KErrNone;
       
   534                         }
       
   535                     else
       
   536                         {
       
   537                         // Loop back to beginning
       
   538                         iSelected = 0;
       
   539                         iSelectedItem = 0;
       
   540                         iHighlightState = EMessageTop;
       
   541                         }
       
   542 
       
   543                     }
       
   544                 }
       
   545             break;
       
   546             }
       
   547         case EMessageTop:   // highlighting message ("top" of it)
       
   548             {
       
   549             if ( up )
       
   550                 {
       
   551                 // up, highlighting previous message
       
   552                 if ( iSelected > 0 )
       
   553                     {
       
   554                     // prev
       
   555                     --iSelected;
       
   556 
       
   557                     // get highlight count of prev message
       
   558                     // if item highlighting is on
       
   559                     if ( iItemHighlight )
       
   560                         {
       
   561                         highlightCount = iMessages[iSelected]->Highlights().Count();
       
   562                         }
       
   563 
       
   564                     if ( highlightCount > 0 )
       
   565                         {
       
   566                         // highlight items inside prev message (if any)
       
   567                         iHighlightState = EItemSelected;
       
   568                         iSelectedItem = highlightCount - 1;
       
   569                         }
       
   570                     else
       
   571                         {
       
   572                         // highlight whole prev message
       
   573                         iHighlightState = EMessageBottom;
       
   574                         }
       
   575                     }
       
   576                 else if ( iScrollOver )
       
   577                     {
       
   578                     // going up from first message,
       
   579                     // disable highlight, so editor can take the focus
       
   580                     DisableHighlightL();
       
   581                     return KErrNone;
       
   582                     }
       
   583                 else
       
   584                     {
       
   585                     // Loop to last message
       
   586                     iSelected = messageCount - 1;
       
   587                     highlightCount = 0;
       
   588 
       
   589                     // Get highlight count of last message
       
   590                     // if item highlighting is on
       
   591                     if ( iItemHighlight )
       
   592                         {
       
   593                         highlightCount =
       
   594                             iMessages[iSelected]->Highlights().Count();
       
   595                         }
       
   596 
       
   597                     if ( highlightCount > 0 )
       
   598                         {
       
   599                         // Highlight items inside last message (if any)
       
   600                         iHighlightState = EItemSelected;
       
   601                         iSelectedItem = highlightCount - 1;
       
   602                         }
       
   603                     else
       
   604                         {
       
   605                         // Highlight whole last message
       
   606                         iHighlightState = EMessageBottom;
       
   607                         }
       
   608                     }
       
   609                 }
       
   610             else
       
   611                 {
       
   612                 // down, highlight items inside this message (if any)
       
   613                 if ( highlightCount > 0 )
       
   614                     {
       
   615                     iSelectedItem = 0;
       
   616                     iHighlightState = EItemSelected;
       
   617                     }
       
   618                 else if ( iSelected < messageCount - 1 )
       
   619                     {
       
   620                     // next
       
   621                     ++iSelected;
       
   622                     iHighlightState = EMessageTop;
       
   623                     }
       
   624                 else if ( iScrollOver )
       
   625                     {
       
   626                     // going down from last message,
       
   627                     // disable highlight, so editor can take the focus
       
   628                     DisableHighlightL();
       
   629                     return KErrNone;
       
   630                     }
       
   631                 else
       
   632                     {
       
   633                     // Loop back to beginning
       
   634                     iSelected = 0;
       
   635                     iSelectedItem = 0;
       
   636                     iHighlightState = EMessageTop;
       
   637                     }
       
   638                 }
       
   639             break;
       
   640             }
       
   641         case EMessageBottom:   // highlighting message ("bottom" of it)
       
   642             {
       
   643             if ( up )
       
   644                 {
       
   645                 // up, highlight items inside this message (if any)
       
   646                 if ( highlightCount > 0 )
       
   647                     {
       
   648                     iSelectedItem = highlightCount - 1;
       
   649                     iHighlightState = EItemSelected;
       
   650                     }
       
   651                 else if ( iSelected > 0 )
       
   652                     {
       
   653                     // prev
       
   654                     --iSelected;
       
   655 
       
   656                     // get highlight count of prev message
       
   657                     // if item highlighting is on
       
   658                     if ( iItemHighlight )
       
   659                         {
       
   660                         highlightCount = iMessages[iSelected]->Highlights().Count();
       
   661                         }
       
   662 
       
   663                     if ( highlightCount > 0 )
       
   664                         {
       
   665                         // highlight items inside prev message (if any)
       
   666                         iHighlightState = EItemSelected;
       
   667                         iSelectedItem = highlightCount - 1;
       
   668                         }
       
   669                     else
       
   670                         {
       
   671                         iHighlightState = EMessageBottom;
       
   672                         }
       
   673                     }
       
   674                 else if ( iScrollOver )
       
   675                     {
       
   676                     // going up from first message,
       
   677                     // disable highlight, so editor can take the focus
       
   678                     DisableHighlightL();
       
   679                     return KErrNone;
       
   680                     }
       
   681                 else
       
   682                     {
       
   683                     // Loop to last message
       
   684                     iSelected = messageCount - 1;
       
   685                     highlightCount = 0;
       
   686 
       
   687                     // Get highlight count of last message
       
   688                     // if item highlighting is on
       
   689                     if ( iItemHighlight )
       
   690                         {
       
   691                         highlightCount =
       
   692                             iMessages[iSelected]->Highlights().Count();
       
   693                         }
       
   694 
       
   695                     if ( highlightCount > 0 )
       
   696                         {
       
   697                         // Highlight items inside last message (if any)
       
   698                         iHighlightState = EItemSelected;
       
   699                         iSelectedItem = highlightCount - 1;
       
   700                         }
       
   701                     else
       
   702                         {
       
   703                         // Highlight whole last message
       
   704                         iHighlightState = EMessageBottom;
       
   705                         }
       
   706                     }
       
   707                 }
       
   708             else
       
   709                 {
       
   710                 // down, highlighting next message
       
   711                 if ( iSelected < messageCount - 1 )
       
   712                     {
       
   713                     // next
       
   714                     ++iSelected;
       
   715                     iHighlightState = EMessageTop;
       
   716                     }
       
   717                 else if ( iScrollOver )
       
   718                     {
       
   719                     // going down from last message,
       
   720                     // disable highlight, so editor can take the focus
       
   721                     DisableHighlightL();
       
   722                     return KErrNone;
       
   723                     }
       
   724                 else
       
   725                     {
       
   726                     // Loop back to beginning
       
   727                     iSelected = 0;
       
   728                     iSelectedItem = 0;
       
   729                     iHighlightState = EMessageTop;
       
   730                     }
       
   731                 }
       
   732             break;
       
   733             }
       
   734         default:
       
   735             {
       
   736             __CHAT_ASSERT_DEBUG( EFalse );
       
   737             break;
       
   738             }
       
   739         }
       
   740 
       
   741     // get the selection
       
   742     TCursorSelection curSel( CurrentSelection() );
       
   743 
       
   744     // remove colors from old highlight
       
   745     TInt textLen( iRichText->DocumentLength() );
       
   746     if ( iPrevious.iAnchorPos < textLen &&
       
   747          iPrevious.iCursorPos <= textLen )
       
   748         {
       
   749         BackColorL( iPrevious, KRgbWhite );
       
   750         TextBackColorL( iPrevious, KRgbWhite );
       
   751         }
       
   752 
       
   753     // and set new one
       
   754     if ( iHighlightState == EItemSelected )
       
   755         {
       
   756         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   757         TRgb color;
       
   758 
       
   759         TInt error = AknsUtils::GetCachedColor( skin,
       
   760                                                 color,
       
   761                                                 KAknsIIDQsnHighlightColors,
       
   762                                                 EAknsCIQsnHighlightColorsCG2 );
       
   763 
       
   764         if ( !error )
       
   765             {
       
   766             // No error, use skinned background color
       
   767             TextBackColorL( curSel, color );
       
   768             }
       
   769         else
       
   770             {
       
   771             TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
   772             }
       
   773         }
       
   774     else
       
   775         {
       
   776         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   777         TRgb color;
       
   778 
       
   779         TInt error = AknsUtils::GetCachedColor( skin,
       
   780                                                 color,
       
   781                                                 KAknsIIDQsnHighlightColors,
       
   782                                                 EAknsCIQsnHighlightColorsCG2 );
       
   783 
       
   784         if ( !error )
       
   785             {
       
   786             // No error, use skinned background color
       
   787             BackColorL( curSel, color );
       
   788             }
       
   789         else
       
   790             {
       
   791             BackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
   792             }
       
   793         }
       
   794 
       
   795     // handle changed format
       
   796     TCursorSelection changed( Union( iPrevious, curSel ) );
       
   797 
       
   798     iTextView.HandleFormatChangedL( changed );
       
   799 
       
   800     iTextView.ScrollVisibleL( curSel, ETrue );
       
   801 
       
   802     iPrevious = curSel;
       
   803     return KErrNone;
       
   804     }
       
   805 
       
   806 
       
   807 // -----------------------------------------------------------------------------
       
   808 // CCARichTextContainer::DisableHighlightL
       
   809 // (other items were commented in a header).
       
   810 // -----------------------------------------------------------------------------
       
   811 //
       
   812 void CCARichTextContainer::DisableHighlightL()
       
   813     {
       
   814     iHighlightState = ENoHighlight;
       
   815 
       
   816     TCursorSelection sel( 0, 0 );
       
   817     TInt count( iMessages.Count() );
       
   818     if ( count > 0 )
       
   819         {
       
   820         sel = iMessages[count-1]->Selection();
       
   821         }
       
   822 
       
   823     // remove colors from old highlight (if any)
       
   824     TInt textLen( iRichText->DocumentLength() );
       
   825     if ( iPrevious.iAnchorPos < textLen &&
       
   826          iPrevious.iCursorPos <= textLen )
       
   827         {
       
   828         BackColorL( iPrevious, KRgbWhite );
       
   829         TextBackColorL( iPrevious, KRgbWhite );
       
   830         iTextView.HandleFormatChangedL( iPrevious );
       
   831         }
       
   832 
       
   833     // set focus to last message
       
   834     iTextView.ScrollVisibleL( sel, EFalse );
       
   835     }
       
   836 
       
   837 
       
   838 // -----------------------------------------------------------------------------
       
   839 // CCARichTextContainer::SetItemHighlight
       
   840 // (other items were commented in a header).
       
   841 // -----------------------------------------------------------------------------
       
   842 //
       
   843 void CCARichTextContainer::SetItemHighlight( TBool aItemHighlight )
       
   844     {
       
   845     iItemHighlight = aItemHighlight;
       
   846     }
       
   847 
       
   848 // -----------------------------------------------------------------------------
       
   849 // CCARichTextContainer::Highlighted
       
   850 // (other items were commented in a header).
       
   851 // -----------------------------------------------------------------------------
       
   852 //
       
   853 TBool CCARichTextContainer::Highlighted()
       
   854     {
       
   855     return iHighlightState != ENoHighlight;
       
   856     }
       
   857 
       
   858 // -----------------------------------------------------------------------------
       
   859 // CCARichTextContainer::Highlighted
       
   860 // (other items were commented in a header).
       
   861 // -----------------------------------------------------------------------------
       
   862 //
       
   863 TInt CCARichTextContainer::HighlightItemAtPosL( TInt aPos )
       
   864     {
       
   865     TInt messageCount = iMessages.Count();
       
   866     if ( messageCount == 0 )
       
   867         {
       
   868         // no messages
       
   869         return KErrNotFound;
       
   870         }
       
   871 
       
   872     // Store old values
       
   873     TInt oldSelectedMessage = iSelected;
       
   874     TInt oldSelectedItem = iSelectedItem;
       
   875     THighlightState oldHighlight = iHighlightState;
       
   876 
       
   877     // Find message in position aPos
       
   878     TBool found = EFalse;
       
   879     for ( TInt i = 0; i < messageCount; ++i )
       
   880         {
       
   881         TCursorSelection sel = iMessages[ i ]->WholeSelection();
       
   882         if ( aPos >= sel.LowerPos() &&
       
   883              aPos <= sel.HigherPos() )
       
   884             {
       
   885             // Found the message
       
   886             iSelected = i;
       
   887             iHighlightState = EMessageTop;
       
   888             found = ETrue;
       
   889             // stop searching
       
   890             break;
       
   891             }
       
   892         }
       
   893 
       
   894     if ( !found )
       
   895         {
       
   896         // not found
       
   897         return KErrNotFound;
       
   898         }
       
   899 
       
   900     // Check if there are items inside the message that can be highlighted.
       
   901     if ( iItemHighlight )
       
   902         {
       
   903         TInt hlCount = iMessages[ iSelected ]->Highlights().Count();
       
   904         TInt relativePos =
       
   905             aPos - iMessages[ iSelected ]->WholeSelection().LowerPos();
       
   906 
       
   907         for ( TInt i = 0; i < hlCount; ++i )
       
   908             {
       
   909             TCursorSelection sel = iMessages[ iSelected ]->Highlights()[ i ];
       
   910 
       
   911             // Highlight's selection is relative to message
       
   912             if ( relativePos >= sel.LowerPos() &&
       
   913                  relativePos <= sel.HigherPos() )
       
   914                 {
       
   915                 // Found an item
       
   916                 iHighlightState = EItemSelected;
       
   917                 iSelectedItem = i;
       
   918                 // stop searching
       
   919                 break;
       
   920                 }
       
   921             }
       
   922         }
       
   923 
       
   924     // Update UI only if selection has changed
       
   925     if ( iSelected != oldSelectedMessage ||
       
   926          iSelectedItem != oldSelectedItem ||
       
   927          oldHighlight != iHighlightState )
       
   928         {
       
   929         UpdateSelectionL();
       
   930         return KErrNone;
       
   931         }
       
   932     // Already highlighted
       
   933     return KErrAlreadyExists;
       
   934     }
       
   935 
       
   936 // -----------------------------------------------------------------------------
       
   937 // CCARichTextContainer::UpdateSelection
       
   938 // (other items were commented in a header).
       
   939 // -----------------------------------------------------------------------------
       
   940 //
       
   941 void CCARichTextContainer::UpdateSelectionL()
       
   942     {
       
   943     // get the selection
       
   944     TCursorSelection curSel( CurrentSelection() );
       
   945 
       
   946     // remove colors from old highlight
       
   947     TInt textLen( iRichText->DocumentLength() );
       
   948     if ( iPrevious.iAnchorPos < textLen &&
       
   949          iPrevious.iCursorPos <= textLen )
       
   950         {
       
   951         BackColorL( iPrevious, KRgbWhite );
       
   952         TextBackColorL( iPrevious, KRgbWhite );
       
   953         }
       
   954 
       
   955     // and set new one
       
   956     if ( iHighlightState == EItemSelected )
       
   957         {
       
   958         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   959         TRgb color;
       
   960 
       
   961         TInt error = AknsUtils::GetCachedColor( skin,
       
   962                                                 color,
       
   963                                                 KAknsIIDQsnHighlightColors,
       
   964                                                 EAknsCIQsnHighlightColorsCG2 );
       
   965 
       
   966         if ( !error )
       
   967             {
       
   968             // No error, use skinned background color
       
   969             TextBackColorL( curSel, color );
       
   970             }
       
   971         else
       
   972             {
       
   973             TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
   974             }
       
   975         }
       
   976     else
       
   977         {
       
   978         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   979         TRgb color;
       
   980 
       
   981         TInt error = AknsUtils::GetCachedColor( skin,
       
   982                                                 color,
       
   983                                                 KAknsIIDQsnHighlightColors,
       
   984                                                 EAknsCIQsnHighlightColorsCG2 );
       
   985 
       
   986         if ( !error )
       
   987             {
       
   988             // No error, use skinned background color
       
   989             BackColorL( curSel, color );
       
   990             }
       
   991         else
       
   992             {
       
   993             BackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
   994             }
       
   995         }
       
   996 
       
   997     // handle changed format
       
   998     TCursorSelection changed( Union( iPrevious, curSel ) );
       
   999     iTextView.HandleFormatChangedL( changed );
       
  1000     iTextView.ScrollVisibleL( curSel, ETrue );
       
  1001 
       
  1002     iPrevious = curSel;
       
  1003     }
       
  1004 
       
  1005 // -----------------------------------------------------------------------------
       
  1006 // CCARichTextContainer::InsertUserIdentityL
       
  1007 // (other items were commented in a header).
       
  1008 // -----------------------------------------------------------------------------
       
  1009 //
       
  1010 TCursorSelection CCARichTextContainer::InsertUserIdentityL(
       
  1011     CCAMessageWrapper& aMessageWrapper )
       
  1012     {
       
  1013     TInt stampStart = 0;
       
  1014     TCursorSelection timeSel( stampStart, stampStart );
       
  1015     TInt stampEnd = stampStart;
       
  1016     MCAConversationMessage& message = aMessageWrapper.Message();
       
  1017     TPtrC sender;
       
  1018     TPtrC recipient;
       
  1019     MCAStoredContacts* contacts = CCAStorageManagerFactory::ContactListInterfaceL();
       
  1020     if ( message.MessagerType() == TEnumsPC::EMessageSent
       
  1021          && message.MessageType() != TEnumsPC::EMessageSystem )
       
  1022         {
       
  1023         sender.Set( contacts->OwnStatus().Identification() );
       
  1024         }
       
  1025     else
       
  1026         {
       
  1027         sender.Set( contacts->Identification( message.Sender() ) );
       
  1028         }
       
  1029     recipient.Set( contacts->Identification( message.Recipient() ) );
       
  1030 
       
  1031     if ( message.MessagerType() == TEnumsPC::EMessageSent &&
       
  1032          message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  1033          iOwnMsgIcon )
       
  1034         {
       
  1035         if ( sender.Length() >= KMaxLength )
       
  1036             {
       
  1037             TPtrC aTempPtr;
       
  1038             aTempPtr.Set( sender.Left( 8 ) );
       
  1039             TBuf<11> aTruncateSender( aTempPtr );
       
  1040             aTruncateSender.Append( _L( ".. " ) );
       
  1041             iRichText->InsertL( stampStart, aTruncateSender );
       
  1042             stampEnd = stampStart + aTruncateSender.Length();
       
  1043             }
       
  1044         else
       
  1045             {
       
  1046             TBuf<10> aTruncateSender( sender );
       
  1047             aTruncateSender.Append( KSpace );
       
  1048             iRichText->InsertL( stampStart, aTruncateSender );
       
  1049             stampEnd = stampStart + aTruncateSender.Length();
       
  1050             }
       
  1051         }
       
  1052     else if ( message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  1053               message.MessagerType() == TEnumsPC::EMessageReceived &&
       
  1054               iMsgIcon )
       
  1055         {
       
  1056         if ( recipient.Length() >= KMaxLength )
       
  1057             {
       
  1058             TPtrC aTempPtr;
       
  1059             aTempPtr.Set( recipient.Left( 8 ) );
       
  1060             TBuf<11> aTruncateRecipient( aTempPtr );
       
  1061             aTruncateRecipient.Append( _L( ".. " ) );
       
  1062             iRichText->InsertL( stampStart, aTruncateRecipient );
       
  1063             stampEnd = stampStart + aTruncateRecipient.Length();
       
  1064             }
       
  1065         else
       
  1066             {
       
  1067             TBuf<10> aTruncateRecipient( recipient );
       
  1068             aTruncateRecipient.Append( KSpace );
       
  1069             //CEikonEnv::Static()->InfoMsg(aTruncateRecipient);
       
  1070             iRichText->InsertL( stampStart, aTruncateRecipient );
       
  1071             stampEnd = stampStart + aTruncateRecipient.Length();
       
  1072             }
       
  1073         }
       
  1074     timeSel.SetSelection( stampStart, stampEnd - 1 );
       
  1075 
       
  1076     // bold the User Identity
       
  1077     if ( timeSel.Length() > 0 )
       
  1078         {
       
  1079         BoldL( timeSel );
       
  1080         }
       
  1081 
       
  1082     return timeSel;
       
  1083     }
       
  1084 
       
  1085 // -----------------------------------------------------------------------------
       
  1086 // CCARichTextContainer::InsertTimeStampL
       
  1087 // (other items were commented in a header).
       
  1088 // -----------------------------------------------------------------------------
       
  1089 //
       
  1090 TCursorSelection CCARichTextContainer::InsertTimeStampL(
       
  1091     CCAMessageWrapper& aMessageWrapper )
       
  1092     {
       
  1093     TInt start = 0;
       
  1094     TCursorSelection timeSel( start, start );
       
  1095 
       
  1096     if ( !iSettings.GetBoolValuePC( TEnumsPC::EShowTimeStamps, NULL ) ||
       
  1097          aMessageWrapper.Message().SystemMessageType() ==
       
  1098          TEnumsPC::ESystemMessageDateChange )
       
  1099         {
       
  1100         // 1. Setting for time stamp is OFF
       
  1101         // 2. Special case: date change don't have time stamp.
       
  1102         return timeSel;
       
  1103         }
       
  1104 
       
  1105     // format time
       
  1106     HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() );
       
  1107     TPtr timePtr( timeStamp->Des() );
       
  1108 
       
  1109     HBufC* timeStampFormat = NULL;
       
  1110     timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO );
       
  1111 
       
  1112     TTime time = aMessageWrapper.Message().TimeStamp();
       
  1113     TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) );
       
  1114     if ( err == KErrOverflow )
       
  1115         {
       
  1116         // Reserved text space was not enough.
       
  1117         // Adjust the KTimeStampMaxLength
       
  1118         __CHAT_ASSERT_DEBUG( EFalse );
       
  1119 
       
  1120         // in release builds return without timestamp
       
  1121         CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
       
  1122         return timeSel;
       
  1123         }
       
  1124 
       
  1125     // Convert numbers to local language
       
  1126     AknTextUtils::LanguageSpecificNumberConversion( timePtr );
       
  1127 
       
  1128     // Set Alignment of Pm/Am from local setting
       
  1129     // This keeps the am/pm text close to the time.
       
  1130     timePtr.Append( AknLayoutUtils::LayoutMirrored() ?
       
  1131                     KUnicodeRLM : KUnicodeLRM );
       
  1132 
       
  1133     //	IM client UI customization, phase 2
       
  1134     //  Based on Variation flag, changes Time Stamp format in conversation view.
       
  1135     //  where Time Stamp should appear in brackets.
       
  1136 
       
  1137     // read variation flag values
       
  1138     TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1139     // and check dynamic features
       
  1140     if ( requireUserIdentity )
       
  1141         {
       
  1142         timePtr.Insert( 0, _L( "(" ) );
       
  1143         timePtr.Append( _L( ")" ) );
       
  1144         timePtr.Append( KSpace );
       
  1145         }
       
  1146     else
       
  1147         {
       
  1148         timePtr.Append( KSpace );
       
  1149         }
       
  1150 
       
  1151     iRichText->InsertL( start, timePtr );
       
  1152 
       
  1153     CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
       
  1154     timeSel.SetSelection( start, timePtr.Length() - 1 );
       
  1155 
       
  1156     // bold the time
       
  1157     if ( timeSel.Length() > 0 )
       
  1158         {
       
  1159         BoldL( timeSel );
       
  1160         }
       
  1161 
       
  1162     return timeSel;
       
  1163     }
       
  1164 
       
  1165 // -----------------------------------------------------------------------------
       
  1166 // CCARichTextContainer::InsertContentL
       
  1167 // (other items were commented in a header).
       
  1168 // -----------------------------------------------------------------------------
       
  1169 //
       
  1170 TInt CCARichTextContainer::InsertContentL( CCAMessageWrapper& aMessageWrapper )
       
  1171     {
       
  1172     MCAConversationMessage& message = aMessageWrapper.Message();
       
  1173 
       
  1174     TEnumsPC::TContentType type( message.ContentType() );
       
  1175     switch ( type )
       
  1176         {
       
  1177         case TEnumsPC::EContentText:
       
  1178             {
       
  1179             TInt oldLen = iRichText->DocumentLength();
       
  1180 
       
  1181             // Insert text
       
  1182             TPtrC msg( message.Text() );
       
  1183 
       
  1184             HBufC* tempMsg = NULL;
       
  1185 
       
  1186             TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter );
       
  1187             // Replace all paragraph delimiters with line breaks
       
  1188             // to keep alingment consistent
       
  1189             if ( paraBreak != KErrNotFound )
       
  1190                 {
       
  1191                 tempMsg = msg.AllocLC();
       
  1192                 TPtr ptr( tempMsg->Des() );
       
  1193                 ptr.Zero();
       
  1194 
       
  1195                 ReplaceParaDelimsWithLineBreaks( msg, ptr );
       
  1196                 msg.Set( ptr );
       
  1197                 }
       
  1198 
       
  1199             HBufC* numberConv = NULL;
       
  1200 
       
  1201             // Convert numerals to local language
       
  1202             // 1) date item
       
  1203             if ( aMessageWrapper.Message().SystemMessageType() ==
       
  1204                  TEnumsPC::ESystemMessageDateChange )
       
  1205                 {
       
  1206                 // Don't touch the original message
       
  1207                 numberConv = msg.AllocLC();
       
  1208                 TPtr ptr( numberConv->Des() );
       
  1209                 AknTextUtils::LanguageSpecificNumberConversion( ptr );
       
  1210                 msg.Set( ptr );
       
  1211                 }
       
  1212 
       
  1213             iRichText->InsertL( 0, msg );
       
  1214 
       
  1215             TInt textEnd = msg.Length();
       
  1216 
       
  1217             // Check for extensions (smileys)
       
  1218             TCursorSelection selection( 0, textEnd );
       
  1219             TInt bfrConv = iRichText->DocumentLength();
       
  1220             iExtensionsHandler.ConvertSelectionToExtensionL( *iRichText,
       
  1221                                                              selection );
       
  1222 
       
  1223             // Move textEnd index if extensions were found
       
  1224             textEnd -= ( bfrConv - iRichText->DocumentLength() );
       
  1225 
       
  1226             // Add nbs to preserve formatting
       
  1227             iRichText->InsertL( textEnd,
       
  1228                                 CEditableText::EZeroWidthNoBreakSpace );
       
  1229 
       
  1230             // If this is system message, it should be bold
       
  1231             if ( message.MessageType() == TEnumsPC::EMessageSystem )
       
  1232                 {
       
  1233                 TCursorSelection sel( 0, textEnd );
       
  1234                 BoldL( sel );
       
  1235                 // System messages need different kind of alignment
       
  1236                 CParaFormat paraFormat;
       
  1237                 TParaFormatMask paraFormatMask;
       
  1238                 paraFormat.iLeftMarginInTwips = 0;
       
  1239                 paraFormatMask.SetAttrib( EAttLeftMargin );
       
  1240                 iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask,
       
  1241                                              0, textEnd + 1 );
       
  1242                 }
       
  1243             else
       
  1244                 {
       
  1245                 // Apply alignment for "normal" messages
       
  1246                 CParaFormat paraFormat;
       
  1247                 TParaFormatMask paraFormatMask;
       
  1248                 paraFormat.iLeftMarginInTwips = 100;
       
  1249                 paraFormatMask.SetAttrib( EAttLeftMargin );
       
  1250                 iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask,
       
  1251                                              0, textEnd + 1 );
       
  1252 
       
  1253                 // Remove bolding from message content
       
  1254                 TCharFormat charFormat;
       
  1255                 TCharFormatMask charFormatMask;
       
  1256                 charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
       
  1257                 charFormatMask.SetAttrib( EAttFontStrokeWeight );
       
  1258                 iRichText->ApplyCharFormatL( charFormat, charFormatMask,
       
  1259                                              0, textEnd + 1 );
       
  1260                 }
       
  1261 
       
  1262             // Cleanup
       
  1263             if ( numberConv )
       
  1264                 {
       
  1265                 CleanupStack::PopAndDestroy( numberConv );
       
  1266                 }
       
  1267             if ( tempMsg )
       
  1268                 {
       
  1269                 CleanupStack::PopAndDestroy( tempMsg );
       
  1270                 }
       
  1271 
       
  1272             return iRichText->DocumentLength() - oldLen;
       
  1273             }
       
  1274         case TEnumsPC::EContentPicture: // Flowthrough
       
  1275         case TEnumsPC::EContentOther:
       
  1276             {
       
  1277             TInt oldLen = iRichText->DocumentLength();
       
  1278             // insert thumbnail (if it's ready)
       
  1279             AddThumbL( 0, aMessageWrapper );
       
  1280             return iRichText->DocumentLength() - oldLen;
       
  1281             }
       
  1282         case TEnumsPC::EContentInvalid:
       
  1283             {
       
  1284             break;
       
  1285             }
       
  1286         default:
       
  1287             {
       
  1288             // Unsupported type
       
  1289             __CHAT_ASSERT_DEBUG( false );
       
  1290             break;
       
  1291             }
       
  1292         }
       
  1293 
       
  1294     return 0;
       
  1295     }
       
  1296 
       
  1297 // -----------------------------------------------------------------------------
       
  1298 // CCARichTextContainer::InsertNickL
       
  1299 // (other items were commented in a header).
       
  1300 // -----------------------------------------------------------------------------
       
  1301 //
       
  1302 TCursorSelection CCARichTextContainer::InsertNickL(
       
  1303     CCAMessageWrapper& aMessageWrapper )
       
  1304     {
       
  1305     // insert nick
       
  1306     MCAConversationMessage& message = aMessageWrapper.Message();
       
  1307 
       
  1308     if ( message.FailedMessage() )
       
  1309         {
       
  1310         return 	TCursorSelection( 0, 0 );
       
  1311         }
       
  1312 
       
  1313     TPtrC sender;
       
  1314     TPtrC recipient;
       
  1315     if ( message.MessageType() == TEnumsPC::EMessageGroup ||
       
  1316          message.MessageType() == TEnumsPC::EMessageWhisper )
       
  1317         {
       
  1318         sender.Set( message.Sender() );
       
  1319 
       
  1320         if ( message.MessagerType() == TEnumsPC::EMessageSent )
       
  1321             {
       
  1322             recipient.Set( message.Recipient() );
       
  1323             }
       
  1324         else
       
  1325             {
       
  1326             CCAAppUi* appUI = static_cast <CCAAppUi*> ( CCoeEnv::Static()->AppUi() );
       
  1327             recipient.Set( appUI->GetProcessManager().GetGroupInterface()->ScreenName() );
       
  1328             }
       
  1329 
       
  1330         }
       
  1331     else
       
  1332         {
       
  1333         MCAStoredContacts* contacts =
       
  1334             CCAStorageManagerFactory::ContactListInterfaceL();
       
  1335         if ( message.MessagerType() == TEnumsPC::EMessageSent
       
  1336              && message.MessageType() != TEnumsPC::EMessageSystem )
       
  1337             {
       
  1338             sender.Set( contacts->OwnStatus().Identification() );
       
  1339             }
       
  1340         else
       
  1341             {
       
  1342             sender.Set( contacts->Identification( message.Sender() ) );
       
  1343             }
       
  1344 
       
  1345         recipient.Set( contacts->Identification( message.Recipient() ) );
       
  1346         }
       
  1347     TCursorSelection nickSel( 0, 0 );
       
  1348 
       
  1349     if ( message.MessagerType() == TEnumsPC::EMessageSent &&
       
  1350          message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  1351          iOwnMsgIcon )
       
  1352         {
       
  1353         // this is sent (or failed) p2p message,
       
  1354         // insert "from me" icon and separator
       
  1355         // (if icons are in use)
       
  1356         //	IM client UI customization, phase 2
       
  1357         //  Based on Variation flag, changes Nick format in conversation view
       
  1358         //  removes arrow sign and append only a seperator.
       
  1359 
       
  1360         // read variation flag values
       
  1361         TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1362         // and check dynamic features
       
  1363         if ( !requireUserIdentity )
       
  1364             {
       
  1365             CCAPicture* pic = new( ELeave ) CCAPicture( iMap, iFromMe );
       
  1366             TPictureHeader header;
       
  1367             header.iPicture = TSwizzle<CPicture>( pic );
       
  1368             iRichText->CancelInsertCharFormat();    // to prevent ETEXT 31 panic
       
  1369             iRichText->InsertL( 0, header ); // takes ownership
       
  1370             iRichText->InsertL( 1, KSeparator );
       
  1371             nickSel.iAnchorPos = 1;
       
  1372             }
       
  1373         else
       
  1374             {
       
  1375             iRichText->InsertL( 0, KSeparator );
       
  1376             nickSel.iAnchorPos = 0;
       
  1377             }
       
  1378         }
       
  1379     else
       
  1380         {
       
  1381         TInt nickStart = 0;
       
  1382         TInt nickEnd = nickStart;
       
  1383 
       
  1384         if ( message.MessageType() == TEnumsPC::EMessageWhisper )
       
  1385             {
       
  1386             // this is send/received whisper message (to us),
       
  1387             // insert sender, "to me" icon and separator
       
  1388             iRichText->InsertL( nickStart, sender );
       
  1389             nickEnd = sender.Length();
       
  1390 
       
  1391             CCAPicture* pic = NULL;
       
  1392             if ( message.MessagerType() == TEnumsPC::EMessageSent )
       
  1393                 {
       
  1394                 pic = new( ELeave )CCAPicture( iMap,
       
  1395                                                iFromMe );
       
  1396                 }
       
  1397             else
       
  1398                 {
       
  1399                 pic = new( ELeave )CCAPicture( iMap,
       
  1400                                                iToMe );
       
  1401                 }
       
  1402             TPictureHeader header;
       
  1403             header.iPicture = TSwizzle<CPicture>( pic );
       
  1404             iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic
       
  1405             iRichText->InsertL( nickEnd, header ); // takes ownership
       
  1406 
       
  1407             iRichText->InsertL( nickEnd + 1, recipient );
       
  1408             nickEnd = nickEnd + 1 + recipient.Length();
       
  1409 
       
  1410             iRichText->InsertL( nickEnd, KSeparator );
       
  1411             }
       
  1412         else if ( message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  1413                   message.MessagerType() == TEnumsPC::EMessageReceived &&
       
  1414                   iMsgIcon )
       
  1415             {
       
  1416             // received p2p message and we want to display icon
       
  1417             // insert "to me" icon and separator
       
  1418             //	IM client UI customization, phase 2
       
  1419             //  Based on Variation flag, changes Nick format in conversation view
       
  1420             //  removes arrow sign and append only a seperator.
       
  1421 
       
  1422             // read variation flag values
       
  1423             TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1424             // and check dynamic features
       
  1425             if ( !requireUserIdentity )
       
  1426                 {
       
  1427                 CCAPicture* pic = new( ELeave ) CCAPicture( iMap,
       
  1428                                                             iToMe );
       
  1429                 TPictureHeader header;
       
  1430                 header.iPicture = TSwizzle<CPicture>( pic );
       
  1431                 iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic
       
  1432                 iRichText->InsertL( nickStart, header ); // takes ownership
       
  1433                 iRichText->InsertL( nickStart + 1, KSeparator );
       
  1434                 nickEnd = 1;
       
  1435                 }
       
  1436             else
       
  1437                 {
       
  1438                 iRichText->InsertL( nickStart, KSeparator );
       
  1439                 nickEnd = 0;
       
  1440                 }
       
  1441             }
       
  1442         else if ( sender.Length() > 0 )
       
  1443             {
       
  1444             // this is normal group message (or p2p message if icons are not used),
       
  1445             // insert sender and separator
       
  1446             iRichText->InsertL( nickStart, sender );
       
  1447             nickEnd = nickStart + sender.Length();
       
  1448             iRichText->InsertL( nickEnd, KSeparator );
       
  1449             }
       
  1450 
       
  1451         // formatting (bold nickname)
       
  1452         nickSel.SetSelection( nickStart, nickEnd );
       
  1453         if ( nickSel.Length() > 0 )
       
  1454             {
       
  1455             BoldL( nickSel );
       
  1456             }
       
  1457         }
       
  1458     return nickSel;
       
  1459     }
       
  1460 
       
  1461 // -----------------------------------------------------------------------------
       
  1462 // CCARichTextContainer::LayoutChangedL
       
  1463 // (other items were commented in a header).
       
  1464 // -----------------------------------------------------------------------------
       
  1465 //
       
  1466 void CCARichTextContainer::LayoutChangedL( TInt /*aType*/ )
       
  1467     {
       
  1468     UpdateSkinnedTextColourL();
       
  1469     if ( Highlighted() )
       
  1470         {
       
  1471         ChangeHighlightColorL();
       
  1472         }
       
  1473     }
       
  1474 
       
  1475 TInt CCARichTextContainer::IntResourceValueL( TInt aResourceId )
       
  1476     {
       
  1477     // Show user Identity, if variated so
       
  1478     TResourceReader reader;
       
  1479     TInt value( KErrNone );
       
  1480     CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
       
  1481     value = ResourceUtils::ReadTInt32L( reader );
       
  1482     CleanupStack::PopAndDestroy(); // reader
       
  1483 
       
  1484     return value;
       
  1485     }
       
  1486 
       
  1487 // -----------------------------------------------------------------------------
       
  1488 // CCARichTextContainer::AddMessageL
       
  1489 // (other items were commented in a header).
       
  1490 // -----------------------------------------------------------------------------
       
  1491 //
       
  1492 void CCARichTextContainer::AddMessageL( MCAConversationMessage& aMessage )
       
  1493     {
       
  1494     if ( !iShowTimeStamps &&
       
  1495          aMessage.SystemMessageType() == TEnumsPC::ESystemMessageDateChange )
       
  1496         {
       
  1497         // if timestamp setting is OFF we don't show day change items
       
  1498         return;
       
  1499         }
       
  1500 
       
  1501     TInt oldCount = iMessages.Count();
       
  1502 
       
  1503     // create wrapper
       
  1504     CCAMessageWrapper* wrapper = CCAMessageWrapper::NewL( aMessage, *this );
       
  1505 
       
  1506     CleanupStack::PushL( wrapper );
       
  1507     iMessages.AppendL( wrapper );   // takes the ownership
       
  1508     CleanupStack::Pop( wrapper );
       
  1509 
       
  1510     if ( aMessage.ContentType() == TEnumsPC::EContentPicture )
       
  1511         {
       
  1512         if ( IMUtils::ContentProtectedL( aMessage.ContentData() ) )
       
  1513             {
       
  1514             aMessage.SetProcessState( TEnumsPC::EContentNotSupported );
       
  1515             }
       
  1516         else
       
  1517             {
       
  1518             // add thumbnail processor for message
       
  1519             aMessage.AddContentProcessorL( iThumbSize );
       
  1520 
       
  1521             // If this is recorded chat container (iScrollOver == EFalse)
       
  1522             // and added message was first move highlight
       
  1523             if ( oldCount == 0 && !iScrollOver )
       
  1524                 {
       
  1525                 iMsgAddedToContentProcessor = 1;
       
  1526                 }
       
  1527             }
       
  1528         }
       
  1529 
       
  1530     // start new paragraph
       
  1531     TInt lineStart = iRichText->DocumentLength();
       
  1532     if ( lineStart != 0 )
       
  1533         {
       
  1534         iRichText->InsertL( lineStart, CEditableText::EParagraphDelimiter );
       
  1535         }
       
  1536 
       
  1537     // Set Alignment from local layout
       
  1538     iRichText->InsertL( iRichText->DocumentLength(),
       
  1539                         AknLayoutUtils::LayoutMirrored() ? KUnicodeRLM : KUnicodeLRM );
       
  1540 
       
  1541     // add message to rich text
       
  1542     TInt startPos( iRichText->DocumentLength() );
       
  1543 
       
  1544     //	IM client UI customization, phase 2
       
  1545     //  Based on Variation flag, enables User Identity with Time Stamp
       
  1546     //  in chat conversation view.
       
  1547 
       
  1548     // read variation flag values
       
  1549     TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1550     // and check dynamic features
       
  1551     if ( requireUserIdentity )
       
  1552         {
       
  1553         TCursorSelection userSel = AddUserIdentityL( *wrapper );
       
  1554         }
       
  1555 
       
  1556     TCursorSelection timeSel = AddTimeStampL( *wrapper );
       
  1557     TCursorSelection nickSel = AddNickL( *wrapper );
       
  1558     AddContentL( startPos, *wrapper );
       
  1559     TInt endPos( iRichText->DocumentLength() );
       
  1560 
       
  1561     // set selection for highlight and the whole selection
       
  1562     // (so that this can be removed)
       
  1563     // append deletioncount to new messages
       
  1564     wrapper->Selection().SetSelection(    endPos - 1, startPos );
       
  1565     wrapper->WholeSelection().SetSelection( endPos, lineStart );
       
  1566     wrapper->MessageSelection().SetSelection( endPos - 1, nickSel.HigherPos() );
       
  1567 
       
  1568     CHAT_DP( D_CHAT_LIT( "owncol: %d msgcol: %d" ), iOwnMsgColorInUse, iMsgColorInUse );
       
  1569 
       
  1570     // append coloring
       
  1571     TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel;
       
  1572     TInt len( sel.Length() );
       
  1573     CHAT_DP( D_CHAT_LIT( "selectiong length %d" ), len );
       
  1574 
       
  1575     // Make sure the background (highlight) is not copied from
       
  1576     // previous message.
       
  1577     BackColorL( sel, KRgbWhite );
       
  1578     TextBackColorL( sel, KRgbWhite );
       
  1579 
       
  1580     if ( len > 0 &&
       
  1581          aMessage.MessageType() != TEnumsPC::EMessageSystem )
       
  1582         {
       
  1583         // custom colors
       
  1584         if ( aMessage.MessagerType() == TEnumsPC::EMessageSent )
       
  1585             {
       
  1586             // own msg
       
  1587             if ( iOwnMsgColorInUse )
       
  1588                 {
       
  1589                 TextColorL( sel, iOwnMsgColor );
       
  1590                 }
       
  1591             else
       
  1592                 {
       
  1593                 //default color
       
  1594                 TextColorL( sel, iDefaultMsgColor );
       
  1595                 }
       
  1596             }
       
  1597         else if ( aMessage.MessagerType() == TEnumsPC::EMessageReceived )
       
  1598             {
       
  1599             // other msg
       
  1600             if ( iMsgColorInUse )
       
  1601                 {
       
  1602                 TextColorL( sel, iMsgColor );
       
  1603                 }
       
  1604             else
       
  1605                 {
       
  1606                 //default color
       
  1607                 TextColorL( sel, iDefaultMsgColor );
       
  1608                 }
       
  1609             }
       
  1610 
       
  1611         }
       
  1612 
       
  1613 
       
  1614     // inform of inserted rich text
       
  1615     TCursorSelection curSel( CurrentSelection() );
       
  1616     TRAPD( error, iTextView.HandleAdditionL( lineStart == 0, curSel, EFalse ) );
       
  1617     if ( error != KErrNone )
       
  1618         {
       
  1619         CHAT_DP_TXT( "CCARichTextContainer::AddMessageL: Recovering from error" );
       
  1620 
       
  1621         // Remove failed text
       
  1622         TCursorSelection del = wrapper->WholeSelection();
       
  1623         iRichText->DeleteL( del.LowerPos(), del.Length() );
       
  1624 
       
  1625         if ( error == KErrNoMemory )
       
  1626             {
       
  1627             // If OOM => stop processing all our pending messages
       
  1628             iRecoveringFromOOM = ETrue;
       
  1629             TInt count = iMessages.Count();
       
  1630             for ( TInt i = count - 1; i >= 0; --i )
       
  1631                 {
       
  1632                 TRAP_IGNORE( iMessages[i]->Message().RemoveProcessingL() );
       
  1633                 }
       
  1634             iRecoveringFromOOM = EFalse;
       
  1635             }
       
  1636         else
       
  1637             {
       
  1638             TRAP_IGNORE( wrapper->Message().RemoveProcessingL() );
       
  1639             }
       
  1640 
       
  1641         // Remove the failed wrapper and leave
       
  1642         TInt index = iMessages.Find( wrapper );
       
  1643         if ( index != KErrNotFound )
       
  1644             {
       
  1645             delete wrapper;
       
  1646             iMessages.Remove( index );
       
  1647             }
       
  1648 
       
  1649         // Try to handle changes once more
       
  1650         TRAPD( updateErr, iTextView.HandleGlobalChangeNoRedrawL() );
       
  1651         if ( !updateErr )
       
  1652             {
       
  1653             TCursorSelection curSel( CurrentSelection() );
       
  1654             TRAP_IGNORE( iTextView.ScrollVisibleL( curSel, EFalse ) );
       
  1655             }
       
  1656         User::Leave( error );
       
  1657         }
       
  1658 
       
  1659     // and scroll (unless in highlight-mode)
       
  1660     if ( iHighlightState == ENoHighlight )
       
  1661         {
       
  1662         TCursorSelection curSel( CurrentSelection() );
       
  1663         iTextView.ScrollVisibleL( curSel, EFalse );
       
  1664 
       
  1665         // If this is recorded chat container (iScrollOver == EFalse)
       
  1666         // and added message was first move highlight
       
  1667         // so we have focus on the topmost item.
       
  1668         if ( oldCount == 0 && !iScrollOver )
       
  1669             {
       
  1670             if ( !iMsgAddedToContentProcessor )
       
  1671                 {
       
  1672                 MoveHighlightL( ENext );
       
  1673                 }
       
  1674             if ( iAddMsgObserver )
       
  1675                 {
       
  1676                 iAddMsgObserver->HandleMessageAddedL( iMessages.Count() );
       
  1677                 }
       
  1678             }
       
  1679 
       
  1680         }
       
  1681     }
       
  1682 
       
  1683 // -----------------------------------------------------------------------------
       
  1684 // CCARichTextContainer::MessageChangedL
       
  1685 // (other items were commented in a header).
       
  1686 // -----------------------------------------------------------------------------
       
  1687 //
       
  1688 void CCARichTextContainer::MessageChangedL( TInt aIndex )
       
  1689     {
       
  1690     CHAT_DP_FUNC_ENTER( "CCARichTextContainer::MessageChangedL" );
       
  1691     __CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < iMessages.Count() );
       
  1692 
       
  1693     if ( iRecoveringFromOOM )
       
  1694         {
       
  1695         // Don't handle changes if we had OOM situation.
       
  1696         return;
       
  1697         }
       
  1698 
       
  1699     CCAMessageWrapper* wrapper = iMessages[ aIndex ];
       
  1700 
       
  1701     // we don't know what's changed, so update whole message
       
  1702 
       
  1703     TCursorSelection& thumbPos = wrapper->ThumbPos();
       
  1704     if ( thumbPos.iAnchorPos != 0 )
       
  1705         {
       
  1706         TInt oldLength( thumbPos.Length() );
       
  1707 
       
  1708         // update thumbnail
       
  1709         if ( thumbPos.Length() > 0 )
       
  1710             {
       
  1711             // delete old thumb
       
  1712             iRichText->DeleteL( thumbPos.iAnchorPos, oldLength );
       
  1713 
       
  1714             TCursorSelection& sel = wrapper->Selection();
       
  1715             TCursorSelection& wholeSel = wrapper->WholeSelection();
       
  1716 
       
  1717             sel.iCursorPos -= thumbPos.Length();
       
  1718             wholeSel.iCursorPos -= thumbPos.Length();
       
  1719             }
       
  1720         AddThumbL( thumbPos.iAnchorPos, *wrapper );
       
  1721         TInt newLength = wrapper->ThumbPos().Length();
       
  1722 
       
  1723         // if there are messages after this one,
       
  1724         // change the selections of those so that they
       
  1725         // are correct after we've added some characters
       
  1726         UpdateWrappers( aIndex + 1, newLength - oldLength );
       
  1727 
       
  1728         // inform of deleted and inserted text
       
  1729         if ( !wrapper->IsInserted() )
       
  1730             {
       
  1731             iTextView.HandleInsertDeleteL( wrapper->ThumbPos(), oldLength );
       
  1732             }
       
  1733         }
       
  1734 
       
  1735     if ( !wrapper->IsInserted() )
       
  1736         {
       
  1737         iTextView.HandleFormatChangedL( wrapper->Selection(),
       
  1738                                         iHighlightState != ENoHighlight );
       
  1739         }
       
  1740     else
       
  1741         {
       
  1742         // HandleGlobalChangeNoRedrawL worked before, but not anymore.. dunno why.
       
  1743         // We have to use this instead.
       
  1744         TCursorSelection sel = CurrentSelection();
       
  1745         iTextView.HandleAdditionL( ETrue, sel, EFalse );
       
  1746         }
       
  1747 
       
  1748     // Scroll view correctly
       
  1749     TCursorSelection sel = CurrentSelection();
       
  1750     iTextView.ScrollVisibleL( sel, EFalse );
       
  1751 
       
  1752     //Messages whose content are images
       
  1753     //have completed the processing
       
  1754     if ( iMsgAddedToContentProcessor )
       
  1755         {
       
  1756         //decrement the messages which has completed processing
       
  1757         iMsgAddedToContentProcessor--;
       
  1758 
       
  1759         if ( !iScrollOver )
       
  1760             {
       
  1761             //only for recorded chats iScrollOver=EFalse
       
  1762             //put the focus on the first item
       
  1763             MoveHighlightL( ENext );
       
  1764             }
       
  1765 
       
  1766         else
       
  1767             {
       
  1768             //when user navigate among tab.
       
  1769             //for conversations/groupview
       
  1770             if ( ( iHighlightState == ENoHighlight ) &&
       
  1771                  !iMsgAddedToContentProcessor &&
       
  1772                  iAddMsgObserver )
       
  1773                 {
       
  1774                 iAddMsgObserver->HandleMessageAddedL( iMessages.Count() );
       
  1775                 }
       
  1776             }
       
  1777         }
       
  1778     }
       
  1779 
       
  1780 
       
  1781 // -----------------------------------------------------------------------------
       
  1782 // CCARichTextContainer::RemoveMessage
       
  1783 // (other items were commented in a header).
       
  1784 // -----------------------------------------------------------------------------
       
  1785 //
       
  1786 void CCARichTextContainer::RemoveMessage( TInt aIndex )
       
  1787     {
       
  1788     __CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < iMessages.Count() );
       
  1789     CCAMessageWrapper* wrapper = iMessages[ aIndex ];
       
  1790 
       
  1791     TCursorSelection& sel = wrapper->WholeSelection();
       
  1792     TInt selectionLength( sel.Length() );
       
  1793 
       
  1794     TRAPD( err, iRichText->DeleteL( sel.LowerPos(), selectionLength ) )
       
  1795     if ( err != KErrNone )
       
  1796         {
       
  1797         // nothing else we could do if the rich text deletion,
       
  1798         // for some reason, didn't succeed.
       
  1799         CActiveScheduler::Current()->Error( err );
       
  1800         }
       
  1801     else
       
  1802         {
       
  1803         // inform viewer of deletion
       
  1804         TCursorSelection startPos( sel.LowerPos(), sel.LowerPos() );
       
  1805         TRAPD( err, iTextView.HandleInsertDeleteL( startPos, selectionLength ) );
       
  1806         if ( err != KErrNone )
       
  1807             {
       
  1808             CActiveScheduler::Current()->Error( err );
       
  1809             }
       
  1810         iTextView.Redraw();
       
  1811 
       
  1812         // message deleted from rich text, we must update the
       
  1813         // positions of all messages after this one
       
  1814         UpdateWrappers( aIndex + 1, -selectionLength );
       
  1815 
       
  1816         // delete wrapper
       
  1817         delete wrapper;
       
  1818         iMessages.Remove( aIndex );
       
  1819 
       
  1820         // check selection
       
  1821         TInt count( iMessages.Count() );
       
  1822         if ( iSelected >= count )
       
  1823             {
       
  1824             iSelected = count - 1;
       
  1825             if ( iSelected < 0 )
       
  1826                 {
       
  1827                 // no messages, nothing to highlight
       
  1828                 iSelected = 0;
       
  1829                 TRAPD( err, DisableHighlightL() );
       
  1830                 if ( err != KErrNone )
       
  1831                     {
       
  1832                     CActiveScheduler::Current()->Error( err );
       
  1833                     }
       
  1834                 }
       
  1835             }
       
  1836 
       
  1837         // check scroll position
       
  1838         TCursorSelection scroll( iTextView.ScrollSelection() );
       
  1839         TInt docLen( iRichText->DocumentLength() );
       
  1840         if ( scroll.HigherPos() >= docLen && docLen ) // no need for scroll with zero doclen
       
  1841             {
       
  1842             // update if it was wrong
       
  1843             scroll.iAnchorPos = docLen - 1;
       
  1844             scroll.iCursorPos = docLen - 1;
       
  1845             TRAPD( err, iTextView.ScrollVisibleL( scroll, EFalse ) );
       
  1846             if ( err != KErrNone )
       
  1847                 {
       
  1848                 CActiveScheduler::Current()->Error( err );
       
  1849                 }
       
  1850             }
       
  1851         }
       
  1852     }
       
  1853 
       
  1854 // -----------------------------------------------------------------------------
       
  1855 // CCARichTextContainer::IsDeleted
       
  1856 // (other items were commented in a header).
       
  1857 // -----------------------------------------------------------------------------
       
  1858 //
       
  1859 TBool CCARichTextContainer::IsDeleted() const
       
  1860     {
       
  1861     return iMessagesDeleted;
       
  1862     }
       
  1863 
       
  1864 // -----------------------------------------------------------------------------
       
  1865 // CCARichTextContainer::MarkDeleted
       
  1866 // (other items were commented in a header).
       
  1867 // -----------------------------------------------------------------------------
       
  1868 //
       
  1869 void CCARichTextContainer::MarkDeleted()
       
  1870     {
       
  1871     iMessagesDeleted = ETrue;
       
  1872     }
       
  1873 
       
  1874 // -----------------------------------------------------------------------------
       
  1875 // CCARichTextContainer::InsertMessageL
       
  1876 // (other items were commented in a header).
       
  1877 // -----------------------------------------------------------------------------
       
  1878 //
       
  1879 void CCARichTextContainer::InsertMessageL( MCAConversationMessage& aMessage )
       
  1880     {
       
  1881     if ( !iShowTimeStamps &&
       
  1882          aMessage.SystemMessageType() == TEnumsPC::ESystemMessageDateChange )
       
  1883         {
       
  1884         // if timestamp setting is OFF we don't show day change items
       
  1885         return;
       
  1886         }
       
  1887     // create wrapper
       
  1888     CCAMessageWrapper* wrapper = CCAMessageWrapper::NewL( aMessage, *this );
       
  1889 
       
  1890     CleanupStack::PushL( wrapper );
       
  1891     iMessages.InsertL( wrapper, 0 ); // takes the ownership
       
  1892     CleanupStack::Pop( wrapper );
       
  1893 
       
  1894     if ( aMessage.ContentType() == TEnumsPC::EContentPicture )
       
  1895         {
       
  1896         if ( IMUtils::ContentProtectedL( aMessage.ContentData() ) )
       
  1897             {
       
  1898             aMessage.SetProcessState( TEnumsPC::EContentNotSupported );
       
  1899             }
       
  1900         else
       
  1901             {
       
  1902             // add thumbnail processor for message
       
  1903             aMessage.AddContentProcessorL( iThumbSize );
       
  1904 
       
  1905             //once any message added to the content processor
       
  1906             //increment this iMsgAddedToContentProcessor
       
  1907             iMsgAddedToContentProcessor++;
       
  1908 
       
  1909             }
       
  1910         }
       
  1911 
       
  1912     TInt oldLen = iRichText->DocumentLength();
       
  1913 
       
  1914     // Insert paragraph break if this is not the last message
       
  1915     TInt paraBreak = 0;
       
  1916     if ( iMessages.Count() > 1 )
       
  1917         {
       
  1918         iRichText->InsertL( 0, CEditableText::EParagraphDelimiter );
       
  1919         paraBreak = 1;
       
  1920         }
       
  1921 
       
  1922     // Insert message to rich text in reverse order compared to adding
       
  1923     TInt contentLen = InsertContentL( *wrapper );
       
  1924     TCursorSelection nickSel = InsertNickL( *wrapper );
       
  1925     TCursorSelection timeSel = InsertTimeStampL( *wrapper );
       
  1926     //	IM client UI customization, phase 2
       
  1927     //  Based on Variation flag, enables User Identity with Time Stamp
       
  1928     //  in chat conversation view.
       
  1929 
       
  1930     // read variation flag values
       
  1931     TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1932     TCursorSelection userSel;
       
  1933     if ( requireUserIdentity )
       
  1934         {
       
  1935         userSel = InsertUserIdentityL( *wrapper );
       
  1936         }
       
  1937 
       
  1938     TInt dirChrLen = iRichText->DocumentLength();
       
  1939     iRichText->InsertL( 0, AknLayoutUtils::LayoutMirrored() ?
       
  1940                         KUnicodeRLM : KUnicodeLRM );
       
  1941     dirChrLen = iRichText->DocumentLength() - dirChrLen;
       
  1942 
       
  1943     wrapper->SetInserted( ETrue );
       
  1944 
       
  1945     // read variation flag values
       
  1946     //TInt needUserIdentity = IntResourceValueL(RSC_CHAT_VARIATION_SHOW_USER_IDENTITY);
       
  1947     TInt needUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  1948     if ( needUserIdentity )
       
  1949         {
       
  1950         // Update user selection
       
  1951         userSel.iAnchorPos += dirChrLen;
       
  1952         userSel.iCursorPos += dirChrLen;
       
  1953         // Update timestamp selection
       
  1954         timeSel.iAnchorPos += userSel.HigherPos();
       
  1955         timeSel.iCursorPos += userSel.HigherPos();
       
  1956         // Update nick selection
       
  1957         nickSel.iAnchorPos += timeSel.HigherPos();
       
  1958         nickSel.iCursorPos += timeSel.HigherPos();
       
  1959         }
       
  1960     else
       
  1961         {
       
  1962         // Update timestamp selection
       
  1963         timeSel.iAnchorPos += dirChrLen;
       
  1964         timeSel.iCursorPos += dirChrLen;
       
  1965         // Update nick selection
       
  1966         nickSel.iAnchorPos += timeSel.HigherPos();
       
  1967         nickSel.iCursorPos += timeSel.HigherPos();
       
  1968         }
       
  1969     // Update thumb pos
       
  1970     TCursorSelection& thumbPos = wrapper->ThumbPos();
       
  1971     thumbPos.iAnchorPos += nickSel.HigherPos() + KSeparator().Length();
       
  1972     thumbPos.iCursorPos += nickSel.HigherPos() + KSeparator().Length();
       
  1973 
       
  1974     TInt addedLen = iRichText->DocumentLength() - oldLen;
       
  1975 
       
  1976     // parse text for highlights and store positions to messagewrapper
       
  1977     HBufC* text = HBufC::NewMaxLC( contentLen );
       
  1978     TPtr txt( text->Des() );
       
  1979     iRichText->Extract( txt,
       
  1980                         nickSel.HigherPos() + KSeparator().Length() + 1, // Don't extract separator and space
       
  1981                         contentLen );
       
  1982     ParseTextL( txt, nickSel.HigherPos() + KSeparator().Length() + 1,
       
  1983                 nickSel.HigherPos() + KSeparator().Length() + 1, *wrapper );
       
  1984     CleanupStack::PopAndDestroy( text );
       
  1985 
       
  1986     // Set selection for highlight and the whole selection
       
  1987     // so that this message can be removed
       
  1988     wrapper->Selection().SetSelection( addedLen - 1 - paraBreak, 0 );
       
  1989     wrapper->WholeSelection().SetSelection( addedLen - 1, 0 );
       
  1990     wrapper->MessageSelection().SetSelection( addedLen - 1,
       
  1991                                               nickSel.HigherPos() + 1 );
       
  1992 
       
  1993     if ( iHighlightState != ENoHighlight )
       
  1994         {
       
  1995         BackColorL( wrapper->WholeSelection(), KRgbWhite );
       
  1996         TextBackColorL( wrapper->WholeSelection(), KRgbWhite );
       
  1997         }
       
  1998 
       
  1999     // Update wrappers after this if there is any
       
  2000     if ( iMessages.Count() > 1 )
       
  2001         {
       
  2002         UpdateWrappers( 1, addedLen );
       
  2003         }
       
  2004 
       
  2005     // Append coloring
       
  2006     TCursorSelection& sel = iColorWholeMessage ? wrapper->Selection() : nickSel;
       
  2007     TInt len( sel.Length() );
       
  2008     CHAT_DP( D_CHAT_LIT( "selectiong length %d" ), len );
       
  2009 
       
  2010     if ( len > 0 &&
       
  2011          aMessage.MessageType() != TEnumsPC::EMessageSystem )
       
  2012         {
       
  2013         // Custom colors
       
  2014         if ( aMessage.MessagerType() == TEnumsPC::EMessageSent )
       
  2015             {
       
  2016             // Own msg
       
  2017             if ( iOwnMsgColorInUse )
       
  2018                 {
       
  2019                 TextColorL( sel, iOwnMsgColor );
       
  2020                 }
       
  2021             else
       
  2022                 {
       
  2023                 //default color
       
  2024                 TextColorL( sel, iDefaultMsgColor );
       
  2025                 }
       
  2026 
       
  2027             }
       
  2028         else if ( aMessage.MessagerType() == TEnumsPC::EMessageReceived )
       
  2029             {
       
  2030             // Other msg
       
  2031             if ( iMsgColorInUse )
       
  2032                 {
       
  2033                 TextColorL( sel, iMsgColor );
       
  2034                 }
       
  2035             else
       
  2036                 {
       
  2037                 //default color
       
  2038                 TextColorL( sel, iDefaultMsgColor );
       
  2039                 }
       
  2040             }
       
  2041         }
       
  2042 
       
  2043     if ( len > 0 &&
       
  2044          aMessage.MessageType() == TEnumsPC::EMessageSystem )
       
  2045         {
       
  2046         TextColorL( sel, iDefaultMsgColor );
       
  2047         }
       
  2048     // Inform of inserted rich text
       
  2049     TInt error = KErrNone;
       
  2050     if ( oldLen == 0 )
       
  2051         {
       
  2052         TCursorSelection curSel( CurrentSelection() );
       
  2053         // First message inserted, format the whole text
       
  2054         TRAP( error, iTextView.HandleAdditionL( ETrue, curSel, EFalse ) );
       
  2055         }
       
  2056     else
       
  2057         {
       
  2058         TCursorSelection curSel( CurrentSelection() );
       
  2059         // There might be a faster method to handle text addition, but
       
  2060         // this works for now.
       
  2061         TRAP( error, iTextView.HandleAdditionL( ETrue, curSel, EFalse ) );
       
  2062         }
       
  2063 
       
  2064     if ( error != KErrNone )
       
  2065         {
       
  2066         // Remove the failed wrapper and leave
       
  2067         wrapper->Message().RemoveProcessingL();
       
  2068         TInt index = iMessages.Find( wrapper );
       
  2069         if ( index != KErrNotFound )
       
  2070             {
       
  2071             delete wrapper;
       
  2072             iMessages.Remove( index );
       
  2073             }
       
  2074         User::Leave( error );
       
  2075         }
       
  2076 
       
  2077     // And scroll (unless in highlight-mode)
       
  2078     if ( iHighlightState == ENoHighlight )
       
  2079         {
       
  2080         TCursorSelection curSel( CurrentSelection() );
       
  2081         iTextView.ScrollVisibleL( curSel, EFalse );
       
  2082 
       
  2083         //if no messages are being processed for the content
       
  2084         //i.e., all messages are text messages
       
  2085         if ( !iMsgAddedToContentProcessor && iAddMsgObserver )
       
  2086             {
       
  2087             iAddMsgObserver->HandleMessageAddedL( iMessages.Count() );
       
  2088             }
       
  2089         }
       
  2090     else
       
  2091         {
       
  2092         // In highlight mode, message inserted -> increase selected
       
  2093         // message index and previous selection indexes
       
  2094         iSelected++;
       
  2095         iPrevious.iAnchorPos += addedLen;
       
  2096         iPrevious.iCursorPos += addedLen;
       
  2097 
       
  2098         TCursorSelection curSel( CurrentSelection() );
       
  2099         iTextView.ScrollVisibleL( curSel, EFalse );
       
  2100         }
       
  2101     }
       
  2102 
       
  2103 // -----------------------------------------------------------------------------
       
  2104 // CCARichTextContainer::UpdateWrappers
       
  2105 // (other items were commented in a header).
       
  2106 // -----------------------------------------------------------------------------
       
  2107 //
       
  2108 void CCARichTextContainer::UpdateWrappers( TInt aFirstIndex, TInt aChange )
       
  2109     {
       
  2110     TInt count( iMessages.Count() );
       
  2111     for ( TInt i( aFirstIndex ); i < count; ++i )
       
  2112         {
       
  2113         CCAMessageWrapper* wrapper = iMessages[i];
       
  2114         TCursorSelection& selection = wrapper->Selection();
       
  2115         TCursorSelection& wholeSelection = wrapper->WholeSelection();
       
  2116         TCursorSelection& thumbPos = wrapper->ThumbPos();
       
  2117         selection.iAnchorPos += aChange;
       
  2118         selection.iCursorPos += aChange;
       
  2119         wholeSelection.iAnchorPos += aChange;
       
  2120         wholeSelection.iCursorPos += aChange;
       
  2121         thumbPos.iAnchorPos += aChange;
       
  2122         thumbPos.iCursorPos += aChange;
       
  2123         }
       
  2124     }
       
  2125 
       
  2126 // -----------------------------------------------------------------------------
       
  2127 // CCARichTextContainer::Union
       
  2128 // (other items were commented in a header).
       
  2129 // -----------------------------------------------------------------------------
       
  2130 //
       
  2131 TCursorSelection CCARichTextContainer::Union( const TCursorSelection& aSel1,
       
  2132                                               const TCursorSelection& aSel2 )
       
  2133     {
       
  2134     // make union of selections
       
  2135     TCursorSelection changed;
       
  2136     changed.iAnchorPos = aSel1.LowerPos();
       
  2137     changed.iCursorPos = aSel1.HigherPos();
       
  2138 
       
  2139     TInt low(  aSel2.LowerPos() );
       
  2140     TInt high( aSel2.HigherPos() );
       
  2141     if ( low < changed.iAnchorPos )
       
  2142         {
       
  2143         changed.iAnchorPos = low;
       
  2144         }
       
  2145     if ( high > changed.iCursorPos )
       
  2146         {
       
  2147         changed.iCursorPos = high;
       
  2148         }
       
  2149 
       
  2150     return changed;
       
  2151     }
       
  2152 
       
  2153 // -----------------------------------------------------------------------------
       
  2154 // CCARichTextContainer::CurrentSelection
       
  2155 // (other items were commented in a header).
       
  2156 // -----------------------------------------------------------------------------
       
  2157 //
       
  2158 TCursorSelection CCARichTextContainer::CurrentSelection() const
       
  2159     {
       
  2160     TCursorSelection sel( 0, 0 );
       
  2161     if ( iHighlightState == ENoHighlight )
       
  2162         {
       
  2163         // if nothing highlighted, return last message
       
  2164         TInt count( iMessages.Count() );
       
  2165         if ( count > 0 )
       
  2166             {
       
  2167             sel = iMessages[count-1]->Selection();
       
  2168             }
       
  2169         }
       
  2170     else
       
  2171         {
       
  2172         // something highlighted, start with current message
       
  2173         sel = iMessages[iSelected]->Selection();
       
  2174 
       
  2175         // check if the highlighted selection is item inside message
       
  2176         if ( iHighlightState == EItemSelected )
       
  2177             {
       
  2178             // calculate item highlight position
       
  2179             TCursorSelection itemSel(
       
  2180                 iMessages[iSelected]->Highlights()[iSelectedItem] );
       
  2181 
       
  2182             TInt messageStart( sel.LowerPos() );
       
  2183             sel.iAnchorPos = itemSel.iAnchorPos + messageStart;
       
  2184             sel.iCursorPos = itemSel.iCursorPos + messageStart;
       
  2185             }
       
  2186         }
       
  2187 
       
  2188     return sel;
       
  2189     }
       
  2190 
       
  2191 
       
  2192 // -----------------------------------------------------------------------------
       
  2193 // CCARichTextContainer::TextBackColorL
       
  2194 // (other items were commented in a header).
       
  2195 // -----------------------------------------------------------------------------
       
  2196 //
       
  2197 void CCARichTextContainer::TextBackColorL( const TCursorSelection& aSel,
       
  2198                                            const TRgb& aColor )
       
  2199     {
       
  2200 #ifdef _DEBUG
       
  2201     TInt len( iRichText->DocumentLength() );
       
  2202     CHAT_DP( D_CHAT_LIT(
       
  2203                  "CCARichTextContainer::TextBackColorL selection: %d,%d, textlen %d" ),
       
  2204              aSel.iAnchorPos, aSel.iCursorPos, len );
       
  2205 #endif //_DEBUG
       
  2206 
       
  2207     TCharFormat charFormat;
       
  2208     TCharFormatMask charFormatMask;
       
  2209     charFormatMask.SetAttrib( EAttFontHighlightColor );
       
  2210     charFormatMask.SetAttrib( EAttFontHighlightStyle );
       
  2211 
       
  2212     charFormat.iFontPresentation.iHighlightColor = aColor;
       
  2213     charFormat.iFontPresentation.iHighlightStyle = aColor == KRgbWhite ?
       
  2214                                                    TFontPresentation::EFontHighlightNone :
       
  2215                                                    TFontPresentation::EFontHighlightNormal;
       
  2216 
       
  2217     iRichText->ApplyCharFormatL( charFormat, charFormatMask,
       
  2218                                  aSel.LowerPos(),
       
  2219                                  aSel.Length() );
       
  2220     }
       
  2221 
       
  2222 // -----------------------------------------------------------------------------
       
  2223 // CCARichTextContainer::TextColorL
       
  2224 // (other items were commented in a header).
       
  2225 // -----------------------------------------------------------------------------
       
  2226 //
       
  2227 void CCARichTextContainer::TextColorL( const TCursorSelection& aSel,
       
  2228                                        const TRgb& aColor )
       
  2229     {
       
  2230 #ifdef _DEBUG
       
  2231     TInt len( iRichText->DocumentLength() );
       
  2232     CHAT_DP( D_CHAT_LIT(
       
  2233                  "CCARichTextContainer::TextColorL selection: %d,%d, textlen %d" ),
       
  2234              aSel.iAnchorPos, aSel.iCursorPos, len );
       
  2235 #endif //_DEBUG
       
  2236     TCharFormat charFormat;
       
  2237     TCharFormatMask charFormatMask;
       
  2238     charFormatMask.SetAttrib( EAttColor );
       
  2239     charFormat.iFontPresentation.iTextColor = aColor;
       
  2240 
       
  2241     iRichText->ApplyCharFormatL( charFormat, charFormatMask,
       
  2242                                  aSel.LowerPos(),
       
  2243                                  aSel.Length() );
       
  2244     }
       
  2245 
       
  2246 // -----------------------------------------------------------------------------
       
  2247 // CCARichTextContainer::BackColorL
       
  2248 // (other items were commented in a header).
       
  2249 // -----------------------------------------------------------------------------
       
  2250 //
       
  2251 void CCARichTextContainer::BackColorL( const TCursorSelection& aSel,
       
  2252                                        const TRgb& aColor )
       
  2253     {
       
  2254 #ifdef _DEBUG
       
  2255     TInt len( iRichText->DocumentLength() );
       
  2256     CHAT_DP( D_CHAT_LIT(
       
  2257                  "CCARichTextContainer::BackColorL selection: %d,%d, textlen %d" ),
       
  2258              aSel.iAnchorPos, aSel.iCursorPos, len );
       
  2259 #endif //_DEBUG
       
  2260 
       
  2261     CParaFormat paraFormat;
       
  2262     TParaFormatMask paraFormatMask;
       
  2263     paraFormatMask.SetAttrib( EAttFillColor );
       
  2264 
       
  2265     paraFormat.iFillColor = aColor;
       
  2266     iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask,
       
  2267                                  aSel.LowerPos(),
       
  2268                                  aSel.Length() );
       
  2269     }
       
  2270 
       
  2271 // -----------------------------------------------------------------------------
       
  2272 // CCARichTextContainer::HighLightItemL
       
  2273 // (other items were commented in a header).
       
  2274 // -----------------------------------------------------------------------------
       
  2275 //
       
  2276 void CCARichTextContainer::HighLightItemL( const TCursorSelection& aSel )
       
  2277     {
       
  2278 #ifdef _DEBUG
       
  2279     TInt len( iRichText->DocumentLength() );
       
  2280     CHAT_DP( D_CHAT_LIT(
       
  2281                  "CCARichTextContainer::HighLightItemL selection: %d,%d, textlen %d" ),
       
  2282              aSel.iAnchorPos, aSel.iCursorPos, len );
       
  2283 #endif //_DEBUG
       
  2284 
       
  2285     TCharFormat charFormat;
       
  2286     TCharFormatMask charFormatMask;
       
  2287     charFormatMask.SetAttrib( EAttFontUnderline );
       
  2288 
       
  2289     charFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
  2290 
       
  2291     iRichText->ApplyCharFormatL( charFormat, charFormatMask,
       
  2292                                  aSel.LowerPos(),
       
  2293                                  aSel.Length() );
       
  2294     }
       
  2295 
       
  2296 // -----------------------------------------------------------------------------
       
  2297 // CCARichTextContainer::BoldL
       
  2298 // (other items were commented in a header).
       
  2299 // -----------------------------------------------------------------------------
       
  2300 //
       
  2301 void CCARichTextContainer::BoldL( const TCursorSelection& aSel )
       
  2302     {
       
  2303 #ifdef _DEBUG
       
  2304     TInt len( iRichText->DocumentLength() );
       
  2305     CHAT_DP( D_CHAT_LIT(
       
  2306                  "CCARichTextContainer::BoldL selection: %d,%d, textlen %d" ),
       
  2307              aSel.iAnchorPos, aSel.iCursorPos, len );
       
  2308 #endif //_DEBUG
       
  2309 
       
  2310     TCharFormat charFormat;
       
  2311     TCharFormatMask charFormatMask;
       
  2312 
       
  2313     charFormat.iFontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
       
  2314     charFormatMask.SetAttrib( EAttFontStrokeWeight );
       
  2315 
       
  2316     iRichText->ApplyCharFormatL( charFormat, charFormatMask,
       
  2317                                  aSel.LowerPos(),
       
  2318                                  aSel.Length() );
       
  2319     }
       
  2320 
       
  2321 // -----------------------------------------------------------------------------
       
  2322 // CCARichTextContainer::ParseTextL
       
  2323 // (other items were commented in a header).
       
  2324 // -----------------------------------------------------------------------------
       
  2325 //
       
  2326 void CCARichTextContainer::ParseTextL( const TDesC& aText, TInt aStartPos,
       
  2327                                        TInt aRelativePos, CCAMessageWrapper& aMessageWrapper )
       
  2328     {
       
  2329     CFindItemEngine* findItem = CFindItemEngine::NewL( aText,
       
  2330                                                        CFindItemEngine::TFindItemSearchCase(
       
  2331                                                            CFindItemEngine::EFindItemSearchPhoneNumberBin |
       
  2332                                                            CFindItemEngine::EFindItemSearchMailAddressBin |
       
  2333                                                            CFindItemEngine::EFindItemSearchURLBin/* |
       
  2334                                 CFindItemEngine::EFindItemSearchScheme*/ )
       
  2335                                                      );
       
  2336 
       
  2337     CleanupStack::PushL( findItem );
       
  2338 
       
  2339     // reset array
       
  2340     RArray<TCursorSelection>& highlights = aMessageWrapper.Highlights();
       
  2341     RArray<TInt>& types = aMessageWrapper.HighlightTypes();
       
  2342     highlights.Reset();
       
  2343     types.Reset();
       
  2344 
       
  2345     // get found items
       
  2346     const CArrayFixFlat<CFindItemEngine::SFoundItem>* items =
       
  2347         findItem->ItemArray();
       
  2348     TInt count( items->Count() );
       
  2349 
       
  2350     for ( TInt i( 0 ); i < count; ++i )
       
  2351         {
       
  2352         const CFindItemEngine::SFoundItem item = items->At( i );
       
  2353 
       
  2354         // selection in rich text
       
  2355         TCursorSelection realSel( aStartPos + item.iStartPos + item.iLength,
       
  2356                                   aStartPos + item.iStartPos );
       
  2357 
       
  2358         // relative selection inside one message
       
  2359         TCursorSelection relativeSel( aRelativePos + item.iStartPos +
       
  2360                                       item.iLength,
       
  2361                                       aRelativePos + item.iStartPos );
       
  2362 
       
  2363         highlights.AppendL( relativeSel );
       
  2364         types.AppendL( item.iItemType );
       
  2365 
       
  2366         // apply highlight item formatting
       
  2367         HighLightItemL( realSel );
       
  2368         }
       
  2369 
       
  2370     CleanupStack::PopAndDestroy( findItem );
       
  2371     }
       
  2372 
       
  2373 // -----------------------------------------------------------------------------
       
  2374 // CCARichTextContainer::AddNickL
       
  2375 // (other items were commented in a header).
       
  2376 // -----------------------------------------------------------------------------
       
  2377 //
       
  2378 TCursorSelection CCARichTextContainer::AddNickL(
       
  2379     CCAMessageWrapper& aMessageWrapper )
       
  2380     {
       
  2381 
       
  2382 
       
  2383     // insert nick
       
  2384     MCAConversationMessage& message = aMessageWrapper.Message();
       
  2385 
       
  2386     if ( message.FailedMessage() )
       
  2387         {
       
  2388         return 	TCursorSelection( 0, 0 );
       
  2389         }
       
  2390 
       
  2391     TPtrC sender;
       
  2392     TPtrC recipient;
       
  2393 
       
  2394     if ( message.MessageType() == TEnumsPC::EMessageGroup ||
       
  2395          message.MessageType() == TEnumsPC::EMessageWhisper )
       
  2396         {
       
  2397         sender.Set( message.Sender() );
       
  2398         recipient.Set( message.Recipient() );
       
  2399         }
       
  2400     else
       
  2401         {
       
  2402         MCAStoredContacts* contacts =
       
  2403             CCAStorageManagerFactory::ContactListInterfaceL();
       
  2404         if ( message.MessagerType() == TEnumsPC::EMessageSent
       
  2405              && message.MessageType() != TEnumsPC::EMessageSystem )
       
  2406             {
       
  2407             sender.Set( contacts->OwnStatus().Identification() );
       
  2408             }
       
  2409         else
       
  2410             {
       
  2411             sender.Set( contacts->Identification( message.Sender() ) );
       
  2412             }
       
  2413 
       
  2414         recipient.Set( contacts->Identification( message.Recipient() ) );
       
  2415         }
       
  2416     TCursorSelection nickSel( 0, 0 );
       
  2417 
       
  2418     if ( message.MessagerType() == TEnumsPC::EMessageSent &&
       
  2419          message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  2420          iOwnMsgIcon )
       
  2421         {
       
  2422         // this is sent (or failed) p2p message,
       
  2423         // insert "from me" icon and separator
       
  2424         // (if icons are in use)
       
  2425 
       
  2426         //	IM client UI customization, phase 2
       
  2427         //  Based on Variation flag, changes Nick format in conversation view
       
  2428         //  removes arrow sign and append only a seperator.
       
  2429 
       
  2430         // read variation flag values
       
  2431         TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  2432         // and check dynamic features
       
  2433         if ( !requireUserIdentity )
       
  2434             {
       
  2435             CCAPicture* pic = new( ELeave )CCAPicture( iMap, iFromMe );
       
  2436             TPictureHeader header;
       
  2437             header.iPicture = TSwizzle<CPicture>( pic );
       
  2438             iRichText->CancelInsertCharFormat();    // to prevent ETEXT 31 panic
       
  2439             iRichText->InsertL( iRichText->DocumentLength(), header ); // takes ownership
       
  2440             }
       
  2441         iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
       
  2442         }
       
  2443     else
       
  2444         {
       
  2445         TInt nickStart( iRichText->DocumentLength() );
       
  2446         TInt nickEnd( nickStart );
       
  2447 
       
  2448         if ( message.MessageType() == TEnumsPC::EMessageWhisper )
       
  2449             {
       
  2450             // This is received whisper message (to us),
       
  2451             // insert sender, "to me" icon and separator
       
  2452             iRichText->InsertL( nickStart, sender );
       
  2453             nickEnd = iRichText->DocumentLength();
       
  2454 
       
  2455             CCAPicture* pic = NULL;
       
  2456             if ( message.MessagerType() == TEnumsPC::EMessageSent )
       
  2457                 {
       
  2458                 pic = new( ELeave )CCAPicture( iMap,
       
  2459                                                iFromMe );
       
  2460                 }
       
  2461             else
       
  2462                 {
       
  2463                 pic = new( ELeave )CCAPicture( iMap,
       
  2464                                                iToMe );
       
  2465                 }
       
  2466             TPictureHeader header;
       
  2467             header.iPicture = TSwizzle<CPicture>( pic );
       
  2468             iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic
       
  2469             iRichText->InsertL( nickEnd, header ); // takes ownership
       
  2470             iRichText->InsertL( iRichText->DocumentLength(), recipient );
       
  2471             nickEnd = iRichText->DocumentLength();
       
  2472             iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
       
  2473             }
       
  2474         else if ( message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  2475                   message.MessagerType() == TEnumsPC::EMessageReceived &&
       
  2476                   iMsgIcon )
       
  2477             {
       
  2478             // received p2p message and we want to display icon
       
  2479             // insert "to me" icon and separator
       
  2480             //	IM client UI customization, phase 2
       
  2481             //  Based on Variation flag, changes Nick format in conversation view
       
  2482             //  removes arrow sign and append only a seperator.
       
  2483 
       
  2484             // read variation flag values
       
  2485             TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  2486             // and check dynamic features
       
  2487             if ( !requireUserIdentity )
       
  2488                 {
       
  2489                 CCAPicture* pic = new( ELeave )CCAPicture( iMap,
       
  2490                                                            iToMe );
       
  2491                 TPictureHeader header;
       
  2492                 header.iPicture = TSwizzle<CPicture>( pic );
       
  2493                 iRichText->CancelInsertCharFormat(); // to prevent ETEXT 31 panic
       
  2494                 iRichText->InsertL( iRichText->DocumentLength(), header ); // takes ownership
       
  2495                 }
       
  2496             nickEnd = iRichText->DocumentLength();
       
  2497             iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
       
  2498             }
       
  2499         else if ( sender.Length() > 0 )
       
  2500             {
       
  2501             // this is normal group message (or p2p message if icons are not used),
       
  2502             // insert sender and separator
       
  2503             iRichText->InsertL( nickStart, sender );
       
  2504             nickEnd = iRichText->DocumentLength();
       
  2505             iRichText->InsertL( iRichText->DocumentLength(), KSeparator );
       
  2506             }
       
  2507 
       
  2508         // formatting (bold nickname)
       
  2509         nickSel.SetSelection( nickStart, nickEnd );
       
  2510         if ( nickSel.Length() > 0 )
       
  2511             {
       
  2512             BoldL( nickSel );
       
  2513             }
       
  2514         }
       
  2515     return nickSel;
       
  2516     }
       
  2517 
       
  2518 // -----------------------------------------------------------------------------
       
  2519 // CCARichTextContainer::AddTimeStampL
       
  2520 // (other items were commented in a header).
       
  2521 // -----------------------------------------------------------------------------
       
  2522 //
       
  2523 TCursorSelection CCARichTextContainer::AddTimeStampL(
       
  2524     CCAMessageWrapper& aMessageWrapper )
       
  2525     {
       
  2526     TInt start = iRichText->DocumentLength();
       
  2527     TCursorSelection timeSel( start, start );
       
  2528 
       
  2529     if ( !iSettings.GetBoolValuePC( TEnumsPC::EShowTimeStamps, NULL ) ||
       
  2530          aMessageWrapper.Message().SystemMessageType() ==
       
  2531          TEnumsPC::ESystemMessageDateChange )
       
  2532         {
       
  2533         // 1. Setting for time stamp is OFF
       
  2534         // 2. Special case: date change don't have time stamp.
       
  2535         return timeSel;
       
  2536         }
       
  2537 
       
  2538     // format time
       
  2539     HBufC* timeStamp = HBufC::NewLC( KTimeStampMaxLength + KSpace().Length() );
       
  2540     TPtr timePtr( timeStamp->Des() );
       
  2541 
       
  2542     HBufC* timeStampFormat = NULL;
       
  2543     timeStampFormat = StringLoader::LoadLC( R_QTN_TIME_USUAL_WITH_ZERO );
       
  2544 
       
  2545     TTime time = aMessageWrapper.Message().TimeStamp();
       
  2546     TRAPD( err, time.FormatL( timePtr, *timeStampFormat ) );
       
  2547     if ( err == KErrOverflow )
       
  2548         {
       
  2549         // Reserved text space was not enough.
       
  2550         // Adjust the KTimeStampMaxLength
       
  2551         __CHAT_ASSERT_DEBUG( EFalse );
       
  2552 
       
  2553         // in release builds return without timestamp
       
  2554         CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
       
  2555         return timeSel;
       
  2556         }
       
  2557 
       
  2558     // Convert numbers to local language
       
  2559     AknTextUtils::LanguageSpecificNumberConversion( timePtr );
       
  2560 
       
  2561     // Set Alignment of Pm/Am from local setting
       
  2562     // This keeps the am/pm text close to the time.
       
  2563     timePtr.Append( AknLayoutUtils::LayoutMirrored() ?
       
  2564                     KUnicodeRLM : KUnicodeLRM );
       
  2565 
       
  2566     //	IM client UI customization, phase 2
       
  2567     //  Based on Variation flag, changes Time Stamp format in conversation view.
       
  2568     //  where Time Stamp should appear in brackets.
       
  2569 
       
  2570     // read variation flag values
       
  2571     TInt requireUserIdentity = IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_SHOW_USER_IDENTITY );
       
  2572     // and check dynamic features
       
  2573     if ( requireUserIdentity )
       
  2574         {
       
  2575         // append time to rich text
       
  2576         timePtr.Insert( 0, _L( "(" ) );
       
  2577         timePtr.Append( _L( ")" ) );
       
  2578         timePtr.Append( KSpace );
       
  2579         }
       
  2580     else
       
  2581         {
       
  2582         timePtr.Append( KSpace );
       
  2583         }
       
  2584     iRichText->InsertL( start, timePtr );
       
  2585 
       
  2586     CleanupStack::PopAndDestroy( 2, timeStamp ); // timeStamp, timeStampFormat
       
  2587     timeSel.SetSelection( start, iRichText->DocumentLength() - 1 );
       
  2588 
       
  2589     // bold the time
       
  2590     if ( timeSel.Length() > 0 )
       
  2591         {
       
  2592         BoldL( timeSel );
       
  2593         }
       
  2594 
       
  2595     return timeSel;
       
  2596     }
       
  2597 
       
  2598 // -----------------------------------------------------------------------------
       
  2599 // CCARichTextContainer::AddUserIdentityL
       
  2600 // (other items were commented in a header).
       
  2601 // -----------------------------------------------------------------------------
       
  2602 //
       
  2603 TCursorSelection CCARichTextContainer::AddUserIdentityL(
       
  2604     CCAMessageWrapper& aMessageWrapper )
       
  2605     {
       
  2606     TInt start = iRichText->DocumentLength();
       
  2607     TCursorSelection userSel( start, start );
       
  2608 
       
  2609     MCAConversationMessage& message = aMessageWrapper.Message();
       
  2610     TPtrC sender;
       
  2611     TPtrC recipient;
       
  2612     MCAStoredContacts* contacts = CCAStorageManagerFactory::ContactListInterfaceL();
       
  2613     if ( message.MessagerType() == TEnumsPC::EMessageSent
       
  2614          && message.MessageType() != TEnumsPC::EMessageSystem )
       
  2615         {
       
  2616         sender.Set( contacts->OwnStatus().Identification() );
       
  2617         }
       
  2618     else
       
  2619         {
       
  2620         sender.Set( contacts->Identification( message.Sender() ) );
       
  2621         }
       
  2622     recipient.Set( contacts->Identification( message.Recipient() ) );
       
  2623 
       
  2624     if ( message.MessagerType() == TEnumsPC::EMessageSent &&
       
  2625          message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  2626          iOwnMsgIcon )
       
  2627         {
       
  2628         if ( sender.Length() >= KMaxLength )
       
  2629             {
       
  2630             TPtrC aTempPtr;
       
  2631             aTempPtr.Set( sender.Left( 8 ) );
       
  2632             TBuf<10> aTruncateSender( aTempPtr );
       
  2633             aTruncateSender.Append( _L( ".." ) );
       
  2634             iRichText->InsertL( start, aTruncateSender );
       
  2635             }
       
  2636         else
       
  2637             {
       
  2638             iRichText->InsertL( iRichText->DocumentLength(), sender );
       
  2639             }
       
  2640         }
       
  2641     else if ( message.MessageType() == TEnumsPC::EMessagePTOP &&
       
  2642               message.MessagerType() == TEnumsPC::EMessageReceived &&
       
  2643               iMsgIcon )
       
  2644         {
       
  2645         if ( recipient.Length() >= KMaxLength )
       
  2646             {
       
  2647             TPtrC aTempPtr;
       
  2648             aTempPtr.Set( recipient.Left( 8 ) );
       
  2649             TBuf<10> aTruncateRecipient( aTempPtr );
       
  2650             aTruncateRecipient.Append( _L( ".." ) );
       
  2651             iRichText->InsertL( iRichText->DocumentLength(), aTruncateRecipient );
       
  2652             }
       
  2653         else
       
  2654             {
       
  2655             iRichText->InsertL( iRichText->DocumentLength(), recipient );
       
  2656             }
       
  2657         }
       
  2658     iRichText->InsertL( iRichText->DocumentLength(), KSpace );
       
  2659     userSel.SetSelection( start, iRichText->DocumentLength() - 1 );
       
  2660 
       
  2661     // bold the time
       
  2662     if ( userSel.Length() > 0 )
       
  2663         {
       
  2664         BoldL( userSel );
       
  2665         }
       
  2666 
       
  2667     return userSel;
       
  2668     }
       
  2669 // -----------------------------------------------------------------------------
       
  2670 // CCARichTextContainer::AddContentL
       
  2671 // (other items were commented in a header).
       
  2672 // -----------------------------------------------------------------------------
       
  2673 //
       
  2674 void CCARichTextContainer::AddContentL( TInt aMsgStart,
       
  2675                                         CCAMessageWrapper& aMessageWrapper )
       
  2676     {
       
  2677     MCAConversationMessage& message = aMessageWrapper.Message();
       
  2678 
       
  2679     TEnumsPC::TContentType type( message.ContentType() );
       
  2680     switch ( type )
       
  2681         {
       
  2682         case TEnumsPC::EContentText:
       
  2683             {
       
  2684             // insert text
       
  2685             TPtrC msg( message.Text() );
       
  2686 
       
  2687             HBufC* tempMsg = NULL;
       
  2688 
       
  2689             TInt paraBreak = msg.Locate( CEditableText::EParagraphDelimiter );
       
  2690             // Replace all paragraph delimiters with line breaks
       
  2691             // to keep alingment consistent
       
  2692             if ( paraBreak != KErrNotFound )
       
  2693                 {
       
  2694                 tempMsg = msg.AllocLC();
       
  2695                 TPtr ptr( tempMsg->Des() );
       
  2696                 ptr.Zero();
       
  2697 
       
  2698                 ReplaceParaDelimsWithLineBreaks( msg, ptr );
       
  2699                 msg.Set( ptr );
       
  2700                 }
       
  2701 
       
  2702             HBufC* numberConv = NULL;
       
  2703 
       
  2704             // Convert numerals to local language
       
  2705             // 1) date item
       
  2706             if ( aMessageWrapper.Message().SystemMessageType() ==
       
  2707                  TEnumsPC::ESystemMessageDateChange )
       
  2708                 {
       
  2709                 // don't touch the original message
       
  2710                 numberConv = msg.AllocLC();
       
  2711                 TPtr ptr( numberConv->Des() );
       
  2712                 AknTextUtils::LanguageSpecificNumberConversion( ptr );
       
  2713                 msg.Set( ptr );
       
  2714                 }
       
  2715 
       
  2716             TInt textStart( iRichText->DocumentLength() );
       
  2717             iRichText->InsertL( textStart, msg );
       
  2718 
       
  2719             // check for extensions (smileys)
       
  2720             TCursorSelection selection( iRichText->DocumentLength(),
       
  2721                                         textStart );
       
  2722             iExtensionsHandler.ConvertSelectionToExtensionL( *iRichText,
       
  2723                                                              selection );
       
  2724 
       
  2725             TInt textEnd( iRichText->DocumentLength() );
       
  2726 
       
  2727             // add nbs to preserve formatting
       
  2728             iRichText->InsertL( iRichText->DocumentLength(),
       
  2729                                 CEditableText::EZeroWidthNoBreakSpace );
       
  2730 
       
  2731             // if this is system message, it should be bold
       
  2732             if ( message.MessageType() == TEnumsPC::EMessageSystem )
       
  2733                 {
       
  2734                 TCursorSelection sel( textStart, textEnd );
       
  2735                 BoldL( sel );
       
  2736                 // System messages need different kind of alignment
       
  2737                 CParaFormat paraFormat;
       
  2738                 TParaFormatMask paraFormatMask;
       
  2739                 paraFormat.iLeftMarginInTwips = 0;
       
  2740                 paraFormatMask.SetAttrib( EAttLeftMargin );
       
  2741                 iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask,
       
  2742                                              textStart, sel.Length() );
       
  2743                 }
       
  2744             else
       
  2745                 {
       
  2746                 // Apply alignment for "normal" messages
       
  2747                 CParaFormat paraFormat;
       
  2748                 TParaFormatMask paraFormatMask;
       
  2749                 paraFormat.iLeftMarginInTwips = 100;
       
  2750                 paraFormatMask.SetAttrib( EAttLeftMargin );
       
  2751                 iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask,
       
  2752                                              textStart, textEnd - textStart );
       
  2753                 }
       
  2754 
       
  2755             // parse text for highlights and store positions to messagewrapper
       
  2756             HBufC* text = HBufC::NewMaxLC( textEnd - textStart );
       
  2757             TPtr txt( text->Des() );
       
  2758             iRichText->Extract( txt, textStart, textEnd - textStart );
       
  2759             ParseTextL( txt, textStart, textStart - aMsgStart, aMessageWrapper );
       
  2760             CleanupStack::PopAndDestroy( text );
       
  2761 
       
  2762             // Cleanup
       
  2763             if ( numberConv )
       
  2764                 {
       
  2765                 CleanupStack::PopAndDestroy( numberConv );
       
  2766                 }
       
  2767             if ( tempMsg )
       
  2768                 {
       
  2769                 CleanupStack::PopAndDestroy( tempMsg );
       
  2770                 }
       
  2771             break;
       
  2772             }
       
  2773         case TEnumsPC::EContentPicture: // Flowthrough
       
  2774         case TEnumsPC::EContentOther:
       
  2775             {
       
  2776             // insert thumbnail (if it's ready)
       
  2777             AddThumbL( iRichText->DocumentLength(), aMessageWrapper );
       
  2778             break;
       
  2779             }
       
  2780         case TEnumsPC::EContentInvalid:
       
  2781             {
       
  2782             break;
       
  2783             }
       
  2784         default:
       
  2785             {
       
  2786             // unsupported type
       
  2787             __CHAT_ASSERT_DEBUG( false );
       
  2788             break;
       
  2789             }
       
  2790         }
       
  2791     }
       
  2792 
       
  2793 // -----------------------------------------------------------------------------
       
  2794 // CCARichTextContainer::AddThumbL
       
  2795 // (other items were commented in a header).
       
  2796 // -----------------------------------------------------------------------------
       
  2797 //
       
  2798 void CCARichTextContainer::AddThumbL( TInt aPos,
       
  2799                                       CCAMessageWrapper& aMessageWrapper )
       
  2800     {
       
  2801     TCursorSelection& thumb = aMessageWrapper.ThumbPos();
       
  2802     thumb.iAnchorPos = aPos;
       
  2803     thumb.iCursorPos = aPos;
       
  2804 
       
  2805     MCAConversationMessage& message = aMessageWrapper.Message();
       
  2806     TEnumsPC::TContentType type = message.ContentType();
       
  2807     if ( type == TEnumsPC::EContentPicture ||
       
  2808          type == TEnumsPC::EContentOther )
       
  2809         {
       
  2810         // this is a content message
       
  2811         CFbsBitmap* bitmap = NULL;
       
  2812         CFbsBitmap* mask = NULL;
       
  2813         switch ( message.ContentProcessState() )
       
  2814             {
       
  2815             case TEnumsPC::EThumbnailReady:
       
  2816                 {
       
  2817                 // get the thumbnail from message
       
  2818                 bitmap = message.Thumbnail();
       
  2819                 break;
       
  2820                 }
       
  2821             case TEnumsPC::EContentNotSupported:
       
  2822                 {
       
  2823                 bitmap = iUnsupported->Bitmap();
       
  2824                 mask = iUnsupported->Mask();
       
  2825                 break;
       
  2826                 }
       
  2827             case TEnumsPC::EContentCorrupted:
       
  2828             case TEnumsPC::EContentNotSupportedDrm:
       
  2829                 {
       
  2830                 bitmap = iCorrupted->Bitmap();
       
  2831                 mask = iCorrupted->Mask();
       
  2832                 break;
       
  2833                 }
       
  2834             default:
       
  2835                 {
       
  2836                 // other types do not have thumbnails.
       
  2837                 return;
       
  2838                 }
       
  2839             }
       
  2840 
       
  2841         // create gulicon
       
  2842         CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
       
  2843         //we don`t own the bitmap, just the CGulIcon
       
  2844         icon->SetBitmapsOwnedExternally( ETrue );
       
  2845         CleanupStack::PushL( icon );
       
  2846 
       
  2847         // insert in to rich text
       
  2848         CCAPicture* pic = new( ELeave )CCAPicture( iMap, icon, KErrNotFound, EFalse );
       
  2849         CleanupStack::Pop( icon ); //ownership is taken by pic
       
  2850 
       
  2851         TSize thumbnailSize;
       
  2852         pic->GetOriginalSizeInTwips( thumbnailSize );
       
  2853 
       
  2854         CleanupStack::PushL( pic );
       
  2855         TPictureHeader header;
       
  2856         header.iPicture = TSwizzle<CPicture>( pic );
       
  2857         iRichText->CancelInsertCharFormat();    // to prevent ETEXT 31 panic
       
  2858 
       
  2859         // new paragraph, image and new paragraph
       
  2860         // 1 char for EParagraphDelimiter
       
  2861         // 1 char for picture
       
  2862         // 1 char for EZeroWidthNoBreakSpace
       
  2863         // 1 char for EParagraphDelimiter
       
  2864         TInt pos = aPos;
       
  2865         iRichText->InsertL( pos++, CEditableText::EParagraphDelimiter );
       
  2866         TInt picStart = pos;
       
  2867         CleanupStack::Pop( pic );
       
  2868         iRichText->InsertL( pos++, header ); // takes ownership
       
  2869         iRichText->InsertL( pos++, CEditableText::EZeroWidthNoBreakSpace );
       
  2870         TInt picEnd = pos;
       
  2871         iRichText->InsertL( pos++, CEditableText::EParagraphDelimiter );
       
  2872 
       
  2873         // store length
       
  2874         thumb.iCursorPos = pos;
       
  2875 
       
  2876         // update wrapper
       
  2877         TCursorSelection& sel = aMessageWrapper.Selection();
       
  2878         TCursorSelection& wholeSel = aMessageWrapper.WholeSelection();
       
  2879         sel.iCursorPos += thumb.Length();
       
  2880         wholeSel.iCursorPos += thumb.Length();
       
  2881 
       
  2882         // append formatting
       
  2883         CParaFormat paraFormat;
       
  2884         TParaFormatMask paraFormatMask;
       
  2885         paraFormat.iIndentInTwips = 0;
       
  2886         paraFormat.iLeftMarginInTwips = 100;
       
  2887         paraFormatMask.SetAttrib( EAttIndent );
       
  2888         paraFormatMask.SetAttrib( EAttLeftMargin );
       
  2889 
       
  2890         paraFormat.iLineSpacingInTwips = thumbnailSize.iHeight;
       
  2891         paraFormatMask.SetAttrib( EAttLineSpacing );
       
  2892 
       
  2893         // apply formatting to picture character only
       
  2894         iRichText->ApplyParaFormatL( &paraFormat, paraFormatMask, picStart,
       
  2895                                      picEnd - picStart );
       
  2896 
       
  2897         CHAT_DP( D_CHAT_LIT( "*Added thumbnail to %d-%d" ),
       
  2898                  thumb.iAnchorPos, thumb.iCursorPos );
       
  2899         }
       
  2900     }
       
  2901 // -----------------------------------------------------------------------------
       
  2902 // CCARichTextContainer::UpdateSkinnedTextColourL
       
  2903 // (other items were commented in a header).
       
  2904 // -----------------------------------------------------------------------------
       
  2905 //
       
  2906 void CCARichTextContainer::UpdateSkinnedTextColourL()
       
  2907     {
       
  2908     // Get current text's color
       
  2909     TRgb defaultSkinTextColor( KRgbBlack );
       
  2910     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
       
  2911                                defaultSkinTextColor,
       
  2912                                KAknsIIDQsnTextColors,
       
  2913                                EAknsCIQsnTextColorsCG6 );
       
  2914 
       
  2915     iDefaultMsgColor =  defaultSkinTextColor;
       
  2916     TCharFormat charFormat;
       
  2917     TCharFormatMask charFormatMask;
       
  2918     charFormat.iFontPresentation.iTextColor = defaultSkinTextColor;
       
  2919     charFormatMask.SetAttrib( EAttColor );
       
  2920 
       
  2921     // The color settings is read from the resource file only, so IntResourceValueFromRssL is used instead of IntResourceValueL
       
  2922     TBool defaultColors = IMUtils::IntResourceValueFromRssL(
       
  2923                               RSC_CHAT_DEFAULT_MESSAGE_COLORS );
       
  2924 
       
  2925     // Update text colour in all messages
       
  2926     TInt messagecount = iMessages.Count();
       
  2927     for ( TInt i = 0; i < messagecount; ++i )
       
  2928         {
       
  2929         MCAConversationMessage &msg = iMessages[ i ]->Message();
       
  2930         TCursorSelection sel( 0, 0 );
       
  2931 
       
  2932         // system message use always default color
       
  2933         if ( msg.MessageType() == TEnumsPC::EMessageSystem )
       
  2934             {
       
  2935             sel = iMessages[ i ]->WholeSelection();
       
  2936             }
       
  2937         // Sent messages
       
  2938         else if ( msg.MessagerType() == TEnumsPC::EMessageSent )
       
  2939             {
       
  2940             sel = SkinColoredSelection( *iMessages[ i ],
       
  2941                                         defaultColors,
       
  2942                                         iOwnMsgColorInUse );
       
  2943             }
       
  2944         // Received messages
       
  2945         else if ( msg.MessagerType() == TEnumsPC::EMessageReceived )
       
  2946             {
       
  2947             sel = SkinColoredSelection( *iMessages[ i ],
       
  2948                                         defaultColors,
       
  2949                                         iMsgColorInUse );
       
  2950             }
       
  2951 
       
  2952         // Only update texts which use default color.
       
  2953         if ( sel.Length() > 0 )
       
  2954             {
       
  2955             iRichText->ApplyCharFormatL( charFormat,
       
  2956                                          charFormatMask,
       
  2957                                          sel.LowerPos(),
       
  2958                                          sel.Length() );
       
  2959             }
       
  2960         }
       
  2961     // also appended messages should have new colour
       
  2962     iRichText->SetInsertCharFormatL( charFormat, charFormatMask, iRichText->DocumentLength() );
       
  2963     }
       
  2964 
       
  2965 // -----------------------------------------------------------------------------
       
  2966 // CCARichTextContainer::SkinColoredSelection
       
  2967 // (other items were commented in a header).
       
  2968 // -----------------------------------------------------------------------------
       
  2969 //
       
  2970 TCursorSelection CCARichTextContainer::SkinColoredSelection(
       
  2971     CCAMessageWrapper& aMessageWrapper,
       
  2972     TBool aUseDefaultColors,
       
  2973     TBool aCustomDefinedColor )
       
  2974     {
       
  2975     // This logic determines which part of the message is colored by the theme
       
  2976     if ( !aCustomDefinedColor && aUseDefaultColors )
       
  2977         {
       
  2978         return aMessageWrapper.WholeSelection();
       
  2979         }
       
  2980 
       
  2981     if ( !iColorWholeMessage )
       
  2982         {
       
  2983         return aMessageWrapper.MessageSelection();
       
  2984         }
       
  2985 
       
  2986     return TCursorSelection( 0, 0 );
       
  2987     }
       
  2988 
       
  2989 // -----------------------------------------------------------------------------
       
  2990 // CCARichTextContainer::ReplaceParaDelimsWithLineBreaks
       
  2991 // (other items were commented in a header).
       
  2992 // -----------------------------------------------------------------------------
       
  2993 //
       
  2994 void CCARichTextContainer::ReplaceParaDelimsWithLineBreaks(
       
  2995     const TPtrC& aSource,
       
  2996     TPtr& aTarget ) const
       
  2997     {
       
  2998 #ifdef _DEBUG
       
  2999     TPtrC target;
       
  3000     target.Set( aTarget );
       
  3001     CHAT_DP( D_PLAIN_LIT( "CCARichTextContainer::ReplaceParaDelimsWithLineBreaks: target =  %S" ), &target );
       
  3002 #endif
       
  3003 
       
  3004     TInt paraBreak = aSource.Mid( aTarget.Length() ).Locate(
       
  3005                          CEditableText::EParagraphDelimiter );
       
  3006 
       
  3007     if ( paraBreak == KErrNotFound )
       
  3008         {
       
  3009         // No more paragraph delimiters, append what's left
       
  3010         aTarget.Append( aSource.Mid( aTarget.Length() ) );
       
  3011         // And break away from recursion
       
  3012         return;
       
  3013         }
       
  3014 
       
  3015     aTarget.Append( aSource.Mid( aTarget.Length(), paraBreak ) );
       
  3016     aTarget.Append( CEditableText::ELineBreak );
       
  3017 
       
  3018 #ifdef _DEBUG
       
  3019     target.Set( aTarget );
       
  3020     CHAT_DP( D_PLAIN_LIT( "CCARichTextContainer::ReplaceParaDelimsWithLineBreaks: target =  %S" ), &target );
       
  3021 #endif
       
  3022 
       
  3023     ReplaceParaDelimsWithLineBreaks( aSource, aTarget );
       
  3024     }
       
  3025 
       
  3026 
       
  3027 // -----------------------------------------------------------------------------
       
  3028 // CCARichTextContainer::GetMessageCount
       
  3029 // (other items were commented in a header).
       
  3030 // -----------------------------------------------------------------------------
       
  3031 //
       
  3032 TInt CCARichTextContainer::GetMessageCount()
       
  3033     {
       
  3034     return iMessages.Count();
       
  3035     }
       
  3036 // -----------------------------------------------------------------------------
       
  3037 // CCARichTextContainer::GetMessageCount
       
  3038 // (other items were commented in a header).
       
  3039 // -----------------------------------------------------------------------------
       
  3040 //
       
  3041 void CCARichTextContainer::ChangeHighlightColorL()
       
  3042     {
       
  3043     // get the selection
       
  3044     TCursorSelection curSel( CurrentSelection() );
       
  3045 
       
  3046     // remove colors from old highlight
       
  3047     TInt textLen( iRichText->DocumentLength() );
       
  3048     if ( iPrevious.iAnchorPos < textLen &&
       
  3049          iPrevious.iCursorPos <= textLen )
       
  3050         {
       
  3051         BackColorL( iPrevious, KRgbWhite );
       
  3052         TextBackColorL( iPrevious, KRgbWhite );
       
  3053         }
       
  3054 
       
  3055     // and set new one
       
  3056     if ( iHighlightState == EItemSelected )
       
  3057         {
       
  3058         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
  3059         TRgb color;
       
  3060 
       
  3061         TInt error = AknsUtils::GetCachedColor( skin,
       
  3062                                                 color,
       
  3063                                                 KAknsIIDQsnHighlightColors,
       
  3064                                                 EAknsCIQsnHighlightColorsCG2 );
       
  3065 
       
  3066         if ( !error )
       
  3067             {
       
  3068             // No error, use skinned background color
       
  3069             TextBackColorL( curSel, color );
       
  3070             }
       
  3071         else
       
  3072             {
       
  3073             TextBackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
  3074             }
       
  3075         }
       
  3076     else
       
  3077         {
       
  3078         MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
  3079         TRgb color;
       
  3080 
       
  3081         TInt error = AknsUtils::GetCachedColor( skin,
       
  3082                                                 color,
       
  3083                                                 KAknsIIDQsnHighlightColors,
       
  3084                                                 EAknsCIQsnHighlightColorsCG2 );
       
  3085 
       
  3086         if ( !error )
       
  3087             {
       
  3088             // No error, use skinned background color
       
  3089             BackColorL( curSel, color );
       
  3090             }
       
  3091         else
       
  3092             {
       
  3093             BackColorL( curSel, AKN_LAF_COLOR_STATIC( KChatHighlightColor ) );
       
  3094             }
       
  3095         }
       
  3096 
       
  3097     // handle changed format
       
  3098     TCursorSelection changed( Union( iPrevious, curSel ) );
       
  3099 
       
  3100     iTextView.HandleFormatChangedL( changed );
       
  3101 
       
  3102     iTextView.ScrollVisibleL( curSel, ETrue );
       
  3103 
       
  3104     iPrevious = curSel;
       
  3105     }
       
  3106 
       
  3107 // -----------------------------------------------------------------------------
       
  3108 // CCARichTextContainer::UnRegisterRichTxtCtrlObserver
       
  3109 // (other items were commented in a header).
       
  3110 // -----------------------------------------------------------------------------
       
  3111 //
       
  3112 void CCARichTextContainer::UnRegisterRichTxtCtrlObserver()
       
  3113     {
       
  3114     iAddMsgObserver = NULL;
       
  3115     }
       
  3116 
       
  3117 //  End of File