--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneuis/easydialing/src/easydialinglistboxdata.cpp Fri Feb 19 22:50:26 2010 +0200
@@ -0,0 +1,1319 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Easy dialing list box data.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "easydialinglistboxdata.h"
+#include "easydialinglistbox.h"
+#include "easydialinglistboxview.h"
+#include "easydialinglistboxitemdrawer.h"
+#include "easydialingpanics.h"
+
+#include "easydialingcontactdatamanager.h"
+#include <easydialing.mbg>
+#include <phonebook2.mbg>
+#include <phonebook2ece.mbg>
+
+// AvKON and drawing header files
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <akniconconfig.h>
+#include <gulicon.h>
+#include <AknBidiTextUtils.h>
+#include <bidivisual.h>
+
+#include <aknlistloadertfx.h>
+#include <aknlistboxtfxinternal.h>
+#include <aknlistboxtfx.h>
+
+#include <akntransitionutils.h>
+#include <avkon.rsg>
+
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// KHighlightSeparatorChar is character used to separate matching and non-matching
+// portions of contact names.
+const TInt KHighlightSeparatorChar = 0x1F;
+_LIT( KHighlightSeparatorCharAsLit, "\x1F" );
+
+
+// KContactNameFontHeightPercent is contact name font height relative to list item height.
+const TInt KContactNameFontHeightPercent = 35;
+
+// KCompanyNameFontHeightPercent is company name font height relative to list item height.
+const TInt KCompanyNameFontHeightPercent = 30;
+
+// KTextBoundingBoxHeightPercent gives the text bounding box height in percentages
+// relative to font height. This must be over 100, or part of the text cuts off.
+const TInt KTextBoundingBoxHeightPercent = 120;
+
+// KTextPlacementPercent controls how text is placed vertically within its bounding box.
+// The value is between 0 and 100. 0 means in top part, 50 mean in the middle, 100 means in the
+// bottom.
+const TInt KTextPlacementPercent = 70;
+
+// KMarginXPercent defines a width of horizontal margin used in many places. In relation to
+// the width of the item rectangle.
+const TInt KMarginXPercent = 2;
+
+// KMarginYPercent defines a height of vertical margin. In relation to
+// the height of the item rectangle. Currently used only with contact thumbnail.
+const TInt KMarginYPercent = 4;
+
+// KContacNameYOffsetPercent defines the vertical placement of contact name in relation to
+// item height.
+const TInt KContactNameYOffsetPercent = 10;
+
+// KCompanyNameYOffsetPercent defines the vertical placement of company name in relation to
+// item height.
+const TInt KCompanyNameYOffsetPercent = 60;
+
+// KArrowIconSizePercent defines the size of action menu icon relative to item height.
+const TInt KArrowIconSizePercent = 20;
+
+// KMatchingTextMarginInPixels the absolute pixel width of highlight margin. Highlight margin
+// is an extra space in highlight boundary to make the text look less crowded.
+const TInt KMatchingTextMarginInPixels = 3;
+
+// KMatchingTextMarginInPixels is the absolute pixel value for rounding used in highlight
+// rectangle.
+const TInt KHighligthRectangleRoundingYInPixels = 4;
+
+// KThumbnailAspectRatio is the aspect ratio of contact thumbnail in percents. 133 for instance
+// is 4:3 aspect ration.
+const TInt KThumbnailAspectRatio = 133;
+
+const TInt KCent = 100;
+
+const TInt KMaxRunInfoArrayCount = 20;
+
+// IMPLEMENTATION SPECIFIC CONSTANTS
+// The mif file from where you would like to show the
+// icon on the screen.
+_LIT( KFavouriteIconBitmapFile, "\\resource\\apps\\phonebook2.mif" );
+_LIT( KEasyDialingBitmapFile, "\\resource\\apps\\easydialing.mif" );
+_LIT( KPhonebook2EceBitmapFile, "\\resource\\apps\\phonebook2ece.mif" );
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// GLOBAL FUNCTION PROTOTYPES
+TRect ContactImageBoundingBox( const TRect& aItemRect );
+TRect ArrowIconBoundingBox(const TRect& aItemRect);
+
+// LOCAL FUNCTION PROTOTYPES
+static TRect ContactNameBoundingBox(
+ const TRect& aItemRect,
+ const CFont* aContactNameFont,
+ TBool aIsCurrentItem,
+ TBool aIsFavourite,
+ TBool aThumbnailsShown );
+static TRect CompanyNameBoundingBox(
+ const TRect& aItemRect,
+ const CFont* aCompanyNameFont,
+ TBool aIsCurrentItem,
+ TBool aThumbnailsShown );
+static TRect FavouriteIconBoundingBox( const TRect& aContactNameBoundingBox, TInt aTextWidth );
+static TRect MirrorLayoutBoundingBox(const TRect& aSourceRect, TRect& aBoundingBoxRect);
+static TInt BaseLineOffset( const TRect& aTextBoundingBox, const CFont* aFont );
+static TBool ContainsRightToLeftText( const TDesC& aDesc );
+static TInt HighlightSeparatorCount( const TDesC& aText );
+static HBufC* ConvertToVisualAndClipLC( const TDesC& aText, const CFont& aFont, const TRect& aBoundingBox );
+
+static void ClipTextToWidth(
+ TDes& aText,
+ const CFont& aFont,
+ TInt aMaxWidthInPixels,
+ TBool& aMatch );
+
+static TBool DrawPieceOfText(
+ const TRect& aBoundingBox,
+ TInt& aXOffset,
+ CWindowGc &aGc,
+ const TDesC& aText,
+ TBool aMatch,
+ const CFont* aFont,
+ const CEasyDialingListBoxData::TExtendedColors& aColors,
+ TBool aHighLight);
+
+static TInt DrawTextWithMatchHighlightL(
+ const TRect& aBoundingBox,
+ CWindowGc &aGc,
+ const TDesC& aText,
+ const CFont* aFont,
+ const CEasyDialingListBoxData::TExtendedColors& aColors,
+ TBool aHighLight );
+
+static TInt CalculateTextWidth(
+ const TRect& aBoundingBox,
+ const TDesC& aText,
+ const CFont* aFont );
+
+static TBool CalculateTextPieceWidth(
+ const TRect& aBoundingBox,
+ TInt& aXOffset,
+ const TDesC& aText,
+ TBool aMatch,
+ const CFont* aFont );
+
+// FORWARD DECLARATIONS
+
+
+/*
+ * ==============================================================================
+ *
+ *
+ * class EasyDialingListBoxData::TExtendedColors
+ *
+ *
+ * ==============================================================================
+ */
+
+
+// -----------------------------------------------------------------------------
+// TExtendedColors
+//
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBoxData::TExtendedColors::TExtendedColors() :
+CFormattedCellListBoxData::TColors(),
+iMatchingText(KRgbBlack),
+iMatchingBack(KRgbDarkYellow)
+ {
+ }
+
+
+/*
+ * ==============================================================================
+ *
+ *
+ * class CEasyDialingListBoxData
+ *
+ *
+ * ==============================================================================
+ */
+
+
+// -----------------------------------------------------------------------------
+// CEasyDialingListBoxData
+//
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBoxData::CEasyDialingListBoxData() :
+CFormattedCellListBoxData()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+//
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBoxData::~CEasyDialingListBoxData()
+ {
+ // Release fonts. ReleaseFont function can cope with null pointer
+ // so we don't need to null check them.
+ CWsScreenDevice& screenDev = *( CEikonEnv::Static()->ScreenDevice() );
+ screenDev.ReleaseFont( iContactNameFont );
+ screenDev.ReleaseFont( iCompanyNameFont );
+
+ delete iArrowPointingRight;
+ delete iArrowPointingLeft;
+ delete iColorBitmap;
+ delete iDummyThumbnail;
+
+ iContactDataManager = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// NewL
+//
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBoxData* CEasyDialingListBoxData::NewL()
+ {
+ CEasyDialingListBoxData* self = new (ELeave) CEasyDialingListBoxData();
+
+ CleanupStack::PushL( self );
+ self->ConstructLD();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawData
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::DrawData(
+ const TListItemProperties& aProperties,
+ CWindowGc& aGc,
+ const TDesC* aText,
+ const TRect& aRect,
+ TBool aHighlight,
+ const TExtendedColors& aColors ) const
+ {
+ const TRect &aItemRect = aRect;
+
+ if ( aHighlight )
+ {
+ DrawHighlight( aGc, aItemRect );
+ }
+
+ // Draw the actual items.
+ DrawDataFormatted( aProperties, aGc, aText, aItemRect,
+ aHighlight, aColors );
+ }
+
+
+// -----------------------------------------------------------------------------
+// ConstructLD
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::ConstructLD()
+ {
+ CFormattedCellListBoxData::ConstructLD();
+
+ // EasyDialing bitmap file is attempted to be read from the same directory where the
+ // executed binary is located
+ TFileName dllFileName;
+ Dll::FileName( dllFileName );
+
+ TParse parse;
+ User::LeaveIfError(parse.Set(KEasyDialingBitmapFile, &dllFileName, NULL));
+ TFileName bitmapFileName(parse.FullName());
+
+ CFbsBitmap* bm;
+ CFbsBitmap* mask;
+
+ // iArrowPointingLeft is the icon displayed for the selected item in EasyDialingListBox
+ AknIconUtils::CreateIconL( bm, mask, bitmapFileName, EMbmEasydialingQgn_indi_org_arrow_left,
+ EMbmEasydialingQgn_indi_org_arrow_left_mask );
+
+ iArrowPointingLeft = CGulIcon::NewL( bm, mask );
+
+ AknIconUtils::CreateIconL( bm, mask, bitmapFileName, EMbmEasydialingQgn_indi_org_arrow_right,
+ EMbmEasydialingQgn_indi_org_arrow_right_mask );
+
+ iArrowPointingRight = CGulIcon::NewL( bm, mask );
+
+ // Only mask for the icons are used. iColorBitmap is used for making the icon
+ // to follow text color changes according to skin.
+ iColorBitmap = new (ELeave) CFbsBitmap;
+
+ // Contact default thumbnail is not available in themes. It is read from phonebook resource.
+ AknIconUtils::CreateIconL( bm, mask, KPhonebook2EceBitmapFile,
+ EMbmPhonebook2eceQgn_prop_pb_thumb_unknown, EMbmPhonebook2eceQgn_prop_pb_thumb_unknown_mask );
+ iDummyThumbnail = CGulIcon::NewL( bm, mask );
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawHighlight
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::DrawHighlight( CWindowGc &aGc, const TRect &aItemRect ) const
+ {
+ MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( &aGc );
+ if ( transApi )
+ {
+ transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight );
+ transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aItemRect );
+ transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
+ aGc.SetClippingRect( iControl->Rect() );
+ }
+
+ TAknLayoutRect outerRect;
+ TAknLayoutRect innerRect;
+ outerRect.LayoutRect( aItemRect, TAknWindowComponentLayout::Compose(
+ AknLayoutScalable_Avkon::list_highlight_pane_cp1(),
+ AknLayoutScalable_Avkon::list_highlight_pane_g10_cp1() ).LayoutLine() );
+ innerRect.LayoutRect( aItemRect, TAknWindowComponentLayout::Compose(
+ AknLayoutScalable_Avkon::list_highlight_pane_cp1(),
+ AknLayoutScalable_Avkon::list_highlight_pane_g1_cp1() ).LayoutLine() );
+ MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() );
+
+ if ( !cc )
+ {
+ cc = SkinBackgroundContext();
+ }
+
+ if ( cc )
+ {
+ aGc.SetPenStyle( CGraphicsContext::ENullPen );
+ AknsDrawUtils::DrawFrame(
+ AknsUtils::SkinInstance(),
+ aGc,
+ outerRect.Rect(),
+ innerRect.Rect(),
+ KAknsIIDQsnFrList,
+ KAknsIIDQsnFrListCenter );
+ }
+
+ if ( transApi )
+ {
+ aGc.CancelClippingRect();
+ transApi->StopDrawing();
+ transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawDataFormatted
+//
+// -----------------------------------------------------------------------------
+//
+// ToDo: SetSize function could be called once for all static data in SizeChanged.
+// Applies at least to icons.
+void CEasyDialingListBoxData::DrawDataFormatted(
+ TListItemProperties /* aProperties */,
+ CWindowGc& aGc,
+ const TDesC* aText,
+ const TRect& aItemRect,
+ TBool aHighlight,
+ const TExtendedColors& aColors ) const
+ {
+ TPtrC cellText;
+
+ TInt error = TextUtils::ColumnText( cellText , 0, aText );
+ __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
+ __ASSERT_DEBUG( iContactNameFont, EasyDialingPanic( EEasyDialingNoFontFound ) );
+ __ASSERT_DEBUG( iCompanyNameFont, EasyDialingPanic( EEasyDialingNoFontFound ) );
+
+ MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( &aGc );
+ if ( transApi )
+ {
+ transApi->StartDrawing( MAknListBoxTfxInternal::EListItem );
+ if ( transApi->EffectsDisabled() )
+ {
+ aGc.SetClippingRect( iControl->Rect() );
+ }
+ }
+
+ TRect boundingBox = ContactImageBoundingBox( aItemRect );
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ boundingBox = MirrorLayoutBoundingBox( aItemRect, boundingBox );
+ }
+
+ //Draws the Contact Thumbnail Icon if exists else draws the dummy contact thumbnail
+ TBool fav = ContactThumbnailDrawing( aGc, boundingBox, cellText );
+
+ error = TextUtils::ColumnText( cellText , 1, aText );
+ __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
+
+ boundingBox = ContactNameBoundingBox( aItemRect,
+ iContactNameFont,
+ aHighlight,
+ fav,
+ iContactDataManager->GetContactThumbnailSetting() );
+ TRect nameRectUnMirrored = boundingBox; // used for favourite star drawing
+
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ boundingBox = MirrorLayoutBoundingBox( aItemRect, boundingBox );
+ }
+
+ // favourite icon size is set the same as contact name bounding box height.
+ TInt favouriteIconSize = boundingBox.Height();
+
+ TRect arrowRect = ArrowIconBoundingBox( aItemRect );
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ arrowRect = MirrorLayoutBoundingBox( aItemRect, arrowRect );
+ }
+
+ // Draw arrow icon if the item is in focus.
+ if ( aHighlight )
+ {
+ DrawArrowIcon( aGc, arrowRect );
+ }
+
+ TInt textWidth( 0 );
+ TInt err( KErrNone );
+ TRAP( err, textWidth = DrawTextWithMatchHighlightL(
+ boundingBox, aGc, cellText, iContactNameFont, aColors, aHighlight ) );
+
+ if ( !err && TextUtils::ColumnText( cellText , 2, aText ) == KErrNone )
+ {
+ TRect companyNameBoundingBox = CompanyNameBoundingBox(
+ aItemRect, iCompanyNameFont, aHighlight, iContactDataManager->GetContactThumbnailSetting() );
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ companyNameBoundingBox = MirrorLayoutBoundingBox( aItemRect, companyNameBoundingBox );
+ }
+ TRAP( err, DrawTextWithMatchHighlightL(
+ companyNameBoundingBox, aGc, cellText, iCompanyNameFont, aColors, aHighlight ) );
+ }
+
+ if ( !err && fav )
+ {
+ // Draws the Favourite Icon
+ DrawFavouriteIcon( aGc, nameRectUnMirrored, textWidth, aItemRect );
+ }
+
+ if ( transApi )
+ {
+ aGc.CancelClippingRect();
+ transApi->StopDrawing();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// ContactThumbnailDrawing
+//
+// Draws the Contact Thumbnail Icon if any else draws the dummy contact thumbnail
+// -----------------------------------------------------------------------------
+
+TBool CEasyDialingListBoxData::ContactThumbnailDrawing(CWindowGc& aGc, TRect aBoundingBox, TPtrC aCellText) const
+ {
+ TBool fav(EFalse);
+ CFbsBitmap* thumbnail(NULL);
+ TBool isLoaded = iContactDataManager->GetThumbnailAndFav(aCellText, thumbnail, fav);
+ if ( isLoaded && thumbnail )
+ {
+ // center the thumbnail in its rect
+ TSize size(thumbnail->SizeInPixels());
+ TInt xOffset = (aBoundingBox.Width() - size.iWidth) / 2;
+ TInt yOffset = (aBoundingBox.Height() - size.iHeight) / 2;
+ TPoint tl(aBoundingBox.iTl.iX + xOffset, aBoundingBox.iTl.iY + yOffset);
+ TRect sourceRect( TPoint(0,0),size);
+ aGc.BitBlt(tl, thumbnail, sourceRect);
+ }
+ else if ( isLoaded && iContactDataManager->GetContactThumbnailSetting() )
+ {
+ // draw dummy thumnbnail, but only if we know that the contact doesn't
+ // have a thumbnail, and thumbnail drawing is enabled.
+ AknIconUtils::SetSize(iDummyThumbnail->Bitmap(), aBoundingBox.Size());
+ AknIconUtils::SetSize(iDummyThumbnail->Mask(), aBoundingBox.Size());
+ aGc.BitBltMasked( aBoundingBox.iTl, iDummyThumbnail->Bitmap(),
+ TRect( TPoint(0,0), aBoundingBox.Size() ),
+ iDummyThumbnail->Mask(), ETrue );
+ }
+ return fav;
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawArrowIcon
+// Draws the Action Menu
+// -----------------------------------------------------------------------------
+void CEasyDialingListBoxData::DrawArrowIcon(
+ CWindowGc& aGc, TRect aArrowRect) const
+ {
+ // Action Menu Arrow for opening the Action Menu
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ // For mirrored layout the UI logic is mirrored as well
+ AknIconUtils::SetSize( iArrowPointingLeft->Mask(), aArrowRect.Size() );
+ aGc.BitBltMasked( aArrowRect.iTl, iColorBitmap,
+ TRect( TPoint(0,0), aArrowRect.Size() ),
+ iArrowPointingLeft->Mask(), ETrue );
+
+ }
+ else
+ {
+ AknIconUtils::SetSize( iArrowPointingRight->Mask(), aArrowRect.Size() );
+ aGc.BitBltMasked( aArrowRect.iTl, iColorBitmap,
+ TRect( TPoint(0,0), aArrowRect.Size() ),
+ iArrowPointingRight->Mask(), ETrue );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// DrawFavouriteIcon
+//
+// Draws the Favourite Icon
+// -----------------------------------------------------------------------------
+void CEasyDialingListBoxData::DrawFavouriteIcon(
+ CWindowGc& aGc,
+ TRect aNameRectUnMirrored,
+ TInt aTextWidth,
+ TRect aEffectiveRect) const
+ {
+ CFbsBitmap* favouriteIcon;
+ CFbsBitmap* favouriteIconMask;
+ TRect favouriteIconBoundingBox;
+
+ favouriteIconBoundingBox = FavouriteIconBoundingBox( aNameRectUnMirrored, aTextWidth );
+
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ favouriteIconBoundingBox = MirrorLayoutBoundingBox(aEffectiveRect, favouriteIconBoundingBox);
+ }
+
+ aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
+ TRect sourceRect( TPoint(0,0), favouriteIconBoundingBox.Size() );
+
+ if( AknsUtils::SkinInstance()->GetCachedItemData(KAknsIIDQgnFsContactsFavorite) )
+ {
+ AknsDrawUtils::DrawCachedImage( AknsUtils::SkinInstance(), aGc, sourceRect,
+ KAknsIIDQgnFsContactsFavorite );
+ }
+ else
+ {
+ // Create the bitmap and mask to draw.
+ TRAP_IGNORE( AknIconUtils::CreateIconL(favouriteIcon, favouriteIconMask, KFavouriteIconBitmapFile,
+ EMbmPhonebook2Qgn_prop_pb_topc, EMbmPhonebook2Qgn_prop_pb_topc_mask ));
+
+ // Set size for the bitmap and mask
+ AknIconUtils::SetSize(favouriteIcon, favouriteIconBoundingBox.Size());
+ AknIconUtils::SetSize(favouriteIconMask, favouriteIconBoundingBox.Size());
+ aGc.BitBltMasked( favouriteIconBoundingBox.iTl , favouriteIcon, sourceRect, favouriteIconMask, ETrue);
+ }
+ }
+// -----------------------------------------------------------------------------
+// SetContactDataManager
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::SetContactDataManager(CEasyDialingContactDataManager* aContactDataManager)
+ {
+ iContactDataManager = aContactDataManager;
+ }
+
+// -----------------------------------------------------------------------------
+// HandleItemSizeChange
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::HandleItemSizeChange()
+ {
+ TInt height = iControl->ItemHeight();
+ TSize size( height, height );
+ TRAP_IGNORE( UpdateColorBitmapL( size ) );
+
+ // Obtain fonts.
+ ObtainFonts( height );
+
+ // TODO: also bounding boxes could be updated and stored here
+ }
+
+// -----------------------------------------------------------------------------
+// ObtainFonts
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::ObtainFonts( TInt aItemHeight )
+ {
+ CWsScreenDevice& screenDev = *( CEikonEnv::Static()->ScreenDevice() );
+
+ // Release previous fonts. ReleaseFont function can cope with null pointers
+ // so we don't need to null check them.
+ screenDev.ReleaseFont( iContactNameFont );
+ screenDev.ReleaseFont( iCompanyNameFont );
+
+ // Get a logical font to a basis for our own fonts.
+ const CFont* logicalFont = AknLayoutUtils::FontFromId( EAknLogicalFontSecondaryFont );
+
+ // Extract font information
+ TFontSpec fontSpec = logicalFont->FontSpecInTwips();
+
+ // Calculate contact name font height in TWIPs.
+ TInt fontHeightPixels = aItemHeight * KContactNameFontHeightPercent / KCent;
+ TInt fontHeightTwips = screenDev.VerticalPixelsToTwips( fontHeightPixels );
+
+ // Set height, weight, and posture.
+ fontSpec.iHeight = fontHeightTwips;
+ fontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
+ fontSpec.iFontStyle.SetPosture( EPostureUpright );
+
+ // Obtain contact name font
+ TInt err = screenDev.GetNearestFontToDesignHeightInTwips( iContactNameFont, fontSpec );
+ __ASSERT_DEBUG( err == KErrNone, EasyDialingPanic( EEasyDialingNoFontFound ) );
+
+ // Calculate company name font height in TWIPs.
+ fontHeightPixels = aItemHeight * KCompanyNameFontHeightPercent / KCent;
+ fontHeightTwips = screenDev.VerticalPixelsToTwips( fontHeightPixels );
+ fontSpec.iHeight = fontHeightTwips;
+ fontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
+
+ // Obtain company name font.
+ err = screenDev.GetNearestFontToDesignHeightInTwips( iCompanyNameFont, fontSpec );
+ __ASSERT_DEBUG( err == KErrNone, EasyDialingPanic( EEasyDialingNoFontFound ) );
+ }
+
+
+// -----------------------------------------------------------------------------
+// UpdateColorBitmapL
+// ColorBitmap is redrawn when UI layout or text color (Theme) changes
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::UpdateColorBitmapL( const TSize& aSize )
+ {
+ TRgb color;
+ // Get the HighLighted text color in ListBox from the Theme
+ AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color,
+ KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10 );
+
+ // Create a bitmap with the similar display mode than what the device currently
+ // uses for using it as an offscreen bitmap
+ AknIconConfig::TPreferredDisplayMode mode;
+ AknIconConfig::PreferredDisplayMode( mode, AknIconConfig::EImageTypeOffscreen );
+ User::LeaveIfError( iColorBitmap->Create( aSize, mode.iBitmapMode ) );
+
+ // Create a new drawing device and graphics context for enabling drawing to
+ // the offscreen bitmap
+ CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( iColorBitmap );
+ CleanupStack::PushL(destinationDevice);
+
+ CFbsBitGc* destinationGc;
+ User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+
+ // Set the color and style for pen and brush and draw a rectangle to the
+ // bitmap graphics
+ destinationGc->SetPenColor( color );
+ destinationGc->SetPenStyle( CGraphicsContext::ESolidPen );
+ destinationGc->SetBrushColor( color );
+ destinationGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+ destinationGc->DrawRect( TRect( TPoint( 0,0 ), aSize ) );
+
+ // Colorbitmap is ready, cleanup
+ delete destinationGc;
+ CleanupStack::PopAndDestroy(destinationDevice);
+ }
+
+// -----------------------------------------------------------------------------
+// SetEDLBXControl
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBoxData::SetEDLBXControl(CEasyDialingListBox* aControl)
+ {
+ iControl = aControl;
+ }
+
+
+/*
+ * ==============================================================================
+ *
+ * Local functions
+ *
+ * ==============================================================================
+ */
+
+
+// -----------------------------------------------------------------------------
+// ContactImageBoundingBox
+// Calculates the area where contact thumbnail is confined
+// -----------------------------------------------------------------------------
+//
+TRect ContactImageBoundingBox(const TRect& aItemRect)
+ {
+ TInt leftMargin = aItemRect.Width() * KMarginXPercent / KCent;
+ TInt topMargin = KMarginYPercent * aItemRect.Height() / KCent;
+ TInt bottomMargin = topMargin;
+ TInt width = ((aItemRect.Height() - topMargin - bottomMargin) * KThumbnailAspectRatio) / KCent;
+
+ return TRect(
+ aItemRect.iTl.iX + leftMargin,
+ aItemRect.iTl.iY + topMargin,
+ aItemRect.iTl.iX + leftMargin + width,
+ aItemRect.iBr.iY - bottomMargin);
+ }
+
+// -----------------------------------------------------------------------------
+// ContactNameBoundingBox
+// Calculates the area to which the contact name and possible match highlights
+// are confined.
+//
+// -----------------------------------------------------------------------------
+//
+static TRect ContactNameBoundingBox(
+ const TRect& aItemRect,
+ const CFont* aContactNameFont,
+ TBool aIsCurrentItem,
+ TBool aIsFavourite,
+ TBool aThumbnailsShown )
+ {
+ // Position X will contain the starting position of text from left side of item rect.
+ TInt positionX = aItemRect.Width() * KMarginXPercent / KCent;
+
+ if (aThumbnailsShown)
+ {
+ // If contact image is shown, text starts from right side of contact picture + margin.
+ TRect contactImageBoundingBox = ContactImageBoundingBox( aItemRect );
+ positionX += contactImageBoundingBox.Width();
+ positionX += aItemRect.Width() * KMarginXPercent / KCent;
+ }
+
+ TInt topMargin = KContactNameYOffsetPercent * aItemRect.Height() / KCent;
+ TInt height = KTextBoundingBoxHeightPercent * aContactNameFont->FontMaxHeight() / KCent;
+ TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
+
+ // Reserve space for communication launcher icon.
+ // Communication launcher icon is shown only id item is highlighted.
+ if ( aIsCurrentItem )
+ {
+ rightMargin += KArrowIconSizePercent * aItemRect.Height() / KCent;
+ }
+
+ // If item is favourite, reserve space for favourite icon. Icon dimensions are the same as bounding box height.
+ if ( aIsFavourite )
+ {
+ rightMargin += height;
+ }
+
+ return TRect(
+ aItemRect.iTl.iX + positionX,
+ aItemRect.iTl.iY + topMargin,
+ aItemRect.iTl.iX + aItemRect.Width() - rightMargin,
+ aItemRect.iTl.iY + topMargin + height);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CompanyNameBoundingBox
+// Calculates the area to which the company name and possible match highlights
+// are confined.
+// -----------------------------------------------------------------------------
+//
+static TRect CompanyNameBoundingBox(
+ const TRect& aItemRect,
+ const CFont* aCompanyNameFont,
+ TBool aIsCurrentItem,
+ TBool aThumbnailsShown )
+ {
+ // Position X will contain the starting position of text from left side of item rect.
+ TInt positionX = aItemRect.Width() * KMarginXPercent / KCent;
+
+ if (aThumbnailsShown)
+ {
+ // If contact image is show, text starts from right side of contact picture + margin.
+ TRect contactImageBoundingBox = ContactImageBoundingBox( aItemRect );
+ positionX += contactImageBoundingBox.Width();
+ positionX += aItemRect.Width() * KMarginXPercent / KCent;
+ }
+
+ TInt topMargin = KCompanyNameYOffsetPercent * aItemRect.Height() / KCent;
+ TInt height = KTextBoundingBoxHeightPercent * aCompanyNameFont->FontMaxHeight() / KCent;
+ TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
+
+ // Reserve space for communication launcher icon.
+ // Communication launcher icon is shown only id item is highlighted.
+ if ( aIsCurrentItem )
+ {
+ rightMargin += KArrowIconSizePercent * aItemRect.Height() / KCent;
+ }
+
+ return TRect(
+ aItemRect.iTl.iX + positionX,
+ aItemRect.iTl.iY + topMargin,
+ aItemRect.iTl.iX + aItemRect.Width() - rightMargin,
+ aItemRect.iTl.iY + topMargin + height);
+ }
+
+
+// -----------------------------------------------------------------------------
+// ArrowIconBoundingBox
+// Calculates the area to which the action menu icon is drawn.
+// -----------------------------------------------------------------------------
+//
+TRect ArrowIconBoundingBox(const TRect& aItemRect)
+ {
+ TInt iconSize = KArrowIconSizePercent * aItemRect.Height() / KCent;
+ TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
+ TInt positionX = aItemRect.iBr.iX - rightMargin - iconSize;
+ TInt topMargin = ( aItemRect.Height() - iconSize ) / 2; // Icon is vertically centered.
+
+ return TRect(
+ positionX,
+ aItemRect.iTl.iY + topMargin,
+ positionX + iconSize,
+ aItemRect.iTl.iY + topMargin + iconSize );
+ }
+
+
+// -----------------------------------------------------------------------------
+// FavouriteIconBoundingBox
+// Calculates the area to which the favourite icon is drawn.
+// Because favourite icon is drawn in the same line with contact name,
+// this function takes contact name bounding box as the parameter, not
+// the whole item rect.
+// -----------------------------------------------------------------------------
+//
+static TRect FavouriteIconBoundingBox( const TRect& aContactNameBoundingBox, TInt aTextWidth )
+ {
+ return TRect(
+ aContactNameBoundingBox.iTl.iX + aTextWidth,
+ aContactNameBoundingBox.iTl.iY,
+ aContactNameBoundingBox.iTl.iX + aTextWidth + aContactNameBoundingBox.Height(),
+ aContactNameBoundingBox.iBr.iY);
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// BaseLineOffset
+//
+// -----------------------------------------------------------------------------
+//
+static TInt BaseLineOffset( const TRect& aTextBoundingBox, const CFont* aFont )
+ {
+ TInt fontHeight = aFont->FontMaxHeight();
+ TInt topMargin = KTextPlacementPercent * (aTextBoundingBox.Height() - fontHeight) / KCent;
+ return fontHeight + topMargin - aFont->FontMaxDescent();
+ }
+
+
+// -----------------------------------------------------------------------------
+// MirrorLayoutBoundingBox
+//
+// -----------------------------------------------------------------------------
+//
+static TRect MirrorLayoutBoundingBox(const TRect& aSourceRect, TRect& aBoundingBoxRect)
+ {
+ return TRect(
+ aSourceRect.iTl.iX + aSourceRect.iBr.iX - aBoundingBoxRect.iBr.iX,
+ aBoundingBoxRect.iTl.iY,
+ aSourceRect.iTl.iX + aSourceRect.iBr.iX - aBoundingBoxRect.iTl.iX,
+ aBoundingBoxRect.iBr.iY);
+ }
+
+
+// -----------------------------------------------------------------------------
+// ClipTextToWidth
+// Cuts the text in the given pixel width. Also considers match highlight
+// issues.
+// NOTE: Can change the aMatch parameter if considers that there is too little
+// width for matching highlight.
+// NOTE 2: This function cannot handle right-to-left or bidirectional text currently.
+// These cases must be handled elsewhere.
+// -----------------------------------------------------------------------------
+//
+
+_LIT( KThreeDots, "..." );
+
+static void ClipTextToWidth(
+ TDes& aText,
+ const CFont& aFont,
+ TInt aMaxWidthInPixels,
+ TBool& aMatch)
+ {
+ TInt minimumWidth = aFont.TextWidthInPixels( KThreeDots );
+
+ // If this is a matching piece of text, also match text marginals need to be counted.
+ if ( aMatch )
+ {
+ minimumWidth += 2 * KMatchingTextMarginInPixels;
+ }
+
+ if ( minimumWidth > aMaxWidthInPixels )
+ {
+
+ // Not enough space for any text.
+ aText.Zero();
+ aMatch = EFalse; // No match highlight shown.
+ return;
+ }
+
+ if ( aMatch )
+ {
+ aMaxWidthInPixels -= 2 * KMatchingTextMarginInPixels;
+ }
+
+ AknTextUtils::ClipToFit( aText, aFont, aMaxWidthInPixels );
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawPieceOfText
+// Draws a piece of text of contact, either matching or not matching.
+// Updates aXOffset argument by adding drawn text width.
+//
+// @return: ETrue, if there was enough space for the text to draw.
+// NOTE: CWindowGc font must be set before calling this function.
+// -----------------------------------------------------------------------------
+//
+static TBool DrawPieceOfText(
+ const TRect& aBoundingBox,
+ TInt& aXOffset,
+ CWindowGc &aGc,
+ const TDesC& aText,
+ TBool aMatch,
+ const CFont* aFont,
+ const CEasyDialingListBoxData::TExtendedColors& aColors,
+ TBool aHighLight )
+ {
+ if (aText.Length() == 0)
+ {
+ return ETrue;
+ }
+
+ HBufC* newText = aText.Alloc();
+ if ( !newText )
+ {
+ return EFalse;
+ }
+
+ TPtr textPtr = newText->Des();
+
+ // textWidth is the width needed for the text.
+ TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, textPtr, CFont::TMeasureTextInput::EFVisualOrder );
+
+ // whole width includes also possible highlight margins.
+ TInt wholeWidth = textWidth + ( aMatch ? 2 * KMatchingTextMarginInPixels : 0);
+
+ // availableWidth is the space left for drawing.
+ TInt availableWidth = aBoundingBox.Width() - aXOffset;
+
+ if ( availableWidth < wholeWidth )
+ {
+ ClipTextToWidth( textPtr, *aFont, availableWidth, aMatch );
+ wholeWidth = availableWidth;
+ if ( aMatch )
+ {
+ textWidth = wholeWidth - (2 * KMatchingTextMarginInPixels);
+ }
+ else
+ {
+ textWidth = wholeWidth;
+ }
+ }
+
+ // textBox is rectangle for text without highlight.
+ TRect textBox( aBoundingBox );
+ textBox.iTl.iX += aXOffset;
+ textBox.iBr.iX = textBox.iTl.iX + textWidth;
+
+ TInt baseLineOffset = BaseLineOffset( textBox, aFont );
+
+ if ( aMatch )
+ {
+ // highlightBox rectangle for text with highlight.
+ // Compared to no highlight, it has extra margins on both sides.
+ TRect highlightBox( textBox );
+ highlightBox.iBr.iX = highlightBox.iTl.iX + wholeWidth;
+
+ // Also boundingBox is shifted right for one margin width.
+ textBox.iTl.iX += KMatchingTextMarginInPixels;
+ textBox.iBr.iX += KMatchingTextMarginInPixels;
+
+ // Outline of matching highlight is of same colour as text.
+ // This looks quite OK.
+ aGc.SetPenColor( aColors.iMatchingText );
+ aGc.SetBrushStyle( CGraphicsContext::ESolidBrush );
+ aGc.SetBrushColor( aColors.iMatchingBack );
+
+ aGc.DrawRoundRect( highlightBox, TSize( KMatchingTextMarginInPixels, KHighligthRectangleRoundingYInPixels ) );
+
+ aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
+ }
+ else
+ {
+ if ( aHighLight )
+ {
+ aGc.SetPenColor( aColors.iHighlightedText );
+ }
+ else
+ {
+ aGc.SetPenColor( aColors.iText );
+ }
+ }
+
+ aGc.DrawText( textPtr, textBox, baseLineOffset );
+ delete newText;
+ aXOffset += wholeWidth;
+ return ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// DrawTextWithMatchHighlight
+// Draws a string with match highlight. Highlighted and non-highlighted
+// parts are separated with KHighlightSeparatorChar.
+// The first text part is not highlighted and from that on highlight
+// is on on every other text piece.
+//
+// -----------------------------------------------------------------------------
+//
+static TInt DrawTextWithMatchHighlightL(
+ const TRect& aBoundingBox,
+ CWindowGc &aGc,
+ const TDesC& aText,
+ const CFont* aFont,
+ const CEasyDialingListBoxData::TExtendedColors& aColors,
+ TBool aHighLight)
+ {
+ TInt xOffset = 0;
+
+ HBufC* visualBuf = ConvertToVisualAndClipLC( aText, *aFont, aBoundingBox );
+
+ TInt calculatedTextWidth = CalculateTextWidth( aBoundingBox, *visualBuf, aFont );
+
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ xOffset = aBoundingBox.Width() - calculatedTextWidth;
+ }
+ TPtrC textPiece;
+ TInt textPieceIndex = 0;
+ TBool match = EFalse;
+
+ aGc.UseFont( aFont );
+ aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
+
+ while ( TextUtils::ColumnText( textPiece , textPieceIndex, visualBuf, KHighlightSeparatorChar) == KErrNone )
+ {
+ if (! DrawPieceOfText( aBoundingBox, xOffset, aGc, textPiece, match, aFont, aColors, aHighLight ))
+ {
+ // If there was not enough space for this piece of text, exit the loop stop drawing further pieces.
+ break;
+ }
+
+ // Toggle match
+ match = !match;
+
+ ++textPieceIndex;
+ }
+
+ CleanupStack::PopAndDestroy( visualBuf );
+
+ aGc.DiscardFont();
+
+ return calculatedTextWidth;
+ }
+
+// -----------------------------------------------------------------------------
+// CalculateTextWidth
+// Calculates the width of the text and returns it
+// -----------------------------------------------------------------------------
+//
+static TInt CalculateTextWidth(const TRect& aBoundingBox, const TDesC& aText, const CFont* aFont )
+ {
+
+ TInt xOffset = 0;
+ TPtrC textPiece;
+ TInt textPieceIndex = 0;
+ TBool match = EFalse;
+
+ while ( TextUtils::ColumnText( textPiece , textPieceIndex, &aText, KHighlightSeparatorChar) == KErrNone )
+ {
+ if (! CalculateTextPieceWidth( aBoundingBox, xOffset, textPiece, match, aFont ))
+ {
+ // If there was not enough space for this piece of text, exit the loop stop drawing further pieces.
+ break;
+ }
+
+ // Toggle match
+ match = !match;
+
+ ++textPieceIndex;
+ }
+
+ return xOffset;
+ }
+
+// -----------------------------------------------------------------------------
+// CalculateTextPieceWidth
+//
+// Calculates the width of the text piece of highlighted text.
+// The function is aware of the available width for the text, and can take
+// possible clippings into account.
+//
+// The available width is given by parameters aBoundingBox (space for all text
+// pieces) and aXOffset (now much of that space has already been used).
+//
+// The function adds the text width to the aXOffset reference parameter.
+// Returns EFalse, if there is no more space for new text pieces, otherwise
+// ETrue.
+//
+// This function contains the same logic as function DrawPieceOfText.
+// -----------------------------------------------------------------------------
+//
+static TBool CalculateTextPieceWidth(
+ const TRect& aBoundingBox,
+ TInt& aXOffset,
+ const TDesC& aText,
+ TBool aMatch,
+ const CFont* aFont )
+ {
+ if (aText.Length() == 0)
+ {
+ return ETrue;
+ }
+
+ // textWidth is the width needed for the text.
+ TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, aText, CFont::TMeasureTextInput::EFVisualOrder );
+
+ // whole width includes also possible highlight margins.
+ TInt wholeWidth = textWidth + ( aMatch ? 2 * KMatchingTextMarginInPixels : 0);
+
+ // availableWidth is the space left for drawing.
+ TInt availableWidth = aBoundingBox.Width() - aXOffset;
+
+ if ( availableWidth < wholeWidth )
+ {
+
+ // We get to this branch, if there is not enough space for the text piece.
+ HBufC* newText = aText.Alloc();
+ if ( !newText )
+ {
+ return EFalse;
+ }
+
+ TPtr textPtr = newText->Des();
+
+ // Clip the text so that it fits the space.
+ ClipTextToWidth( textPtr, *aFont, availableWidth, aMatch );
+
+ if ( textPtr.Length() > 0 )
+ {
+ wholeWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, textPtr, CFont::TMeasureTextInput::EFVisualOrder );
+ wholeWidth += (aMatch ? 2 * KMatchingTextMarginInPixels : 0);
+
+ aXOffset += wholeWidth;
+ }
+
+ delete newText;
+
+ return EFalse;
+ }
+
+ aXOffset += wholeWidth;
+
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// ContainsRightToLeftText
+//
+// Returns true if argument descriptor contains right-to-left text.
+// -----------------------------------------------------------------------------
+//
+static TBool ContainsRightToLeftText( const TDesC& aDesc )
+ {
+ TBool rtlFound = EFalse;
+
+ // TRunInfoArray contains information of the directionalities of the different sections of the aText
+ TBidirectionalState::TRunInfo array[ KMaxRunInfoArrayCount ];
+
+ // Initialize the TBidiLogicalToVisual converter for making the conversion from logical to visual order
+ TBidiLogicalToVisual converter( aDesc, array, KMaxRunInfoArrayCount );
+
+ // Do the reordering. Amount of different directionality sections is returned.
+ TInt count( converter.Reorder() );
+ // If there are more directionality blocks than we are prepared to handle, just ignore
+ // the rest. Those shouldn't fit the screen anyway.
+ count = Min( count, KMaxRunInfoArrayCount );
+
+ for ( TInt i = 0 ; i < count && !rtlFound ; i++ )
+ {
+ // iDirection is 0 for left-to-right text.
+ if (array[i].iDirection)
+ {
+ rtlFound = ETrue;
+ }
+ }
+
+ return rtlFound;
+ }
+
+// -----------------------------------------------------------------------------
+// ConvertToVisualAndClipL
+//
+// Clip bidirectional text to given box and convert it to visual order, ensuring
+// that the match highlights don't get broken in the process. Result is given
+// as new heap descriptor which is left to CleanupStack.
+// NOTE1: No clipping happens here if given descriptor contains only
+// left-to-right text.
+// NOTE2: It's assumed that there can be highlights only in pure LTR and RTL
+// texts. Highlights for mixed LTR-RTL text cannot be handled properly.
+// -----------------------------------------------------------------------------
+//
+static HBufC* ConvertToVisualAndClipLC( const TDesC& aText,
+ const CFont& aFont,
+ const TRect& aBoundingBox )
+ {
+ HBufC* buf = HBufC::NewLC( aText.Length() + KAknBidiExtraSpacePerLine );
+ TPtr ptr = buf->Des();
+ ptr.Copy( aText );
+
+ // Calling AknBidiTextUtils::ConvertToVisualAndClip doesn't work correctly
+ // with the highlight separator characters (they are not considered to be
+ // zero-length). To minimise the problem, we call the function only when
+ // necessary, i.e. when given text really contains RTL text. This should be
+ // considered as temporary solutions because now the problem of excessive
+ // truncation still remains with RTL languages.
+ if ( ContainsRightToLeftText( ptr ) )
+ {
+ AknBidiTextUtils::ConvertToVisualAndClipL(
+ ptr, aFont, aBoundingBox.Width(),
+ aBoundingBox.Width() );
+
+ // If there's an odd number of highlight separators in the RTL text,
+ // then the matching and and not-matching parts have gone
+ // off-sync in the visual conversion (because parts are drawn starting
+ // from left and first part is always interpreted as not-matching part).
+ // Fix this by adding one highlight separator.
+ TInt sepCount = HighlightSeparatorCount( ptr );
+ if ( sepCount % 2 )
+ {
+ if ( ptr.Length() == ptr.MaxLength() )
+ {
+ // There's no more space available. We need to reallocate the
+ // buffer in order to fit the extra separator character.
+ HBufC* newBuf = buf->ReAllocL( buf->Length() + 1 );
+ CleanupStack::Pop( buf ); // original buf deleted by ReAllocL
+ buf = newBuf;
+ CleanupStack::PushL( buf );
+ ptr.Set( buf->Des() );
+ }
+ ptr.Insert( 0, KHighlightSeparatorCharAsLit );
+ }
+ }
+
+ return buf;
+ }
+
+// -----------------------------------------------------------------------------
+// HighlightSeparatorCount
+//
+// Returns number of match highlight separator characters in the text
+// -----------------------------------------------------------------------------
+//
+static TInt HighlightSeparatorCount( const TDesC& aText )
+ {
+ TInt len = aText.Length();
+ TInt sepCount = 0;
+
+ for ( TInt i = 0; i < len; i++ )
+ {
+ if ( aText[i] == KHighlightSeparatorChar )
+ {
+ sepCount++;
+ }
+ }
+
+ return sepCount;
+ }
+
+// End of File.
+