/*
* Copyright (c) 2002-2009 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: 
*
*/

#ifdef __ARMCC__
#pragma push
#pragma O3
#pragma Otime
#pragma arm
#endif // __ARMCC__

#include <eikfrlbd.h>
#include <aknlists.h>
#include <AknMarqueeControl.h>
#include <AknPictographInterface.h>
#include <AknPictographDrawerInterface.h>
#include <AknsEffectAnim.h>
#include <AknsListBoxBackgroundControlContext.h>
#include <AknsFrameBackgroundControlContext.h>
#include <AknPanic.h>
#include <AknBidiTextUtils.h>
#include <centralrepository.h>
#include <AvkonInternalCRKeys.h>
#include <gulicon.h>
#include <eikslbd.h>
#include "AknDebug.h"
#include <aknlayoutscalable_avkon.cdl.h>
#include <layoutmetadata.cdl.h>
#include <aknphysics.h>
#include <AknIconArray.h>
#include <avkon.mbg>


#ifdef RD_UI_TRANSITION_EFFECTS_LIST
#include <aknlistloadertfx.h>
#include <aknlistboxtfxinternal.h>
#endif //RD_UI_TRANSITION_EFFECTS_LIST

#include <touchfeedback.h>
#include <AknSmileyUtils.h>
#include "akntrace.h"

// there are 17(!) subcells in qdial grid (0 ... 16)
const TInt KMaxSubCellIndex = 16 + 1;

// colored tick marks support
const TInt KColorIconFlag = -1;
const TInt KColorIconIdx  =  0;

// Number of icons in marking mode icon array
const TInt KMarkingModeIconArraySize = 2;

// smiley text place holder
_LIT( KPlaceHolder, "\xFFF0i" );

/**
* This class needs to be in .cpp file so that we do not accidentally make it
* derivable; that would destroy all the binary compability advantages this
* class has..
*
* About animation usage:
* All animation usage is implemented in this class. Animation is eye candy and
* low priority when it comes to resources -> on resource failures animation
* fails fast to release resources for more critical functionality. Also, no
* attempt to (re)construct failed animation is made.
*
* User inactivity is not being observed. Only one animation is used. Extension
* is CActive to make it possible to postpone animation deletion on animation
* failure.
*/
NONSHARABLE_CLASS(CFormattedCellListBoxDataExtension) :
    public CActive,
    public MAknPictographAnimatorCallBack,
    public MCoeForegroundObserver,
    public MAknsEffectAnimObserver,
    public MListBoxItemChangeObserver,
    public MAknSmileyObserver
    {
public:
    enum TFlag
        {
        // Set if current item background should be copied to animation as
        // input layer.
        EFlagUpdateBg      = 0,

        // Set if animation has been resized at least once
        EFlagHasLayers     = 1,

        // Set if foreground has been gained.
        EFlagHasForeground = 2
        };

    enum TSubCellType
        {
        EAknSLGraphic,
        EAknSLText,
        EAknSLNumeric
        };

public:
    CFormattedCellListBoxDataExtension();
    void ConstructL( CFormattedCellListBoxData* aListBoxData,
                     const TAknsItemID& aAnimationIID );
    ~CFormattedCellListBoxDataExtension();
    void CreatePictographInterfaceL();
    void CreateMarqueeControlL();
    static TInt RedrawEvent(TAny* aControl);    // Marquee draw callback
    TBool IsMarqueeOn();
    struct SRowAndSubCell
        {
        TInt iIndex; // 24 bits for row and 8 bits for subcell
        const CFont* iFont;
        //TBool iUnderline;
        //TBool iStrikethrough;
        };
    struct SSLSubCell
        {
        TInt iSubCell; // Must be first entry
        TAknTextLineLayout iTextLayout;
        TAknWindowLineLayout iGraphicLayout;
        TInt iSubCellType;
        TInt iConditionValue; // used with conditional layouts for not always drawn subcells
        TBool iSmileyCell;
        };

    SRowAndSubCell& At(TInt aArrayIndex);
    const SRowAndSubCell& At(TInt aArrayIndex) const;
    void AddRowAndSubCellL(TInt aRow,TInt aSubCell);
    TInt FindRowAndSubCellIndex(TInt& aArrayIndex,TInt aRow,TInt aSubCell) const;
    void FindRowAndSubCellIndexOrAddL(TInt& aArrayIndex,TInt aRow,TInt aSubCell);

    SSLSubCell& SLAt(TInt aArrayIndex);
    const SSLSubCell& SLAt(TInt aArrayIndex) const;
    void AddSLSubCellL(TInt aSubCell);
    TInt FindSLSubCellIndex(TInt& aArrayIndex, TInt aSubCell) const;
    void FindSLSubCellIndexOrAddL(TInt& aArrayIndex, TInt aSubCell);
    void ResetSLSubCellArray();

    inline void NoAnimIfError( TInt aError );
    void TryCreateAnimation();
    TBool SyncAnim( const TSize& aSize );
    TBool SyncAndDrawAnim( CBitmapContext& aGc, const TRect& aRect );
    MAknsControlContext* SkinBackgroundContext() const;
    void DeleteAnim();
    void FocusGained();
    void FocusLost();
    void SkinChanged();
    void SetControl( CCoeControl* aControl );

    // Implementation of MCoeForegroundObserver
    void HandleGainingForeground();
    void HandleLosingForeground();

    // Implementation of MAknsEffectAnimObserver
    void AnimFrameReady( TInt aError, TInt );

    // Implementation of MListBoxItemChangeObserver
    void ListBoxItemsChanged(CEikListBox* aListBox);

    // Overloads CActive::DoCancel
    void DoCancel();
    // Overloads CActive::RunL
    void RunL();

    void Play();

    void CreateColorBitmapsL( TSize aSize );
    void CreateColorBitmapsL();
    
    TBool DrawPressedDownEffect( MAknsSkinInstance* aSkin, 
                                 CWindowGc& aGc, 
                                 const TRect& aOutRect, 
                                 const TRect& aInnerRect ) const;
    void DrawSmileyWithText( CWindowGc& aGc, const TDesC& aSmileyText, 
                             const TAknLayoutText& aLayout, 
                             TBool aUseLogicalToVisualConversion, 
                             const TRgb &aColor);
    TInt ConvertTextToSmiley( TDes& aText );
    void LoadMarkingIconsL();

private: // New internal methods
    TBool DrawHighlightBackground( CFbsBitGc& aGc );
    void PostDeleteAnimation();
    void CreateAnimationL();
    void DoResizeL( const TSize& aHighlightSize, TBool aAboutToStart );

public:
    struct TSubCellExt
        { 
        TInt iSubCell; // Must be first entry 
        TBool iLayoutAlign;         
        };
    
    TInt AddSubCellExtL(TInt aSubCell);
    void FindSubCellExtIndexOrAddL( TInt& aArrayIndex,TInt aSubCell);

    void SetSubCellLayoutAlignmentL( TInt aSubCellIndex );        
        
        
    TInt FindSubCellExtIndex(TInt& aArrayIndex,TInt aSubCell) const;
    TBool SubCellLayoutAlignment(TInt aSubCellIndex) const;        
public: // from MAknSmileyObserver
    void SmileyStillImageLoaded( CAknSmileyIcon* aSmileyIcon );
    void SmileyAnimationChanged( CAknSmileyIcon* aSmileyIcon );
private: // From MAknPictographAnimatorCallBack
    void DrawPictographArea();

public:
    CCoeControl *iControl; // not owned
    CFormattedCellListBoxData* iListBoxData; // Not owned
    CAknsListBoxBackgroundControlContext* iSkinControlContext;
    TBool iSkinEnabled;
    const TAknsItemID *iSkinHighlightFrameId;
    const TAknsItemID *iSkinHighlightFrameCenterId;
    TBool iRespectFocus;
// not used ?    HBufC *iTempTextBuffer;
    TRect iSkinPopupInnerRect;
    TRect iSkinPopupOuterRect;
    CAknsFrameBackgroundControlContext* iPopupFrame;
    TBool iUseLogicalToVisualConversion;
    TInt16 iFirstWordWrappedSubcellIndex;
    TInt16 iSecondWordWrappedSubcellIndex;
    CAknPictographInterface* iPictoInterface;
    CAknMarqueeControl* iMarquee;
    CAknMarqueeControl* i2ndLineMarquee;
    TInt iCurrentItem; // Current list item index that marquee draws/has drawn.
    TInt iCurrentRow; // Current list row being drawn.  // not true - cache of currentitemindex 
    TInt iCurrentlyDrawnItemIndex;
    CArrayFix<SRowAndSubCell>* iRowAndSubCellArray;
    CArrayFix<SSLSubCell>* iSLSubCellArray;
    TBool iDrawBackground;   // Determines if background should be drawn (transparency)
    TSize iSubCellIconSize[KMaxSubCellIndex]; // Store icon sizes for each subcell
    TAknSeparatorLinePosition iSeparatorLinePosition;
    CAknsEffectAnim* iAnimation;
    TBitFlags32 iAnimFlags;
    TRgb iHighlightedTextColor;
    TRgb iTextColor;
    TBool iDrawScrollbarBackground;
    TBool iSimpleList;

    TBool       iUnderlineFlagSet;  // underlining support for more than
    TBitFlags32 iUnderlineFlags;    // one text subcell
    TBool iHideSecondRow;
    TBool iSubCellsMightIntersect;
    TBool iStretchingEnabled;
    TAknsItemID iAnimIID;
    MListBoxAnimBackgroundDrawer* iHighlightBgDrawer;
    TSize iAnimSize; // TODO Deprecating old style anim API and removing this
    // Drop shadows can be toggled on/off in
    // "transparent" lists (eg. transparent camera setting page).
    TBool iUseDropShadows;

    // highlight color skinning for setstyle lists - to be deprecated once correct color skinning is available
    TBool iUseHighligthIconSwapping;

    // colorskin highlight icons
    CFbsBitmap* iColorBmp;
    CFbsBitmap* iHiliBmp;
    TRgb        iIconColor;
    TRgb        iHiliIconColor;

    TInt        iConditionalCells;

    // which columns of highlighted item have clipped text ?
    TUint32     iClippedSubcells;
    TUint32     iClippedByWrap;
    TBool       iUseClippedByWrap;

    CArrayFix<TSubCellExt>* iSubCellExtArray; //for subcell alignment

    TRect iMarginRect;    
    TBool iKineticScrolling;
    CAknSmileyManager* iSmileyMan;
    TSize iSmileySize; // last set simley size
    CAknIconArray* iMarkingIconArray;
    };


/**
* High priority is well argumented because running the active object will
* result in animation deletion -> results in freeing resources.
*/
CFormattedCellListBoxDataExtension::CFormattedCellListBoxDataExtension():
    CActive( EPriorityHigh )
    {}

void CFormattedCellListBoxDataExtension::ConstructL(
    CFormattedCellListBoxData* aListBoxData,
    const TAknsItemID& aAnimationIID )
    {
    _AKNTRACE_FUNC_ENTER;
    iListBoxData = aListBoxData;
    iRowAndSubCellArray = new(ELeave) CArrayFixFlat<SRowAndSubCell>(4);
    iSLSubCellArray = new(ELeave) CArrayFixFlat<SSLSubCell>(4);
    
    iSubCellExtArray = new(ELeave) CArrayFixFlat<TSubCellExt>(4);

    // bi-di algorithm support (NON_LEAVING_VERSION)
// not used ?    iTempTextBuffer = HBufC::NewL(256);
    iUseLogicalToVisualConversion = ETrue;

    iFirstWordWrappedSubcellIndex = -1;
    iSecondWordWrappedSubcellIndex = -1;

    iDrawBackground = ETrue;
    iSeparatorLinePosition = ENoLine;

    iAnimIID = aAnimationIID;
    CActiveScheduler::Add( this );
    TryCreateAnimation(); // Animations are created by default

    iTextColor = NULL; // just in case
    iHighlightedTextColor = NULL; // just in case
    iDrawScrollbarBackground = ETrue;
    
#ifdef RD_LIST_STRETCH
    // check list stretching from cenrep
    CRepository* cenRep = CRepository::NewL( KCRUidAvkon );
    cenRep->Get( KAknAutomaticListStretching, iStretchingEnabled );
    delete cenRep;
#endif

    iKineticScrolling = CAknPhysics::FeatureEnabled();
    LoadMarkingIconsL();
    _AKNTRACE_FUNC_EXIT;
    }

CFormattedCellListBoxDataExtension::~CFormattedCellListBoxDataExtension()
    {
    _AKNTRACE_FUNC_ENTER;
    Cancel();

    // Stop receiving foreground events
    CCoeEnv* env = CCoeEnv::Static();
    env->RemoveForegroundObserver( *this );
    delete iSmileyMan;

    delete iRowAndSubCellArray;
    iRowAndSubCellArray = NULL;
    delete iSLSubCellArray;
    iSLSubCellArray = NULL;
    delete iSubCellExtArray;
    iSubCellExtArray = NULL;
    delete iPopupFrame;
    delete iSkinControlContext;
// not used ?    delete iTempTextBuffer;
    delete iPictoInterface;
    delete iMarquee;
    delete i2ndLineMarquee;
    delete iAnimation;
    delete iColorBmp;
    delete iHiliBmp;
    
    if ( iMarkingIconArray )
        {
        iMarkingIconArray->ResetAndDestroy();
        }

    delete iMarkingIconArray;
    _AKNTRACE_FUNC_EXIT;
    }

void 
CFormattedCellListBoxDataExtension::AddRowAndSubCellL(TInt aRow,TInt aSubCell)
    {
    _AKNTRACE("CFormattedCellListBoxDataExtension::AddRowAndSubCellL aRow = %d, aSubCell=%d",
            aRow, aSubCell);
    SRowAndSubCell subcell;
    subcell.iIndex = (aRow << 8) | (aSubCell & 0xff);
    subcell.iFont=NULL;
    TKeyArrayFix key(0,ECmpTInt32);
    iRowAndSubCellArray->InsertIsqL(subcell,key);
    }


CFormattedCellListBoxDataExtension::SRowAndSubCell& 
CFormattedCellListBoxDataExtension::At(TInt aArrayIndex)
    {
/*    SRowAndSubCell subcell;
    for (int a=0;a<iRowAndSubCellArray->Count();a++)
        subcell = iRowAndSubCellArray->At(a); */

    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iRowAndSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iRowAndSubCellArray->At(aArrayIndex));
    }

const CFormattedCellListBoxDataExtension::SRowAndSubCell& 
CFormattedCellListBoxDataExtension::At(TInt aArrayIndex) const
    {
    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iRowAndSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iRowAndSubCellArray->At(aArrayIndex));
    }

TInt CFormattedCellListBoxDataExtension::FindRowAndSubCellIndex(TInt& aArrayIndex,
                                                                TInt aRow,
                                                                TInt aSubCell) const
    {
    if (iRowAndSubCellArray->Count()==0)
        return(KErrNotFound);
    TKeyArrayFix key(0,ECmpTInt32);
    SRowAndSubCell rowAndSubcell;
    rowAndSubcell.iIndex = (aRow << 8) | (aSubCell & 0xff);
    return(iRowAndSubCellArray->FindIsq(rowAndSubcell,key,aArrayIndex));
    }

void CFormattedCellListBoxDataExtension::FindRowAndSubCellIndexOrAddL(TInt& aArrayIndex,
                                                                      TInt aRow,
                                                                      TInt aSubCell)
    {
    if (FindRowAndSubCellIndex(aArrayIndex,aRow,aSubCell)!=0) //==KErrNotFound)
        {
        AddRowAndSubCellL(aRow,aSubCell);
        FindRowAndSubCellIndex(aArrayIndex,aRow,aSubCell);
        }
/*       SRowAndSubCell rowAndSubcell;
    rowAndSubcell = iRowAndSubCellArray->At(aArrayIndex); */
    }


void 
CFormattedCellListBoxDataExtension::AddSLSubCellL(TInt aSubCell)
    {
    _AKNTRACE("CFormattedCellListBoxDataExtension::AddSLSubCellL aSubCell = %d",
            aSubCell);
    SSLSubCell subcell;
    subcell.iSubCell = aSubCell;
    subcell.iTextLayout = NULL;
    subcell.iGraphicLayout = NULL;
    subcell.iSubCellType = 0;
    subcell.iConditionValue = -1;
    subcell.iSmileyCell = EFalse;

    TKeyArrayFix key(0,ECmpTInt32);
    iSLSubCellArray->InsertIsqL(subcell,key);
    }


CFormattedCellListBoxDataExtension::SSLSubCell& 
CFormattedCellListBoxDataExtension::SLAt(TInt aArrayIndex)
    {
    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iSLSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iSLSubCellArray->At(aArrayIndex));
    }

const CFormattedCellListBoxDataExtension::SSLSubCell& 
CFormattedCellListBoxDataExtension::SLAt(TInt aArrayIndex) const
    {
    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iSLSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iSLSubCellArray->At(aArrayIndex));
    }

TInt CFormattedCellListBoxDataExtension::FindSLSubCellIndex(TInt& aArrayIndex,
                                                            TInt aSubCell) const
    {
    if (iSLSubCellArray->Count()==0)
        return(KErrNotFound);
    TKeyArrayFix key(0,ECmpTInt32);
    SSLSubCell SLSubCell;
    SLSubCell.iSubCell = aSubCell;
    return(iSLSubCellArray->FindIsq(SLSubCell,key,aArrayIndex));
    }

void CFormattedCellListBoxDataExtension::FindSLSubCellIndexOrAddL(TInt& aArrayIndex,
                                                                  TInt aSubCell)
    {
    if (FindSLSubCellIndex(aArrayIndex, aSubCell)!=0) //==KErrNotFound)
        {
        AddSLSubCellL(aSubCell);
        FindSLSubCellIndex(aArrayIndex,aSubCell);
        }
    }

void CFormattedCellListBoxDataExtension::ResetSLSubCellArray()
    {
    iSLSubCellArray->Reset();
    iRowAndSubCellArray->Reset();
    }

void CFormattedCellListBoxDataExtension::CreatePictographInterfaceL()
    {
    if ( !iPictoInterface )
        {
        iPictoInterface = CAknPictographInterface::NewL( *iControl, *this );
        }
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::NoAnimIfError
// -----------------------------------------------------------------------------
//
inline void CFormattedCellListBoxDataExtension::NoAnimIfError( TInt aError )
    {
    if( KErrNone != aError )
        {
        DeleteAnim();
        }
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::TryCreateAnimation
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::TryCreateAnimation()
    {
    _AKNTRACE_FUNC_ENTER;
    if( !iControl )
        {
        _AKNTRACE("CFormattedCellListBoxDataExtension::TryCreateAnimation iControl==NULL");
        _AKNTRACE_FUNC_EXIT;
        return;
        }

#ifdef RD_UI_TRANSITION_EFFECTS_LIST  
    CEikListBox* list = static_cast<CEikListBox*>( iControl );
    CListBoxView* view = list->View();
    if ( !view || !view->ItemDrawer() )
        {
        return;
        }
    CWindowGc* gc = view->ItemDrawer()->Gc();
    MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( gc );
    if ( transApi && transApi->VerifyKml() == KErrNone )
        {
        return;
        }
#endif //RD_UI_TRANSITION_EFFECTS_LIST      


    // Ideally we should not create animation if the list has zero items.
    // Unfortunately, this will cause problems elsewhere as setting item text
    // array to list requires not calling HandleItemAddition (or similar
    // method) -> in some situations animation would not be created at all as
    // we don't receive item change event. Fortunately, creating animation to
    // empty list doesn't carry much overhead as layer creation is delayed to
    // first render.

    if( !iAnimation )
        {
        // This must be the first call because animation does not exist.
        // Animation layers are created when the animation is rendered for the
        // first time.
        TRAPD( err, CreateAnimationL() );
        NoAnimIfError( err );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::SyncAnim
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxDataExtension::SyncAnim( const TSize& aSize )
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("CFormattedCellListBoxDataExtension::SyncAnim aSize=(%d,%d)",
            aSize.iWidth, aSize.iHeight);
    if( !iAnimation || aSize.iWidth <= 0 || aSize.iHeight <= 0 )
        {
        _AKNTRACE("SyncAnim: invalid size or no iAnimation");
        _AKNTRACE_FUNC_EXIT;
        return EFalse;
        }

    if( iAnimation->Size() != aSize || iAnimation->NeedsInputLayer() )
        {
        // Resizing will update animation background
        iAnimFlags.Clear( EFlagUpdateBg );

        // Animation exists but its size is out of sync or input layers have
        // been released
        TRAPD( err, DoResizeL( aSize, iAnimFlags.IsSet( EFlagHasForeground ) ) );

        if( err )
            {
            DeleteAnim();
            return EFalse;
            }
        iAnimFlags.Set( EFlagHasLayers );
        }

    // Highlight animation background needs update (current item has changed)
    if( iAnimFlags.IsSet( EFlagUpdateBg ) )
        {
        iAnimFlags.Clear( EFlagUpdateBg );

        if( iAnimation->InputRgbGc() )
            {
            DrawHighlightBackground( *iAnimation->InputRgbGc() );
            // We need to update the output frame (otherwise the highlight
            // would drawn with the old output before the next new animation
            // frame).
            NoAnimIfError( iAnimation->UpdateOutput() );
            if( !iAnimation )
                {
                return EFalse;
                }
            }
        }

    _AKNTRACE_FUNC_EXIT;
    return ETrue;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::SyncAndDrawAnim
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxDataExtension::SyncAndDrawAnim(
        CBitmapContext& aGc, const TRect& aRect )
    {
    if( iAnimation )
        {
        // When application loses foreground or has not yet gained foreground
        // animation is in stopped state and input layers are not present. It
        // is possible that list is repainted in this situation. Calling
        // SyncAnim will create the non-present layers -> WSERV flush ->
        // flicker. To prevent flickering we just render the existing frame.
        // This can lead to incorrect draw if the current item index is changed
        // when the app has no foreground (very unlikely). If EFlagHasLayers is
        // not set we need to do SyncAnim because it is the first call to draw
        // (and flicker is not an issue).
        if( EAknsAnimStateStopped == iAnimation->State() &&
            !iAnimFlags.IsSet( EFlagHasForeground ) &&
            iAnimFlags.IsSet( EFlagHasLayers ) &&
            !iAnimFlags.IsSet( EFlagUpdateBg ) )
            {
            return iAnimation->Render( aGc, aRect );
            }
        }

    if( SyncAnim( aRect.Size() ) )
        {
        return iAnimation->Render( aGc, aRect );
        }

    return EFalse;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::SkinBackgroundContext
// -----------------------------------------------------------------------------
//
MAknsControlContext* CFormattedCellListBoxDataExtension::SkinBackgroundContext() const
    {
    if( iSkinEnabled )
        return iSkinControlContext;
    else
        return NULL;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::DeleteAnim
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::DeleteAnim()
    {
    // Stop receiving foreground events
    _AKNTRACE_FUNC_ENTER;
    CCoeEnv* env = CCoeEnv::Static();
    env->RemoveForegroundObserver( *this );

    delete iAnimation;
    iAnimation = NULL;
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::FocusGained
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::FocusGained()
    {
    _AKNTRACE_FUNC_ENTER;
    Play();
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::FocusLost
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::FocusLost()
    {
    _AKNTRACE_FUNC_ENTER;
    if( iAnimation )
        {
        _AKNTRACE("CFormattedCellListBoxDataExtension::FocusLost begin pause "
                  "animation");
        NoAnimIfError( iAnimation->Pause() );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::SkinChanged
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::SkinChanged()
    {
    _AKNTRACE_FUNC_ENTER;
    DeleteAnim();
    TryCreateAnimation();
    TRAP_IGNORE(CreateColorBitmapsL());
    TRAP_IGNORE( LoadMarkingIconsL() );
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::SetControl
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::SetControl( CCoeControl* aControl )
    {
    _AKNTRACE_FUNC_ENTER;
    if( iControl )
        {
        CEikListBox* list = (CEikListBox*) iControl;
        list->RemoveItemChangeObserver( this );
        }

    iControl = aControl;

    if( iControl )
        {
        CEikListBox* list = (CEikListBox*) iControl;
        TRAP_IGNORE( list->AddItemChangeObserverL(this) );

        if( !iAnimation )
            {
            TryCreateAnimation();
            }

        if( iAnimation )
            {
            Play();
            }
        }
    else
        {
        DeleteAnim();
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::HandleGainingForeground
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::HandleGainingForeground()
    {
    _AKNTRACE_FUNC_ENTER;
    // Most of the time focus focus events happen between foreground events.
    // Unfortunately, there are embedded app related cases where this does not
    // always hold (it is possible to focus in non-foreground application or
    // gain foreground without getting a focus gained). Therefore animations
    // must be started here. This causes potential problem case: foreground
    // events are broadcasted to all animations, if there are multiple lists
    // that have focus the result will be multiple animations running at the
    // same time.
    iAnimFlags.Set( EFlagHasForeground );

    if( iAnimation )
        {
        // Because we are gaining foreground we must restore input layers
        // (which are released when animation stops to reduce memory usage).
        SyncAnim( iAnimation->Size() );
        }

    if( iControl )
        {
        if( iControl->IsFocused() )
            {
            Play();
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::HandleLosingForeground
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::HandleLosingForeground()
    {
    _AKNTRACE_FUNC_ENTER;
    iAnimFlags.Clear( EFlagHasForeground );
    if( iAnimation )
        {
        NoAnimIfError( iAnimation->Stop() );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::AnimFrameReady
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::AnimFrameReady( TInt aError, TInt )
    {
    _AKNTRACE_FUNC_ENTER;
    if( KErrNone != aError )
        {
        _AKNTRACE("AnimFrameReady£º aError=%d, return",aError);
        // Animation has failed to run -> schedule the animation for
        // deletion to fall back to normal rendering.
        PostDeleteAnimation();
        return;
        }

    // This situation should never happen because we start/stop animation when
    // the extension's control is set.
    if( !iControl )
        {
        _AKNTRACE("AnimFrameReady£º no iControl, return");
        return;
        }

    // From now on, we have a valid control pointer
    CEikListBox* list = static_cast<CEikListBox*>( iControl );
    CListBoxView* view = list->View();

    if( !view )
        {
        _AKNTRACE("AnimFrameReady£º no view, return");
        return;
        }

    // We should not run animation when control is in certain states. When
    // control is in these states we idle the animation until the control state
    // becomes valid again.
    TBool invalid = !iControl->IsVisible() ||
                    iControl->IsDimmed() ||
                    (view->ItemDrawer()->Flags() & CListItemDrawer::EDisableHighlight);

    _AKNTRACE("AnimFrameReady£º invalid=%d", invalid);
    // Check for idling
    if( iAnimation->IsIdling() )
        {
        if( invalid )
            {
            // We are idling and the control is still invalid -> keep on
            // idling.
            return;
            }
        else
            {
            // Control is in valid state, animation should be continued
            TInt err = iAnimation->Continue();
            if( err )
                PostDeleteAnimation();
            return;
            }
        }
    else if( invalid ) // Not idling and invalid control -> start idling
        {
        iAnimation->SetIdling( KAknsEffectAnimDefaultIdleInterval );
        // If the highlight has been disabled, render once to clear the
        // highlight (not returning in that case).
        if( !(view->ItemDrawer()->Flags() & CListItemDrawer::EDisableHighlight) )
            return;
        }

    // From now on, we have a valid control pointer and control has enabled
    // highlight, is visible and is not dimmed.

    // No items, no drawing
    if( list->Model()->NumberOfItems() == 0 )
        return;

    if( iListBoxData->LastSubCell() < 0 )
        return;
    
    

    TBool customGcInUse = list->GetGc() != &CEikonEnv::Static()->SystemGc();

    // if remoteGc is in use (CCoeControl has custom gc set)
    // then draw the whole control as the transition system 
    // expects the draw to be initiated from CONE control

    if( !customGcInUse )
        {
        // Repaint the highlighted cell only
        list->RedrawItem( view->CurrentItemIndex() );
        }
    else
        {
        CCoeControl* ctrl = (CCoeControl*)list;
        ctrl->DrawNow();
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::ListBoxItemsChanged
//
// this is called from from:
// - CEikListBox::Reset()
// - CEikListBox::HandleItemRemoval{WithoutSelections}L()
// - CEikListBox::HandleItemAdditionL()
// - CEikListBox::FireItemChange()
// In all cases:
// - feedback areas might be invalid
// - application is responsible for redrawing the listbox.
//
// since re-drawing listbox fixes feedback areas, those can be reset here.
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::ListBoxItemsChanged(
        CEikListBox* aListBox)
    {
    _AKNTRACE_FUNC_ENTER;
    TInt items = aListBox->Model()->NumberOfItems();

    if( iAnimation )
        {
        if( 0 == items )
            {
            DeleteAnim();
            }
        else
            {
            Play();
            }
        }
    else if( !iAnimation )
        {
        // Animation doesn't exist and we have > 0 items
        TryCreateAnimation();
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::DoCancel
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::DoCancel()
    {
    // Required method, but not needed
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::RunL
// Postponed animation deletion is done here.
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::RunL()
    {
    _AKNTRACE_FUNC_ENTER;
    DeleteAnim();
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::Play
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::Play()
    {
    _AKNTRACE_FUNC_ENTER;
    if( !iAnimation )
        {
        _AKNTRACE("Play: no iAnimation, return");
        return;
        }

    // No need to start running/finished animation
    if( EAknsAnimStateRunning == iAnimation->State() ||
        EAknsAnimStateFinished == iAnimation->State() )
        {
        _AKNTRACE("Play: animation already started or finished");
        return;
        }

    // Check that application is on foreground because there are cases where
    // focus changes are done after foreground is lost -> potentially leads to
    // multiple running animations.
    if( !iAnimFlags.IsSet( EFlagHasForeground ) )
        {
        _AKNTRACE("Play: animation is not foreground, return");
        return;
        }

    // Animation cannot run if we don't have control (nowhere to draw)
    if( !iControl )
        {
        _AKNTRACE("Play: no iControl, return");
        return;
        }

    // The control must also have the focus
    if( !iControl->IsFocused() )
        {
        _AKNTRACE("Play: iControl doesn't have focus, return");
        return;
        }

    // Don't animate empty list
    CEikListBox* list = static_cast<CEikListBox*>( iControl );
    if( list->Model()->NumberOfItems() == 0 )
        {
        _AKNTRACE("Play: empty list, return");
        return;
        }

    // All preconditions are met: we have animation, foreground, focus, more
    // than zero items and animation is either paused or stopped. Invisibility,
    // dimming and disabled highlight are handled by idling the animation (see
    // AnimFrameReady).

    if( EAknsAnimStatePaused == iAnimation->State() )
        {
        NoAnimIfError( iAnimation->Continue() );
        }
    else if( EAknsAnimStateStopped == iAnimation->State() )
        {
        NoAnimIfError( iAnimation->Start() );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::DrawHighlightBackground
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxDataExtension::DrawHighlightBackground( CFbsBitGc& aGc )
    {
    _AKNTRACE_FUNC_ENTER;
    if( iHighlightBgDrawer ) // Bg drawing is done externally (in derived class)
        {
        return iHighlightBgDrawer->DrawHighlightAnimBackground( aGc );
        }

    // Draw the background under the current highlight. This is simplified
    // drawing, we only grab a piece from the list background bitmap.
    CEikListBox* list = static_cast<CEikListBox*>( iControl );
    CListBoxView* view = list->View();
    TRect itemRect;
    TInt index = view->CurrentItemIndex();

    // It is possible that the animation is constructed when the list is
    // empty. In this case draw the first element background (drawing works ok
    // even if the list has no items).
    if( list->Model()->NumberOfItems() == 0 )
        {
        index = 0;
        }
    itemRect.SetRect( view->ItemPos( index ), iAnimation->Size() );

    MAknsControlContext* cc = AknsDrawUtils::ControlContext( iControl );

    if( !cc )
        {
        cc = SkinBackgroundContext();
        }

    TBool ret = AknsDrawUtils::DrawBackground( AknsUtils::SkinInstance(), cc, iControl, aGc, TPoint(0,0),
                                          itemRect, KAknsDrawParamBottomLevelRGBOnly );
    _AKNTRACE_FUNC_EXIT;
    return ret;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::PostDeleteAnimation
// Schedules the animation for deletion by activating the extension itself.
// Deletion is postponed because in many error/failure occasions the caller has
// been animation and direct deletion is possibly not safe (because function
// stack would return through the deleted object).
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::PostDeleteAnimation()
    {
    _AKNTRACE_FUNC_ENTER;
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
    SetActive();
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::CreateAnimationL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::CreateAnimationL()
    {
    _AKNTRACE_FUNC_ENTER;
    DeleteAnim();

    // Check if derived class wants to disable highlight animation. Also, no
    // highlight animation on lists that don't have background
    if( ( KAknsIIDNone == iAnimIID ) ||
        !iListBoxData->IsBackgroundDrawingEnabled() )
        {
        _AKNTRACE("CreateAnimationL: derived class wants to disable hightlight"
                " or highlight animation on lists don't have background.");
        return;
        }

    // Create animation
    CCoeEnv* env = CCoeEnv::Static();
    env->AddForegroundObserverL( *this );

    iAnimation = CAknsEffectAnim::NewL( this );
    TBool ok = iAnimation->ConstructFromSkinL( iAnimIID );

    if( !ok ) // Animation for the ID was not found from the skin
        {
        _AKNTRACE("CreateAnimationL: Animation ID was not found from the skin.");
        User::Leave( KErrNotFound );
        }

    // Sync the local foreground flag state. Foreground state is stored locally
    // because calling AppUi::IsForeground causes WSERV flush (shocking) and
    // therefore it cannot be used in draw routines.
    CAknAppUi* aui = static_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi());
    iAnimFlags.Assign( EFlagHasForeground, aui->IsForeground() );

    Play();
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::DoResizeL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::DoResizeL(
    const TSize& aHighlightSize, TBool aAboutToStart )
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("DoResizeL: aHightlightSize=(%d,%d), aAboutToStart=%d",
            aHighlightSize.iWidth, aHighlightSize.iHeight, aAboutToStart);
    iAnimation->BeginConfigInputLayersL( aHighlightSize, aAboutToStart );

    if( iAnimation->InputRgbGc() )
        {
        DrawHighlightBackground( *iAnimation->InputRgbGc() );
        }

    iAnimation->EndConfigInputLayersL();
    _AKNTRACE_FUNC_EXIT;
    }

///////////handling TSubCellExt,start

TInt 
CFormattedCellListBoxDataExtension::AddSubCellExtL(TInt aSubCell)
    {
    TSubCellExt subcell;
    subcell.iSubCell=aSubCell;
    subcell.iLayoutAlign = ETrue; 

    TKeyArrayFix key(0,ECmpTInt);
    return iSubCellExtArray->InsertIsqL(subcell,key);   
    
    }

void 
CFormattedCellListBoxDataExtension::FindSubCellExtIndexOrAddL(
        TInt& aArrayIndex,
        TInt aSubCell)
    {
    if (FindSubCellExtIndex(aArrayIndex,aSubCell)==KErrNotFound)
        {
        aArrayIndex = AddSubCellExtL(aSubCell);
        //FindSubCellExtIndex(aArrayIndex,aSubCell);
        }
    }

void 
CFormattedCellListBoxDataExtension::SetSubCellLayoutAlignmentL(
        TInt aSubCellIndex )
    {
    TInt index = 0;
    FindSubCellExtIndexOrAddL(index,aSubCellIndex);     
    iSubCellExtArray->At(index).iLayoutAlign = EFalse;
    }  

 
TInt 
CFormattedCellListBoxDataExtension::FindSubCellExtIndex(
        TInt& aArrayIndex,
        TInt aSubCell) const
    {
    _AKNTRACE_FUNC_ENTER;
    if (aSubCell<0 || iSubCellExtArray->Count()==0)
        {
        _AKNTRACE("FindSubCellExtIndex: aSubCell<0 || iSubCellExtArray->Count==0");
        return(KErrNotFound);
        }
    TKeyArrayFix key(0,ECmpTInt);
    TSubCellExt subcell;
    subcell.iSubCell=aSubCell;
    TInt retVal = iSubCellExtArray->FindIsq(subcell,key,aArrayIndex);
    if (retVal != 0)
        {
        _AKNTRACE("FindSubCellExtIndex: retVal != 0");
        return KErrNotFound;
        }

    _AKNTRACE_FUNC_EXIT;
    return retVal;
    }

TBool 
CFormattedCellListBoxDataExtension::SubCellLayoutAlignment(
        TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellExtIndex(index,aSubCellIndex)==KErrNotFound)
        return (ETrue);
    return(iSubCellExtArray->At(index).iLayoutAlign);    
    }   

void CFormattedCellListBoxDataExtension::SmileyStillImageLoaded(
    CAknSmileyIcon* /*aSmileyIcon*/)
    {
    iControl->DrawDeferred();
    }

void CFormattedCellListBoxDataExtension::SmileyAnimationChanged( 
    CAknSmileyIcon* /*aSmileyIcon*/ )
    {
    }

///////////handling TSubCellExt,end

void CFormattedCellListBoxDataExtension::DrawPictographArea()
    {
    // This callback is never invoked, if iControl is NULL.
    iControl->DrawNow();
    }

void CFormattedCellListBoxDataExtension::CreateMarqueeControlL()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( !iMarquee )
        {
        iMarquee = CAknMarqueeControl::NewL();
        }

    if ( !i2ndLineMarquee )
        {
        i2ndLineMarquee = CAknMarqueeControl::NewL();
        }
    _AKNTRACE_FUNC_EXIT;
    }

TInt CFormattedCellListBoxDataExtension::RedrawEvent(TAny* aControl)
    {
    _AKNTRACE_FUNC_ENTER;
    if (!((CCoeControl*)aControl)->IsVisible())
        {
        _AKNTRACE("RedrawEvent: control is invisible, return");
        return EFalse;
        }
    CEikFormattedCellListBox* listBox = 
            (CEikFormattedCellListBox*)aControl;
    if (listBox->CurrentItemIndex() >= 0)
        {
        listBox->RedrawItem(listBox->CurrentItemIndex());
        }
    _AKNTRACE_FUNC_EXIT;
    return ETrue;
    }

TBool CFormattedCellListBoxDataExtension::IsMarqueeOn()
    {
    TBool isOn = EFalse;
    if (iMarquee)
        isOn = iMarquee->IsMarqueeOn();
    return isOn;
    }

TBool CFormattedCellListBoxDataExtension::DrawPressedDownEffect(MAknsSkinInstance* aInstance, 
                                                               CWindowGc& aGc, 
                                                                const TRect& aOutRect,
                                                                const TRect& aInnerRect ) const
    {
    return AknsDrawUtils::DrawFrame( aInstance,
                                     aGc,
                                     aOutRect,
                                     aInnerRect,
                                     KAknsIIDQsnFrListPressed,
                                     KAknsIIDQsnFrListCenterPressed );
    }

void CFormattedCellListBoxDataExtension::DrawSmileyWithText( CWindowGc& aGc,
                                                             const TDesC& aSmileyText,
                                                             const TAknLayoutText& aLayout,
                                                             TBool aUseLogicalToVisualConversion,
                                                             const TRgb& aColor )
    {
    __ASSERT_DEBUG( iSmileyMan, Panic(EAknPanicObjectNotFullyConstructed));
    TInt l = Min( aLayout.Font()->TextWidthInPixels(KPlaceHolder), 
                  aLayout.Font()->HeightInPixels() );
    TSize s(l,l);
    if ( iSmileySize != s )
        {
        iSmileyMan->SetSize( s );
        iSmileySize = s;
        }
    aGc.SetPenColor( aColor ); // SmileyManager's DrawText does not accept aColor...
    iSmileyMan->DrawText( aGc, aSmileyText, aLayout, aUseLogicalToVisualConversion );
    }
TInt CFormattedCellListBoxDataExtension::ConvertTextToSmiley( TDes& aText)
    {
    __ASSERT_DEBUG( iSmileyMan, Panic(EAknPanicObjectNotFullyConstructed));
    TInt count = 0;
    TRAPD( err, count = iSmileyMan->ConvertTextToCodesL( aText )) ;
    return err == KErrNone ? count : err;
    }


// -----------------------------------------------------------------------------
// CFormattedCellListBoxDataExtension::LoadMarkingIconsL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxDataExtension::LoadMarkingIconsL()
    {
    if ( !iMarkingIconArray )
        {
        iMarkingIconArray = new ( ELeave ) CAknIconArray( 
                KMarkingModeIconArraySize );
        }
    else
        {
        iMarkingIconArray->ResetAndDestroy();
        }

    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    const TDesC& avkonIconFile = AknIconUtils::AvkonIconFileName();

    CGulIcon* icon = AknsUtils::CreateGulIconL( skin, 
            KAknsIIDQgnPropCheckboxOn, 
            avkonIconFile, 
            EMbmAvkonQgn_prop_checkbox_on, 
            EMbmAvkonQgn_prop_checkbox_on_mask );
    
    CleanupStack::PushL( icon );
    iMarkingIconArray->AppendL( icon );
    CleanupStack::Pop( icon );

    icon = AknsUtils::CreateGulIconL( skin, 
            KAknsIIDQgnPropCheckboxOff, 
            avkonIconFile, 
            EMbmAvkonQgn_prop_checkbox_off, 
            EMbmAvkonQgn_prop_checkbox_off_mask );

    CleanupStack::PushL( icon );
    iMarkingIconArray->AppendL( icon );
    CleanupStack::Pop( icon );
    }


EXPORT_C CCoeControl *CFormattedCellListBoxData::Control() const 
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iControl;
    }

EXPORT_C void CFormattedCellListBoxData::SetSeparatorLinePosition(TAknSeparatorLinePosition aPosition)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iSeparatorLinePosition = aPosition;
    }
EXPORT_C TAknSeparatorLinePosition CFormattedCellListBoxData::SeparatorLinePosition() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iSeparatorLinePosition;
    }
EXPORT_C CAknLayoutData *CFormattedCellListBoxData::LayoutData() const
    {
        return NULL;
    }

EXPORT_C TBool CFormattedCellListBoxData::LayoutInit() const
    {
    return EFalse;
    }
EXPORT_C void CFormattedCellListBoxData::SetLayoutInit(TBool /*aValue*/)
    {
    }

CFormattedCellListBoxDataExtension *CFormattedCellListBoxData::Extension() { return iExtension; }
CFormattedCellListBoxDataExtension *CFormattedCellListBoxData::Extension() const { return iExtension; }

EXPORT_C void CFormattedCellListBoxData::SetControl(CCoeControl *aControl)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->SetControl( aControl );
    }

EXPORT_C MAknsControlContext* CFormattedCellListBoxData::SkinBackgroundContext() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iSkinEnabled)
        {
        if (iExtension->iPopupFrame)
            {
            return iExtension->iPopupFrame;
            }
        else
            {
            return iExtension->iSkinControlContext;
            }
        }
    else
        {
        return NULL;
        }
    }


EXPORT_C void CFormattedCellListBoxData::SetSkinEnabledL(TBool aEnabled)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    CListBoxData::SetSkinEnabledL(aEnabled);
    iExtension->iSkinEnabled = aEnabled;
    }

EXPORT_C TBool CFormattedCellListBoxData::SkinEnabled() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iSkinEnabled;
    }

EXPORT_C void CFormattedCellListBoxData::SetSkinStyle(const TAknsItemID *id, const TRect &aTileRect)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iSkinControlContext)
        {
        iExtension->iSkinControlContext->SetTiledBitmap(*id);
        iExtension->iSkinControlContext->SetTiledRect(aTileRect);
        }
    }
EXPORT_C void CFormattedCellListBoxData::SetSkinParentPos(const TPoint &aPos)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iSkinControlContext)
        {
        iExtension->iSkinControlContext->SetParentPos(aPos);
        }
    }
EXPORT_C void CFormattedCellListBoxData::SetBackgroundSkinStyle(const TAknsItemID *aId, const TRect &aRect)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iSkinControlContext)
        {
        iExtension->iSkinControlContext->SetBitmap(*aId);
        iExtension->iSkinControlContext->SetRect(aRect);
        }
    }
EXPORT_C void CFormattedCellListBoxData::SetListEndSkinStyle(const TAknsItemID *aListEndId, const TRect &aRect)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iSkinControlContext)
        {
        iExtension->iSkinControlContext->SetBottomBitmap(*aListEndId);
        iExtension->iSkinControlContext->SetBottomRect(aRect);
        }
    }

EXPORT_C void CFormattedCellListBoxData::SetSkinHighlightFrame(const TAknsItemID *aFrameId, const TAknsItemID *aFrameCenterId)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iSkinHighlightFrameId = aFrameId;
    iExtension->iSkinHighlightFrameCenterId = aFrameCenterId;
    }
    
EXPORT_C void CFormattedCellListBoxData::SetSkinPopupFrame(const TAknsItemID *aFrameId, const TAknsItemID *aFrameCenterId)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( iExtension->iPopupFrame)
        {
        iExtension->iPopupFrame->SetFrame(*aFrameId);
        iExtension->iPopupFrame->SetCenter(*aFrameCenterId);
        }
    else
        {
        TRAPD(err, iExtension->iPopupFrame = CAknsFrameBackgroundControlContext::NewL(
            KAknsIIDNone,
            TRect(0,0,1,1), // these must be set by using SetSkinPopupFramePosition
            TRect(0,0,1,1),
            EFalse ) );
        if (!err)
            {
            iExtension->iPopupFrame->SetFrame(*aFrameId);
            iExtension->iPopupFrame->SetCenter(*aFrameCenterId);
            }
        }
    }
    
EXPORT_C void CFormattedCellListBoxData::SetSkinPopupFramePosition(const TRect &aOuterRect, const TRect &aInnerRect)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( iExtension->iPopupFrame)
        iExtension->iPopupFrame->SetFrameRects(aOuterRect, aInnerRect);
    }

EXPORT_C void CFormattedCellListBoxData::UseLogicalToVisualConversion(
    TBool aUseConversion )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iUseLogicalToVisualConversion = aUseConversion;
    }

void CFormattedCellListBoxData::CreatePictographInterfaceL()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->CreatePictographInterfaceL();
    }

void CFormattedCellListBoxData::CreateMarqueeControlL()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TCallBack callBack(CFormattedCellListBoxDataExtension::RedrawEvent, iExtension->iControl);
    //iExtension->iMarquee = CAknMarqueeControl::NewL();
    iExtension->CreateMarqueeControlL();
    iExtension->iMarquee->SetRedrawCallBack(callBack);
    iExtension->i2ndLineMarquee->SetRedrawCallBack(callBack);
    }

const TInt KSubCellListBoxGranularity=4;
const TInt KNoActualSubCellFont=-1;

EXPORT_C
CFormattedCellListBoxData* CFormattedCellListBoxData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CFormattedCellListBoxData* self=new(ELeave) CFormattedCellListBoxData;
    self->ConstructLD( KAknsIIDQsnAnimList );
    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

EXPORT_C
CPopupFormattedListBoxData* CPopupFormattedListBoxData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CPopupFormattedListBoxData* self=new(ELeave) CPopupFormattedListBoxData;
    self->ConstructLD( KAknsIIDQsnAnimList );

    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

EXPORT_C
CFormattedCellGridData* CFormattedCellGridData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CFormattedCellGridData* self=new(ELeave) CFormattedCellGridData;
    self->ConstructLD( KAknsIIDQsnAnimGrid );
    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

EXPORT_C
CSettingItemEditingListBoxData* CSettingItemEditingListBoxData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CSettingItemEditingListBoxData* self=new(ELeave) CSettingItemEditingListBoxData;
    self->ConstructLD( KAknsIIDQsnAnimSetOptFoc );
    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

EXPORT_C
CFormGraphicListBoxData* CFormGraphicListBoxData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CFormGraphicListBoxData* self=new(ELeave) CFormGraphicListBoxData;
    self->ConstructLD( KAknsIIDQsnAnimList );
    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

EXPORT_C 
CFormattedCellListBoxData::~CFormattedCellListBoxData()
    {
    _AKNTRACE_FUNC_ENTER;
    delete iExtension;
    delete iSubCellArray;
    if (iIconArray)
        {
        iIconArray->ResetAndDestroy();
        delete iIconArray;
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TSize 
CFormattedCellListBoxData::SubCellSize(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TSize(0,0);
    return(iSubCellArray->At(index).iSize);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellSizeL(TInt aSubCellIndex, TSize aSize)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iSize=aSize;
    // if someone uses this api directly, revert to old draw
    // new api will turn this to ETrue again.
    UseScalableLayoutData( EFalse );
    }


EXPORT_C TInt 
CFormattedCellListBoxData::SubCellBaselinePos(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TInt(0);
    return(iSubCellArray->At(index).iBaseline);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellBaselinePosL(TInt aSubCellIndex, TInt aPos)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iBaseline=aPos;
    }


EXPORT_C TInt 
CFormattedCellListBoxData::SubCellTextClipGap(TInt aSubCellIndex) const
    {
    TInt index;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TInt(0);
    return(iSubCellArray->At(index).iTextClipGap);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellTextClipGapL(TInt aSubCellIndex, TInt aGap)
    {
    TInt index;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iTextClipGap=aGap;
    }

TSize 
CFormattedCellListBoxData::SubCellRealSize(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TSize(0,0);
    return(iSubCellArray->At(index).iRealSize);
    }

void 
CFormattedCellListBoxData::SetSubCellRealSize(TInt aSubCellIndex, TSize aRealSize) const
    {
    TInt index = 0;
    if (!(FindSubCellIndex(index, aSubCellIndex)==KErrNotFound))
        {
        MUTABLE_CAST(TSize&,At(index).iRealSize)=aRealSize;
        }
    }

TSize 
CFormattedCellListBoxData::SubCellRealTextSize(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TSize(0,0);
    return(iSubCellArray->At(index).iRealTextSize);
    }

void 
CFormattedCellListBoxData::SetSubCellRealTextSize(TInt aSubCellIndex, TSize aRealTextSize) const
    {
    TInt index = 0;
    if (!(FindSubCellIndex(index, aSubCellIndex)==KErrNotFound))
        {
        MUTABLE_CAST(TSize&,At(index).iRealTextSize)=aRealTextSize;
        }
    }

EXPORT_C TPoint 
CFormattedCellListBoxData::SubCellPosition(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return TPoint(0,0);
    return(iSubCellArray->At(index).iPosition);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellPositionL(TInt aSubCellIndex, TPoint aPosition)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iPosition=aPosition;
    // if someone uses this api directly, revert to old draw
    // new api will turn this to ETrue again.
    UseScalableLayoutData( EFalse );
    }

EXPORT_C TMargins 
CFormattedCellListBoxData::SubCellMargins(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound) 
        {
        TMargins tm = {0,0,0,0};
        return tm;
        }
    return(iSubCellArray->At(index).iMargin);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellMarginsL(TInt aSubCellIndex, TMargins aMargins)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iMargin=aMargins;
    }

EXPORT_C const CFont* 
CFormattedCellListBoxData::SubCellFont(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return 0;
    return(iSubCellArray->At(index).iBaseFont);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellFontL(TInt aSubCellIndex, const CFont* aFont)
    {
#if 0
    TInt subcells=iSubCellArray->Count();
#endif
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    if (At(index).iBaseFont != aFont)
        {
#if 0
        TInt actualFontIndex=0;
        TRAPD(err, actualFontIndex=AddActualFontL(aFont));
        if (err)
            {
            if (subcells!=iSubCellArray->Count())
                {
                iSubCellArray->Delete(index);
                }
            User::Leave(err);
            }
        At(index).iActualFontIndex=actualFontIndex;
#endif
        At(index).iBaseFont=aFont;
        }
    }

EXPORT_C CGraphicsContext::TTextAlign 
CFormattedCellListBoxData::SubCellAlignment(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return CGraphicsContext::ELeft;
    return(iSubCellArray->At(index).iAlign);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellAlignmentL(TInt aSubCellIndex, CGraphicsContext::TTextAlign aAlign)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iAlign=aAlign;

    iExtension->SetSubCellLayoutAlignmentL( aSubCellIndex );
    }


EXPORT_C const CFormattedCellListBoxData::TColors & 
CFormattedCellListBoxData::SubCellColors(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex) == KErrNotFound) return defaultcolors;
    return(iSubCellArray->At(index).iColors);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellColorsL(TInt aSubCellIndex, const TColors & aColors)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iColors=aColors;
    At(index).iUseSubCellColors = ETrue;
    }

EXPORT_C TBool CFormattedCellListBoxData::UseSubCellColors(TInt aSubCell) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index, aSubCell)==KErrNotFound) return EFalse;
    return At(index).iUseSubCellColors;
    }


EXPORT_C CGraphicsContext::TPenStyle 
CFormattedCellListBoxData::SubCellRightSeparatorStyle(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return CGraphicsContext::ENullPen;
    return(iSubCellArray->At(index).iRightSeparatorStyle);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetSubCellRightSeparatorStyleL(TInt aSubCellIndex, CGraphicsContext::TPenStyle aStyle)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iRightSeparatorStyle=aStyle;
    }


EXPORT_C TBool 
CFormattedCellListBoxData::SubCellIsGraphics(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return EFalse;
    return(iSubCellArray->At(index).iGraphics);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetGraphicsSubCellL(TInt aSubCellIndex, TBool aIsGraphics)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iGraphics=aIsGraphics;
    // if someone uses this api directly, revert to old draw
    // new api will turn this to ETrue again.
    UseScalableLayoutData( EFalse );
    }


EXPORT_C TBool 
CFormattedCellListBoxData::SubCellIsNumberCell(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return EFalse;
    return(iSubCellArray->At(index).iNumberCell);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetNumberCellL(TInt aSubCellIndex, TBool aIsNumberCell)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iNumberCell=aIsNumberCell;
    }



EXPORT_C TBool 
CFormattedCellListBoxData::SubCellIsTransparent(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return EFalse;
    return(iSubCellArray->At(index).iTransparent);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetTransparentSubCellL(TInt aSubCellIndex, TBool aIsTransparent)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iTransparent=aIsTransparent;
    }


EXPORT_C TBool 
CFormattedCellListBoxData::SubCellIsNotAlwaysDrawn(TInt aSubCellIndex) const
    {
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)==KErrNotFound)
        return EFalse;
    return(iSubCellArray->At(index).iNotAlwaysDrawn);
    }

EXPORT_C void 
CFormattedCellListBoxData::SetNotAlwaysDrawnSubCellL(TInt aSubCellIndex, TBool aIsNotAlwaysDrawn)
    {
    TInt index = 0;
    FindSubCellIndexOrAddL(index,aSubCellIndex);
    At(index).iNotAlwaysDrawn=aIsNotAlwaysDrawn;
    }

EXPORT_C CArrayPtr<CGulIcon>* 
CFormattedCellListBoxData::IconArray() const
    {
    return iIconArray;
    }

EXPORT_C void
CFormattedCellListBoxData::SetIconArrayL(CArrayPtr<CGulIcon>* aArray)
    {
    iIconArray=aArray;
    }

EXPORT_C void
CFormattedCellListBoxData::SetIconArray(CArrayPtr<CGulIcon>* aArray)
    {
    iIconArray=aArray;
    }


EXPORT_C TBool CFormattedCellListBoxData::RespectFocus() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iRespectFocus;
    }

EXPORT_C void CFormattedCellListBoxData::SetRespectFocus(TBool aBool)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iRespectFocus = aBool;
    }

EXPORT_C CFont* 
CFormattedCellListBoxData::Font(const TListItemProperties& /*aItemProperties*/,
                   TInt aSubCellIndex) const
    {
    return const_cast<CFont*>(SubCellFont(aSubCellIndex));
#if 0
    TInt index = 0;
    if (FindSubCellIndex(index,aSubCellIndex)!=0/*KErrNotFound*/)
        return(NULL);
    TInt actualFontIndex=iSubCellArray->At(index).iActualFontIndex;
    if (actualFontIndex==KNoActualSubCellFont)
        return(NULL);
    if ((aItemProperties.IsBold()) && (aItemProperties.IsItalics()))
        {
        return iBoldItalicFont.iFonts->At(actualFontIndex);
        }
    else if (aItemProperties.IsBold())
        {
        return iBoldFont.iFonts->At(actualFontIndex);
        }
    else if (aItemProperties.IsItalics())
        {
        return iItalicFont.iFonts->At(actualFontIndex);
        }
    else return iNormalFont.iFonts->At(actualFontIndex);
#endif
    }

EXPORT_C
void CFormattedCellGridData::Draw( TListItemProperties aProperties,
                                   CWindowGc& aGc,
                                   const TDesC* aText,
                                   const TRect& aRect,
                                   TBool aHighlight,
                                   const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("Draw: aText=%S, aRect=(%d,%d,%d,%d)",
            aText, aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY);
    //
    // Grid highlight!
    //
    CListBoxView* view = static_cast<CEikListBox*>( Extension()->iControl )->View();
    TBool pressedDown = view->ItemDrawer()->Flags() & CListItemDrawer::EPressedDownState;

#ifdef RD_UI_TRANSITION_EFFECTS_LIST  
    MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal(&aGc);
    if( aHighlight )
        {
        if ( transApi )
            {
            transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight );
            transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aRect );
            transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
            }
        TAknLayoutRect hiliCenter;
        TBool windowFrameDrawn = EFalse;
        
        hiliCenter.LayoutRect( aRect, AknLayoutScalable_Avkon::cell_highlight_pane_g1() );
        aGc.SetPenStyle(CGraphicsContext::ENullPen);

        // Try drawing the animated highlight
        if ( Extension()->iAnimation )
            {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST        
            if ( transApi && transApi->VerifyKml() == KErrNone )
                {
                Extension()->DeleteAnim();
                }
            else
                {
            windowFrameDrawn = Extension()->SyncAndDrawAnim( aGc, aRect );
                }
#else //RD_UI_TRANSITION_EFFECTS_LIST 
            windowFrameDrawn = Extension()->SyncAndDrawAnim( aGc, aRect );
#endif
            }
        
        if( !windowFrameDrawn )
            {
            // Animated highlight was not available, use normal skinned
            // rendering.
            MAknsSkinInstance *skin = AknsUtils::SkinInstance();
            MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() );
            CListBoxView* view = static_cast<CEikListBox*>( Extension()->iControl )->View();
            if ( pressedDown )
                {
                windowFrameDrawn = AknsDrawUtils::DrawFrame( skin, 
                                                             aGc, 
                                                             aRect, 
                                                             hiliCenter.Rect(), 
                                                             KAknsIIDQsnFrGridPressed, 
                                                             KAknsIIDQsnFrGridCenterPressed);
                }
            else
                {
            if (!cc) cc = SkinBackgroundContext();
            if (cc)
                {
                windowFrameDrawn = AknsDrawUtils::DrawFrame(skin, 
                                                            aGc, 
                                                            aRect, 
                                                            hiliCenter.Rect(), 
                                                            KAknsIIDQsnFrGrid, 
                                                            KAknsIIDQsnFrGridCenter);
                    }
                }
            }
        
        // Both animated highlight and normal highlight drawing have failed.
        if (!windowFrameDrawn)
            {
            aGc.SetPenStyle( CGraphicsContext::ESolidPen );
            aGc.SetPenColor( KRgbBlack );
            aGc.DrawRect( aRect );
            }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST 
        if ( transApi )
            {
            transApi->StopDrawing();
            transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
            }
#else //RD_UI_TRANSITION_EFFECTS_LIST
        }
    else // Draw without highlight
        {
        aGc.SetPenColor(aColors.iBack);
#endif //RD_UI_TRANSITION_EFFECTS_LIST
        }
#endif
    DrawFormatted(aProperties, aGc, aText, aRect, aHighlight, aColors);
    _AKNTRACE_FUNC_EXIT;
    }


EXPORT_C
void CSettingItemEditingListBoxData::Draw( TListItemProperties aProperties,
                                           CWindowGc& aGc,
                                           const TDesC* aText,
                                           const TRect& aRect,
                                           TBool aHighlight,
                                           const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("Draw: aText=%S, aRect=(%d,%d,%d,%d)",
            aText, aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY); 
    //
    // Setting item editing highlight!
    //
    MAknsSkinInstance *skin = AknsUtils::SkinInstance();
    CCoeControl* control = Control();
    // When this flag set, draw pressed down state and don't use animation.
    // There are several derived CListboxData in this file. All of them do  
    // this same thing.
    CListBoxView* view = static_cast<CEikListBox*>( Extension()->iControl )->View();
    TBool pressedDown = view->ItemDrawer()->Flags() & CListItemDrawer::EPressedDownState;
    
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( &aGc );
#endif

    TBool highlightDraw = EFalse;
    
    if ( control )
        {
        // Get context from setting page.
        MAknsControlContext *context = AknsDrawUtils::ControlContext( control );

        if ( !context )
            {
            context = SkinBackgroundContext();
            }

        const MCoeControlBackground* backgroundDrawer =
            control->FindBackground();

        if (context)
            {

            if (aHighlight)
                {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                if ( transApi )
                    {
                    transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight );
                    transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aRect );
                    transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
                    }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                if ( Extension()->iAnimation )
                    {
                    highlightDraw = Extension()->SyncAndDrawAnim( aGc, aRect );
                    }

                if( !highlightDraw )
                    {
                    TAknLayoutRect innerRect;
                    innerRect.LayoutRect( aRect, AknLayoutScalable_Avkon::list_highlight_pane_g1_cp1().LayoutLine() );
                    if ( pressedDown )
                        {
                        highlightDraw = Extension()->DrawPressedDownEffect( skin, aGc, aRect, innerRect.Rect());
                        }
                    else
                        {
                        highlightDraw = AknsDrawUtils::DrawFrame( skin, aGc,
                                                                  aRect, innerRect.Rect(),
                                                                  KAknsIIDQsnFrSetOptFoc, KAknsIIDQsnFrSetOptFocCenter );
                        }
                    }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                if ( transApi )
                    {
                    transApi->StopDrawing();
                    transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
                    }
                }
            if ( IsBackgroundDrawingEnabled() )
                {
                // Must always draw background if effects are turned on to remove highlight
                // edges from background
                if ( transApi && !transApi->EffectsDisabled() )
                    {
                    highlightDraw = ETrue;
                    if ( transApi->StartDrawing( MAknListBoxTfxInternal::EListView ) )
                        {
                        if ( !backgroundDrawer )
						    {
                            highlightDraw = AknsDrawUtils::Background( skin, context, control, aGc, aRect );
                            }
                        }
                    transApi->StopDrawing();
                    }
                else if ( !aHighlight )
                    {
                    if ( !backgroundDrawer )
                        {
                        highlightDraw = AknsDrawUtils::Background( skin, context, control, aGc, aRect );
                        }
                    else
                        {
                        highlightDraw = ETrue;
                        }
                    }
                }
#else
                }
            else if( IsBackgroundDrawingEnabled() )
                {
                if ( !backgroundDrawer )
                    {
                    highlightDraw = AknsDrawUtils::Background( skin, context, control, aGc, aRect );
                    }
                else
                    {
                    highlightDraw = ETrue;
                    }
                }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            }
        }

    if (!highlightDraw)
        {
        if (!IsBackgroundDrawingEnabled())
            {
            if ( aHighlight )
                {
                aGc.SetBrushColor(aColors.iHighlightedBack);
                aGc.Clear(aRect);
                }
            }
        else
            {
            if ( aHighlight )
                {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                if ( transApi)
                    {
                    transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aRect );
                    transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
                    }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                aGc.SetBrushColor(aColors.iHighlightedBack);
                }
            else
                {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                if ( transApi)
                    {
                    transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
                    }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                aGc.SetBrushColor(aColors.iBack);
                }
            aGc.Clear(aRect);
#ifdef RD_UI_TRANSITION_EFFECTS_LIST  
            if ( transApi )
                {
                transApi->StopDrawing();
                if ( aHighlight )
                    {
                    transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
            }
        }
#endif
            }
        }

    HBufC* buf = NULL;
    
    if ( aHighlight && UseHighlightIconSwapping() )
        {
        /*
        * list item string format: "1\tShortLabel"
        * list item string format: "\t\tLongLabel"
        */
        buf = HBufC::New( aText->Size() + 1 ); // iconindex 9+1 causes length change

        if ( buf )
            {
            TPtrC text;
            
            TextUtils::ColumnText( text, 0, aText );
            TLex lex( *aText );
            TInt index;

            if ( lex.Val( index ) == KErrNone && index != KColorIconFlag )
                {
                index += 2;
                TextUtils::ColumnText( text, 1, aText );
                buf->Des().Format(_L("%d\t"), index );
                buf->Des().Append( text );
                }
            else
                {
                delete buf;
                buf = NULL;
                }
            }
        }

    DrawFormatted(aProperties, aGc, buf ? buf : aText, aRect, aHighlight, aColors);

    if ( buf )
        {
        delete buf;
        }
    _AKNTRACE_FUNC_EXIT;
    }


EXPORT_C
void CFormGraphicListBoxData::Draw( TListItemProperties aProperties,
                                    CWindowGc& aGc,
                                    const TDesC* aText,
                                    const TRect& aRect,
                                    TBool aHighlight,
                                    const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    // Call the base class. This is pretty safe since although layout data
    // components for highlight are different those will in practise always
    // have the same values -> quite a lot of duplicate code is avoided.
    CFormattedCellListBoxData::Draw( aProperties, aGc, aText, aRect, aHighlight, aColors );
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CFormattedCellListBoxData::Draw(TListItemProperties aProperties, CWindowGc& aGc,const TDesC* aText,const TRect& aRect,TBool aHighlight, const TColors& aColors) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("Highlight width: %d, (%d,%d)", aRect.Width(), aRect.iTl.iX, aRect.iBr.iX );
    DrawDefaultHighlight(aGc, aRect, aHighlight);

    // Draw the actual items.
    DrawFormatted(aProperties,aGc,aText,aRect,aHighlight,aColors);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void 
CFormattedCellListBoxData::DrawFormatted( TListItemProperties aProperties,
                                          CWindowGc& aGc,
                                          const TDesC* aText,
                                          const TRect& aItemRect,
                                          TBool aHighlight,
                                          const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("DrawFormatted: aItemRect=(%d,%d,%d,%d)",
            aItemRect.iTl.iX, aItemRect.iTl.iY, aItemRect.iBr.iX, 
            aItemRect.iBr.iY);
    
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    __ASSERT_DEBUG( iExtension->iControl, Panic( EAknPanicNullPointer ));

    CEikListBox* listbox = static_cast<CEikListBox*>( iExtension->iControl ); 
    CListBoxView* view = listbox->View();

    if (!view->ViewRect().Intersects(aItemRect))
        {
        // outside of the clipping rect -> don't process this item
        return;
        }

    if ( aHighlight )
        {
        iExtension->iClippedSubcells = 0;
        }

    TBool backgroundDrawingSuppressed = listbox->BackgroundDrawingSuppressed();
    
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( &aGc );
    if ( transApi && !backgroundDrawingSuppressed )
        {
        transApi->StartDrawing( MAknListBoxTfxInternal::EListItem );
        if(transApi->EffectsDisabled())
            {
            aGc.SetClippingRect( view->ViewRect() );
            }
        }
#else
    if ( !backgroundDrawingSuppressed )
        {
        aGc.SetClippingRect( view->ViewRect() );
        }
#endif //RD_UI_TRANSITION_EFFECTS_LIST
    TRect vr(view->ViewRect());
    _AKNTRACE("Clipping: Width %d, (%d,%d)", vr.Width(), vr.iTl.iX, vr.iBr.iX );
    if ( UsesScalableLayoutData() )
        {
        /* this is a AvKon list or list is created using methods in aknlists.cpp
        * which is _the_ way to set up a list
        */
        DrawFormattedSimple( aProperties, aGc, aText, aItemRect, aHighlight, aColors );
        }
    else
        {
        /* someone used directly the (unfortunately) exported methods
        * from this file. These should be fixed in such way, that
        * DrawFormattedOld could be removed.
        */
        DrawFormattedOld( aProperties, aGc, aText, aItemRect, aHighlight, aColors );
        }

#ifdef RD_UI_TRANSITION_EFFECTS_LIST  
    if ( transApi && !backgroundDrawingSuppressed )
        {        
        if(transApi->EffectsDisabled())
            {
            aGc.CancelClippingRect();
            }

        transApi->StopDrawing();
        }
#else
    if ( !backgroundDrawingSuppressed )
        {
        aGc.CancelClippingRect();
        }
#endif //RD_UI_TRANSITION_EFFECTS_LIST 
    _AKNTRACE_FUNC_EXIT;
    }


void
CFormattedCellListBoxData::BitBltColored( CWindowGc&      aGc,
                                          TBool           aHighlight,
                                          const CGulIcon* aIcon,
                                          TInt            aSubcell,
                                          TBool           aColorIcon,
                                          const TRect&    aGraphicRect ) const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    // se also eikclbd.cpp ( sigh ).
    CFbsBitmap* bitmap( aIcon->Bitmap() );
    CFbsBitmap* mask( aIcon->Mask() );

    // possibly colorskinnable icon. Check must be after SetSize()
    TBool bw( bitmap->DisplayMode() == EGray2 ); 
    
    // center graphics
    TSize size=bitmap->SizeInPixels();
    TInt yDiff = ( aGraphicRect.Height() - size.iHeight ) / 2;
    TInt xDiff = ( aGraphicRect.Width()  - size.iWidth )  / 2;
    TPoint posInBitmap( 0,0 );

    if (xDiff < 0) // icon's width bigger than subcell's width
        {          // possible, if icon is not a aknicon
        posInBitmap.iX = -xDiff;
        xDiff = 0;
        }
    
    if (yDiff < 0) // icon's height bigger than subcell's height
        {
        posInBitmap.iY = -yDiff;
        yDiff = 0;
        }
    
    TPoint bmpPos( aGraphicRect.iTl + TPoint( xDiff, yDiff ) );
    TRect sourcerect( posInBitmap, aGraphicRect.Size() );

    if ( mask )
        {
        TInt i( 0x01 );
        i = i << aSubcell;
        if ( ((i & iExtension->iConditionalCells) && bw) || aColorIcon  )
            {
            aGc.BitBltMasked( bmpPos,
                              aHighlight ? iExtension->iHiliBmp : iExtension->iColorBmp,
                              TRect(posInBitmap, size), mask, ETrue );
            }
        else
            {
            aGc.BitBltMasked( bmpPos, bitmap, sourcerect, mask, ETrue );
            }
        }
    else
        {
        aGc.BitBlt( bmpPos, bitmap ,sourcerect );
        }
    }

    
void 
CFormattedCellListBoxData::DrawFormattedSimple( TListItemProperties& aProperties,
                                                CWindowGc& aGc,
                                                const TDesC* aText,
                                                const TRect& aItemRect,
                                                TBool aHighlight,
                                                const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("DrawFormattedSimple: aItemRect=(%d,%d,%d,%d)",
            aItemRect.iTl.iX, aItemRect.iTl.iY, aItemRect.iBr.iX, 
            aItemRect.iBr.iY);
    
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    TRect textRect(aItemRect);
    DrawMarkingModeIcons( aProperties, aGc, textRect );
    
    const TColors *subcellColors = &aColors;

    TInt lastSubCell = Min( LastSubCell(), KMaxSubCellIndex );

    TInt subcell=0;
    TPtrC text;
    TPtrC tempText;
    TRect textShadowRect;           // For transparent list
    TRgb textShadowColour = AKN_LAF_COLOR_STATIC(215);    // Black shadow for item text.

    MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() );
    if (!cc)
        {
        cc = SkinBackgroundContext();
        }

    TAknTextLineLayout textLines[KMaxSubCellIndex];
    TBool rectClipped[KMaxSubCellIndex];
    
    Mem::FillZ( &rectClipped[0], KMaxSubCellIndex * sizeof( TBool ) );
    
    if ( iExtension->iSubCellsMightIntersect )
        {
        CheckIfSubCellsIntersect( &textLines[0], &rectClipped[0], *aText, textRect );
        }

    TInt SCindex=0;

    // This loop does the drawing.    
    aGc.SetPenStyle(CGraphicsContext::ENullPen);
    subcell=0;
    FOREVER
        {        
        if (subcell>lastSubCell)
            {
            break;
            }
        
        TextUtils::ColumnText(text,subcell, aText);
        if (text == KNullDesC)
            {
            // empty subcell, continue to draw next subcell
            ++ subcell;
            continue;
            }

        if (iExtension->FindSLSubCellIndex(SCindex,subcell)!=0) break;

        if (UseSubCellColors(subcell))
            {
            subcellColors = &SubCellColors(subcell);
            }
        else
            {
            subcellColors = &aColors;
            }
            
        TRgb color;
        CListBoxView* view = static_cast<CEikListBox*>( Control() )->View();
        TBool useOverrideColor = view->ItemDrawer()->Flags() & CListItemDrawer::EUseOverrideSkinTextColor; 
        if (aHighlight)
            {
            color = subcellColors->iHighlightedText;
            aGc.SetBrushColor(subcellColors->iHighlightedBack); 
            if ( AknsUtils::AvkonSkinEnabled() && !useOverrideColor )
                {
                if ( iExtension->iHighlightedTextColor != NULL )
                    {
                    color = iExtension->iHighlightedTextColor;
                    }
                }
            }
        else
            {
            color = subcellColors->iText;
            aGc.SetBrushColor(subcellColors->iBack);
            if ( AknsUtils::AvkonSkinEnabled() && !useOverrideColor )
                {
                if ( iExtension->iTextColor != NULL )
                    {
                    color = iExtension->iTextColor;
                    }
                }
            }
        
        // graphics or text column
        if (iExtension->SLAt(SCindex).iSubCellType == CFormattedCellListBoxDataExtension::EAknSLText)
            {
            const CFont* rowAndCellFont=RowAndSubCellFont(iExtension->iCurrentlyDrawnItemIndex,subcell);
            const CFont* cellFont=Font(aProperties, subcell);
            const CFont* tempFont=(cellFont) ? cellFont : NULL;
            const CFont* usedFont=(rowAndCellFont) ? rowAndCellFont : tempFont;
            
            TAknTextLineLayout textLineLayout = NULL;

            if ( rectClipped[subcell] )
                {
                textLineLayout = textLines[subcell];
                }
            else
                {
                // check if there are icons affecting this text layout
                TInt gSC = iExtension->SLAt(SCindex).iConditionValue; // graphical subcell which might affect this text subcell
                
                if (gSC > -1)
                    {
                    TInt tempIndex;
                    while (gSC > -1) // when gSC == -1, we have found our graphical subcell
                        {
                        if (iExtension->FindSLSubCellIndex(tempIndex,gSC)!=0) break;
                        TextUtils::ColumnText(tempText,gSC, aText);
                        if (tempText != KNullDesC)
                            {
                            textLineLayout = iExtension->SLAt(tempIndex).iTextLayout;
                            break;                      
                            }
                        gSC = iExtension->SLAt(tempIndex).iConditionValue;
                        }
                    }
                    
                if (gSC == -1) // no affecting icons -> use default layout
                    {
                    textLineLayout = iExtension->SLAt(SCindex).iTextLayout;
                    }
                }

                      
            CGraphicsContext::TTextAlign align=SubCellAlignment(subcell); //gumq
            TBool isLayoutAlignment = iExtension->SubCellLayoutAlignment(subcell); //gumq  
            if( !isLayoutAlignment )
                { 
                switch(align) 
                    {
                    case CGraphicsContext::ELeft : 
                        {
                        textLineLayout.iJ = ELayoutAlignLeft;    
                        }
                        break; 
                    case CGraphicsContext::ECenter: 
                        {
                        textLineLayout.iJ = ELayoutAlignCenter;
                        }
                        break; 
                    case CGraphicsContext::ERight:  
                        {
                        textLineLayout.iJ = ELayoutAlignRight;
                        } 
                        break; 
                    default:  break;
                    }; 
                }    
                
            TAknLayoutText textLayout;
            textLayout.LayoutText(textRect, textLineLayout, usedFont);

            SetUnderlineStyle( aProperties, aGc, subcell );

            // * 2 == leave some room for marquee
            const TInt maxlen( KMaxColumnDataLength * 3 );
            TBuf<maxlen> convBuf = text.Left(maxlen);
            TBool smileyDraw = EFalse;
            // do smiley convert before clipping. don't worry marquee now.            
            if ( iExtension->iSmileyMan && 
                 iExtension->SLAt(SCindex).iSmileyCell &&
                 iExtension->ConvertTextToSmiley( convBuf ) > 0 )
                {
                smileyDraw = ETrue;
                }

            // Note that this potentially modifies the text so its lenght in pixels
            // might increase. Therefore, this should always be done before
            // wrapping/clipping text. In some cases, WordWrapListItem is called
            // before coming here. Is it certain that it is not done for number subcells?

            // Do number conversion if required.
            if (SubCellIsNumberCell(subcell))
                {
                AknTextUtils::LanguageSpecificNumberConversion(convBuf);
                }

            // Check whether logical to visual conversion should be done here or not.
            TBool bidiConv =
                iExtension->iUseLogicalToVisualConversion &&
                subcell != iExtension->iFirstWordWrappedSubcellIndex &&
                subcell != iExtension->iSecondWordWrappedSubcellIndex;

            TBool doesNotFit( EFalse );
            if ( aHighlight )
                {
                doesNotFit = usedFont->TextWidthInPixels( convBuf ) > textLayout.TextRect().Width();
            
                if ( doesNotFit )
                    {
                    iExtension->iClippedSubcells |= ( 1 << subcell );
                    }
                else 
                    {
                    iExtension->iClippedSubcells &= ~( 1 << subcell );
                    }

                if ( iExtension->iUseClippedByWrap ) // override if already clipped
                    {
                    iExtension->iClippedSubcells = iExtension->iClippedByWrap;
                    }
                }

            
            // marquee
            CAknMarqueeControl* marquee =
                subcell == 1 || subcell == 3 ? iExtension->iMarquee :
                                               iExtension->i2ndLineMarquee;
            TBool marqueeDisabled =
                static_cast<CEikListBox*>(
                    Control() )->View()->ItemDrawer()->Flags() & CListItemDrawer::EDisableMarquee;

            if ( aHighlight && iExtension->IsMarqueeOn() && doesNotFit && !marqueeDisabled )
                {                
                iExtension->iMarquee->UseLogicalToVisualConversion( bidiConv );

                if ( marquee->DrawText( aGc, textRect, textLineLayout, convBuf, usedFont, color ) )
                    {
                    // all the loops have been executed
                    textLayout.DrawText( aGc, convBuf, bidiConv, color );
                    }
                }
            else
                {
                if ( marquee && marqueeDisabled )
                    {
                    marquee->Stop();
                    }

                if ( smileyDraw )
                    {
                    TRect tr(textLayout.TextRect());
                    _AKNTRACE( "textLayout Width: %d (%d,%d)", tr.Width(), tr.iTl.iX, tr.iBr.iX );
                    iExtension->DrawSmileyWithText( aGc, convBuf, textLayout, bidiConv, color );
                    }
                else
                    {
                textLayout.DrawText( aGc, convBuf, bidiConv, color );
                    }
                }

            if ( iExtension->iPictoInterface )
                {
                
                TRect  pictoRect = textLayout.TextRect();
                pictoRect.Normalize();
                if ( convBuf.Length() && bidiConv )
                    {                      
                    TInt maxWidth = pictoRect.Size().iWidth; 
                    TInt charsCanBeDisplayed = textLayout.Font()->TextCount( 
                                                convBuf, maxWidth );  
                    if ( charsCanBeDisplayed < convBuf.Length() )
                        {
                        TInt clipCharWidth = textLayout.Font()->CharWidthInPixels( 
                                                KEllipsis /*aClipChar*/ ); 
                         // Check how many characters fit in given space with truncation char. 
                         charsCanBeDisplayed = textLayout.Font()->TextCount( 
                         convBuf, maxWidth - clipCharWidth );

                        // This is "avkon rule": should not insert ellipsis right after a space.
                        if ( charsCanBeDisplayed > 1 && 
                             convBuf[charsCanBeDisplayed - 1] == ' ' &&
                             convBuf[charsCanBeDisplayed - 2] != ' ' )
                            {
                            charsCanBeDisplayed--;
                            }

                        TInt pictoRectWidth = textLayout.Font()->TextWidthInPixels( 
                        convBuf.Left( charsCanBeDisplayed ) );
                        pictoRect.SetWidth( pictoRectWidth );
                        } 
                    } 
                         
                
                iExtension->iPictoInterface->Interface()->DrawPictographsInText(
                    aGc, *usedFont, convBuf,
                    pictoRect,
                    textLayout.BaselineOffset(),
                    textLayout.Align(),
                    0 );
                }

            aGc.SetUnderlineStyle( EUnderlineOff );
            }
        else // Graphics subcell
            {
            TLex lex(text);
            TInt index;            
            TInt indexValue;
            
            indexValue=lex.Val(index);
            
            if (indexValue!=KErrNone)
                {
                // wrong icon index
                ++ subcell;
                continue;        
                }
               
            __ASSERT_DEBUG(indexValue==KErrNone, Panic(EAknPanicFormattedCellListInvalidBitmapIndex));
            
            TBool colorIcon( EFalse );
            if ( index == KColorIconFlag )
                {
                if ( iExtension->iColorBmp && iExtension->iHiliBmp )
                    {
                    colorIcon = ETrue;
                    }
                index = KColorIconIdx;
                }
            
            if( !iIconArray )
                {
                ++ subcell;
                continue;
                }

            if (aHighlight && (index > 0xffff))
                {
                index = index >> 16; // we have different icon for highlight
                }

             index = index & 0xffff; // mask off possible highlight icon
            __ASSERT_DEBUG((index>=0 && index<iIconArray->Count()),Panic(EAknPanicFormattedCellListInvalidBitmapIndex));
            
            TAknWindowLineLayout graphicLayout = iExtension->SLAt(SCindex).iGraphicLayout;
            TAknLayoutRect graphicRect; 
            
            graphicRect.LayoutRect(textRect,graphicLayout);
            TSize graphicSize( graphicRect.Rect().Size() );
            
            if (index>=0 && iIconArray)
                {
                CGulIcon* icon=(*iIconArray)[index];
                CFbsBitmap* bitmap=icon->Bitmap();
                // Sometimes we get fake bitmap...
                if ( bitmap )
                    {
                    TSize size( bitmap->SizeInPixels() ); // set size if not already
                    if ( size.iWidth != graphicSize.iWidth && size.iHeight != graphicSize.iHeight )
                        {
                        AknIconUtils::SetSize( bitmap,
                                               graphicSize,
                                               EAspectRatioPreservedAndUnusedSpaceRemoved); 
                        }
                    BitBltColored( aGc, aHighlight, icon, subcell, colorIcon, graphicRect.Rect() );
                    aGc.SetPenStyle(CGraphicsContext::ESolidPen);
                    }
                }
            }
        ++subcell;
        }    
    
    // Clear information of wordwrapped and bidi-reordered subcells.
    const_cast<CFormattedCellListBoxData*>( this )->
        SetWordWrappedSubcellIndices( -1, -1 );
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::DrawMarkingModeIcons
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::DrawMarkingModeIcons( 
                                            TListItemProperties& aProperties,
                                            CWindowGc& aGc,
                                            TRect& aItemRect ) const
    {
    CEikListBox* listbox = static_cast<CEikListBox*>( Control() ); 
    TRect textRect( aItemRect );
    
    if ( listbox->View()->ItemDrawer()->Flags() 
            & CListItemDrawer::EMarkingModeEnabled 
            && !aProperties.IsSelectionHidden()            
            && iExtension->iMarkingIconArray
            &&  iExtension->iMarkingIconArray->Count() 
                == KMarkingModeIconArraySize )       
        {
        if ( AknLayoutUtils::LayoutMirrored() )
            {
            textRect.iBr.iX -= 
                AknLayoutScalable_Avkon::list_double_graphic_pane_t1( 
                    0 ).LayoutLine().ir;
            }
        else
            {
            textRect.iTl.iX += 
                AknLayoutScalable_Avkon::list_double_graphic_pane_t1( 
                    0 ).LayoutLine().il;
            }                    

        TAknLayoutRect layoutRect;
        layoutRect.LayoutRect( aItemRect, 
                AknLayoutScalable_Avkon::list_double_graphic_pane_g1( 0 ) );

        // unchecked icon
        CGulIcon* icon = ( *iExtension->iMarkingIconArray )[1];        
        
        if ( listbox->View()->ItemIsSelected( 
                iExtension->iCurrentlyDrawnItemIndex ) )
            {
            icon = ( *iExtension->iMarkingIconArray )[0];        
            }
        
        CFbsBitmap* bitmap = icon->Bitmap();

        if ( bitmap )
            {
            TSize size( bitmap->SizeInPixels() ); // set size if not already
            TSize targetSize( layoutRect.Rect().Size() );
            
            if ( size.iWidth != targetSize.iWidth && 
                 size.iHeight != targetSize.iHeight )
                {
                AknIconUtils::SetSize( bitmap, targetSize,
                        EAspectRatioPreservedAndUnusedSpaceRemoved ); 
                }
            aGc.BitBltMasked( layoutRect.Rect().iTl, 
                              bitmap, 
                              TRect( layoutRect.Rect().Size() ),
                              icon->Mask(), EFalse );
            }
        aItemRect = textRect;
        }    
    }

EXPORT_C 
CFormattedCellListBoxData::CFormattedCellListBoxData()
    : CListBoxData()
    {
    }

EXPORT_C void CFormattedCellListBoxData::ConstructLD()
    {
    TRAPD( err, DoConstructL( KAknsIIDQsnAnimList ) );
    if( err )
        {
        delete(this);
        User::Leave( err );
        }
    }

EXPORT_C void CFormattedCellListBoxData::ConstructLD(
    const TAknsItemID& aAnimationIID )
    {
    TRAPD( err, DoConstructL( aAnimationIID ) );
    if( err )
        {
        delete(this);
        User::Leave( err );
        }
    }

void CFormattedCellListBoxData::DoConstructL( const TAknsItemID& aAnimationIID )
    {
    iSubCellArray = new(ELeave) CArrayFixFlat<SSubCell>(KSubCellListBoxGranularity);
    iExtension = new(ELeave) CFormattedCellListBoxDataExtension;

    iExtension->iSkinEnabled = AknsUtils::AvkonSkinEnabled();
    SetupSkinContextL();

    // Preallocate so that SizeChanged() methods do not leave so often.
    CListBoxData::ConstructL(NULL);
    iExtension->ConstructL( this, aAnimationIID );
    CListBoxData::SetSkinBackgroundControlContextL(iExtension->iSkinControlContext);
    AddSubCellL(0);
    AddSubCellL(1);
    AddSubCellL(2);
    AddSubCellL(3);
    AddSubCellL(4);
    }

TInt CFormattedCellListBoxData::LastSubCell() const
    {
    TInt count=iSubCellArray->Count();    if (!count)
        return(KErrNotFound);
    return(At(count-1).iSubCell);
    }

void 
CFormattedCellListBoxData::AddSubCellL(TInt aSubCell)
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("AddSubCellL: aSubCell=%d",aSubCell);
    SSubCell subcell;
    TMargins m={0,0,0,0};
    subcell.iSubCell=aSubCell;
    subcell.iWidth=0;
    subcell.iMargin=m;
    subcell.iBaseFont=NULL;
    subcell.iActualFontIndex=KNoActualSubCellFont;
    subcell.iGraphics=EFalse;
    subcell.iTransparent=EFalse;
    subcell.iNotAlwaysDrawn=EFalse;
    subcell.iRightSeparatorStyle = CGraphicsContext::ENullPen;
    subcell.iAlign=CGraphicsContext::ELeft;
    subcell.iPosition=TPoint(0,0);
    subcell.iBaseline = 0;
    subcell.iSize=TSize(0,0);
    subcell.iUseSubCellColors = EFalse;
    subcell.iTextClipGap = 0;
    subcell.iNumberCell = 0;
    TKeyArrayFix key(0,ECmpTInt);
    iSubCellArray->InsertIsqL(subcell,key);
    _AKNTRACE_FUNC_EXIT;
    }

CFormattedCellListBoxData::SSubCell& 
CFormattedCellListBoxData::At(TInt aArrayIndex)
    {
    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iSubCellArray->At(aArrayIndex));
    }

const CFormattedCellListBoxData::SSubCell& 
CFormattedCellListBoxData::At(TInt aArrayIndex) const
    {
    __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndex<iSubCellArray->Count(),Panic(EAknPanicOutOfRange));
    return(iSubCellArray->At(aArrayIndex));
    }

TInt 
CFormattedCellListBoxData::FindSubCellIndex(TInt& aArrayIndex,TInt aSubCell) const
    {
    if (aSubCell<0 || iSubCellArray->Count()==0)
        return(KErrNotFound);
    TKeyArrayFix key(0,ECmpTInt);
    SSubCell subcell;
    subcell.iSubCell=aSubCell;
    TInt retVal = iSubCellArray->FindIsq(subcell,key,aArrayIndex);
    if (retVal != 0)
        {
        return KErrNotFound;
        }

    return retVal;
    }

void 
CFormattedCellListBoxData::FindSubCellIndexOrAddL(TInt& aArrayIndex,TInt aSubCell)
    {
    if (FindSubCellIndex(aArrayIndex,aSubCell)==KErrNotFound)
        {
        AddSubCellL(aSubCell);
        FindSubCellIndex(aArrayIndex,aSubCell);
        }
    }


EXPORT_C
CFormattedCellListBoxData::TColors::TColors()
    : iText(KRgbBlack), iBack(KRgbWhite), iHighlightedText(KRgbWhite), iHighlightedBack(KRgbBlack),
      iRightSeparatorColor(AKN_LAF_COLOR_STATIC(215))
    {
    }



TInt CFormattedCellListBoxData::AddActualFontL(const CFont* aBaseFont)
    {
    _AKNTRACE_FUNC_ENTER;
    if (!iNormalFont.iFonts)
        {
        iNormalFont.iFonts=new (ELeave) CArrayPtrFlat<CFont> (1);
        iBoldFont.iFonts=new (ELeave) CArrayPtrFlat<CFont> (1);
        iItalicFont.iFonts=new (ELeave) CArrayPtrFlat<CFont> (1);
        iBoldItalicFont.iFonts=new (ELeave) CArrayPtrFlat<CFont> (1);
        }
    
    // Reserves extra space for each font array.
    TInt fontCount=iNormalFont.iFonts->Count()+1;
    iNormalFont.iFonts->SetReserveL(fontCount);
    iBoldFont.iFonts->SetReserveL(fontCount);
    iItalicFont.iFonts->SetReserveL(fontCount);
    iBoldItalicFont.iFonts->SetReserveL(fontCount);
    
    // Add Fonts.
    ConstructFontL(aBaseFont, TFontStyle(EPostureUpright, EStrokeWeightNormal, EPrintPosNormal), iNormalFont);
    ConstructFontL(aBaseFont, TFontStyle(EPostureUpright, EStrokeWeightBold, EPrintPosNormal), iBoldFont);
    ConstructFontL(aBaseFont, TFontStyle(EPostureItalic, EStrokeWeightNormal, EPrintPosNormal), iItalicFont);
    ConstructFontL(aBaseFont, TFontStyle(EPostureItalic, EStrokeWeightBold, EPrintPosNormal), iBoldItalicFont);
    
    _AKNTRACE_FUNC_EXIT;
    return fontCount-1;
    }

EXPORT_C void CPopupFormattedListBoxData::Draw(TListItemProperties aProperties, CWindowGc& aGc,const TDesC* aText,const TRect& aRect,TBool aHighlight, const TColors& aColors) const
    {
    _AKNTRACE_FUNC_ENTER;
    const TRect &aItemRect = aRect;

    DrawDefaultHighlight( aGc, aItemRect, aHighlight );

    // Draw the actual items.
    DrawFormatted(aProperties,aGc,aText,aItemRect,aHighlight,aColors);
    _AKNTRACE_FUNC_EXIT;
    }

void CFormattedCellListBoxData::DrawDefaultHighlight(CWindowGc &aGc, const TRect &aItemRect, TBool aHighlight) const
    {
    _AKNTRACE_FUNC_ENTER;    
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    // When this flag set, draw pressed down state and don't use animation.
    // There are several derived CListboxData in this file. All of them do  
    // this same thing.
    CListBoxView* view = static_cast<CEikListBox*>( iExtension->iControl )->View();
    TBool pressedDown = view->ItemDrawer()->Flags() & CListItemDrawer::EPressedDownState;

    if( aHighlight )
        {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( &aGc );
        if ( transApi )
            {
            transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight );
            if ( !transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight,
                                         aItemRect ) )
                {
                // No need to execute drawing if no drawing will occur
                transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
                return;
                }
            transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
            }
#endif //RD_UI_TRANSITION_EFFECTS_LIST

        TBool highlightDrawn = EFalse;
        
        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() );
        
        if ( iExtension->iAnimation ) // animated highlight
            {
            aGc.SetPenStyle( CGraphicsContext::ENullPen );
            highlightDrawn = iExtension->SyncAndDrawAnim( aGc, outerRect.Rect() );
            }

        if ( !highlightDrawn ) // normal skinned highlight
            {
            if ( pressedDown )
                {
                highlightDrawn = iExtension->DrawPressedDownEffect( AknsUtils::SkinInstance(), aGc, outerRect.Rect(), innerRect.Rect() );
                }
            else
                {
            MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() );
            
            if ( !cc ) 
                {
                cc = SkinBackgroundContext();
                }
                
            if ( cc )
                {
                    

                    aGc.SetPenStyle( CGraphicsContext::ENullPen );
                    
                    highlightDrawn = AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), 
                                                               aGc,
                                                               outerRect.Rect(),
                                                               innerRect.Rect(),
                                                               *iExtension->iSkinHighlightFrameId,
                                                               *iExtension->iSkinHighlightFrameCenterId );
                    }
                }
            }

        if ( !highlightDrawn ) // legacy fallback
            {
            TRgb color( AKN_LAF_COLOR( 244 ) );
            aGc.SetPenColor( color );
            aGc.SetBrushColor( color );
            aGc.SetPenStyle( CGraphicsContext::ESolidPen );
            aGc.SetBrushStyle( CGraphicsContext::ESolidBrush );
            aGc.DrawRect( aItemRect );
            }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST  
        if ( transApi )
            {
            transApi->StopDrawing();
            transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
            }
#endif
        }
    _AKNTRACE_FUNC_EXIT;
    }


void CFormattedCellListBoxData::SetWordWrappedSubcellIndices(
    TInt aFirstIndex,
    TInt aSecondIndex )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iFirstWordWrappedSubcellIndex = (TInt16)aFirstIndex;
    iExtension->iSecondWordWrappedSubcellIndex = (TInt16)aSecondIndex;
    }

EXPORT_C void CFormattedCellListBoxData::EnableMarqueeL(TBool aEnable)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    // CreateMarqueeControlL does nothing if marquee already exists,
    // so let's just call it just in case.
    CreateMarqueeControlL();
    iExtension->iMarquee->EnableMarquee(aEnable);
    iExtension->i2ndLineMarquee->EnableMarquee(aEnable);
    }

// Two versions to eliminate compiler warnings.
#ifdef __WINS__
EXPORT_C const TBool CFormattedCellListBoxData::IsMarqueeOn()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->IsMarqueeOn();
    }
#else
EXPORT_C TBool CFormattedCellListBoxData::IsMarqueeOn()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->IsMarqueeOn();
    }
#endif // __WINS__


void CFormattedCellListBoxData::FocusGained()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->FocusGained();
    }

void CFormattedCellListBoxData::FocusLost()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->FocusLost();
    }

void CFormattedCellListBoxData::HandleResourceChange( TInt aType )
    {
    _AKNTRACE_FUNC_ENTER;
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    // Animation is skin dependent, whenever skin changes animation changes
    // too.
    if( KAknsMessageSkinChange == aType )
        {
        iExtension->SkinChanged();
        }
    else if(aType == KEikDynamicLayoutVariantSwitch)
        {
        // What is under highlight may have changed -> we need to update
        // highlight background to animation.
        iExtension->iAnimFlags.Set( CFormattedCellListBoxDataExtension::EFlagUpdateBg );
        }
    else if( ( aType == KEikMessageUnfadeWindows ) ||
             ( aType == KEikMessageFadeAllWindows ) )
        {
        if( iExtension->iMarquee )
            {
            iExtension->iMarquee->HandleResourceChange( aType );
            }
        if( iExtension->i2ndLineMarquee )
            {
            iExtension->i2ndLineMarquee->HandleResourceChange( aType );
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::HighlightAnim
// -----------------------------------------------------------------------------
//
EXPORT_C const CAknsEffectAnim* CFormattedCellListBoxData::HighlightAnim() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iAnimation;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::AboutToDrawHighlightAnim
// -----------------------------------------------------------------------------
//
EXPORT_C void CFormattedCellListBoxData::AboutToDrawHighlightAnim() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if( !iExtension->iAnimation || !iExtension->iControl )
        {
        return;
        }

    CEikListBox* list = static_cast<CEikListBox*>( iExtension->iControl );
    CListBoxView* view = list->View();
    if( !view )
        {
        return;
        }

    if( view->CurrentItemIndex() != iExtension->iCurrentRow )
        {
        iExtension->iAnimFlags.Set( CFormattedCellListBoxDataExtension::EFlagUpdateBg );
        iExtension->iCurrentRow = view->CurrentItemIndex();
        }

    iExtension->SyncAnim( iExtension->iAnimSize );
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SetHighlightAnimBackgroundDrawer
// -----------------------------------------------------------------------------
//
EXPORT_C void CFormattedCellListBoxData::SetHighlightAnimBackgroundDrawer(
    MListBoxAnimBackgroundDrawer* aDrawer )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iHighlightBgDrawer = aDrawer;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SetItemCellSize
// -----------------------------------------------------------------------------
//
EXPORT_C void CFormattedCellListBoxData::SetItemCellSize( const TSize& aSize )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if( iExtension->iAnimSize != aSize )
        {
        iExtension->Play();
        }
    iExtension->iAnimSize = aSize;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::HasHighlightAnim
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CFormattedCellListBoxData::HasHighlightAnim() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return ( iExtension->iAnimation != NULL );
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::DrawHighlightAnim
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CFormattedCellListBoxData::DrawHighlightAnim(
        CBitmapContext& aGc, const TRect& aRect ) const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if( !iExtension->iAnimation )
        return EFalse;

    return iExtension->SyncAndDrawAnim( aGc, aRect );
    }

void CFormattedCellListBoxData::ResetMarquee()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if (iExtension->iMarquee)
        {
        iExtension->iMarquee->Reset();
        }
    if (iExtension->i2ndLineMarquee)
        {
        iExtension->i2ndLineMarquee->Reset();
        }
    }

TInt CFormattedCellListBoxData::CurrentMarqueeItemIndex()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iCurrentItem;
    }

void CFormattedCellListBoxData::SetCurrentMarqueeItemIndex(TInt aIndex)
    {
    _AKNTRACE("CFormattedCellListBoxData::SetCurrentMarqueeItemIndex aIndex=%d",
            aIndex);
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    iExtension->iCurrentItem = aIndex;
    }

void CFormattedCellListBoxData::SetCurrentItemIndex(TInt aIndex)
    {
    _AKNTRACE("CFormattedCellListBoxData::SetCurrentItemIndex aIndex=%d", aIndex);
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if( iExtension->iCurrentRow != aIndex )
        {
        iExtension->iAnimFlags.Set( CFormattedCellListBoxDataExtension::EFlagUpdateBg );
        }
    iExtension->iCurrentRow = aIndex;
    }

void CFormattedCellListBoxData::SetCurrentlyDrawnItemIndex( TInt aIndex )
    {
    _AKNTRACE("CFormattedCellListBoxData::SetCurrentlyDrawnItemIndex aIndex=%d", 
            aIndex);
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iCurrentlyDrawnItemIndex = aIndex;
    }

EXPORT_C const CFont* 
CFormattedCellListBoxData::RowAndSubCellFont(TInt aRow,TInt aSubCellIndex) const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TInt index = 0;
    if (iExtension->FindRowAndSubCellIndex(index,aRow,aSubCellIndex)!=0)
        return 0;
    return(iExtension->At(index).iFont);
    }

EXPORT_C void CFormattedCellListBoxData::SetSubCellFontForRowL(TInt aRowIndex,
                                                               TInt aSubCellIndex,
                                                               const CFont* aFont)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TInt index = 0;
    iExtension->FindRowAndSubCellIndexOrAddL(index,aRowIndex,aSubCellIndex);
    iExtension->At(index).iFont=aFont;
    }

/**
* Enables / disables transparency effect, ie. does the listbox draw it's own background or not.
* @param aDrawBackground  EFalse enables transparency
*/ 
EXPORT_C void CFormattedCellListBoxData::SetDrawBackground(const TBool aDrawBackground)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iDrawBackground = aDrawBackground;
    if( !aDrawBackground )
        {
        iExtension->DeleteAnim();
        }
    }

/**
* Is the listbox drawing the background itself or not (= "transparency")
*/ 
TBool CFormattedCellListBoxData::IsBackgroundDrawingEnabled() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iDrawBackground;
    }


/**
* Enables / disables drawing background after scrollbar
* @param aDrawBackground  default ETrue
*/ 
void CFormattedCellListBoxData::SetDrawScrollbarBackground(const TBool aDrawBackground)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iDrawScrollbarBackground = aDrawBackground;
    }

/**
* Is the listbox drawing the background after scrollbar or not
*/ 
TBool CFormattedCellListBoxData::IsScrollbarBackgroundDrawingEnabled() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iDrawScrollbarBackground;
    }


EXPORT_C void CFormattedCellListBoxData::SetMarqueeParams(const TInt aLoops, const TInt aScrollAmount, 
                                                          const TInt aScrollDelay, const TInt aInterval)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( iExtension->iMarquee )
        {
        iExtension->iMarquee->SetLoops( aLoops );
        iExtension->iMarquee->SetSpeedInPixels( aScrollAmount );
        iExtension->iMarquee->SetDelay( aScrollDelay );
        iExtension->iMarquee->SetInterval( aInterval );
        }
    if ( iExtension->i2ndLineMarquee )
        {
        iExtension->i2ndLineMarquee->SetLoops( aLoops );
        iExtension->i2ndLineMarquee->SetSpeedInPixels( aScrollAmount );
        iExtension->i2ndLineMarquee->SetDelay( aScrollDelay );
        iExtension->i2ndLineMarquee->SetInterval( aInterval );
        }
    }


EXPORT_C void CFormattedCellListBoxData::SetSubCellIconSize(TInt aIndex, TSize aSize)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( aIndex <= KMaxSubCellIndex && aIndex >= 0)
        {
        iExtension->iSubCellIconSize[aIndex] = aSize;
        }
    }

TSize CFormattedCellListBoxData::GetSubCellIconSize(TInt aIndex)
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( aIndex <= KMaxSubCellIndex && aIndex >= 0)
        {
        return iExtension->iSubCellIconSize[aIndex];
        }
    return TSize(0,0);
    }

// Moved here from eikslbd.cpp
EXPORT_C void CSettingsListBoxData::Draw(const TListItemProperties& aItemProperties,
                         CWindowGc& aGc,
                         const TDesC* aText,
                         const TRect& aRect,
                         TBool aHighlight,
                         const TColors& aColors) const
    {
    _AKNTRACE_FUNC_ENTER;
    // Draw the actual items.
    DrawFormatted(aItemProperties,aGc,aText,aRect,aHighlight,aColors);
    _AKNTRACE_FUNC_EXIT;
    }

// Moved here from eikslbd.cpp
EXPORT_C
CSettingsListBoxData* CSettingsListBoxData::NewL()
    {
    _AKNTRACE_FUNC_ENTER;
    CSettingsListBoxData* self=new(ELeave) CSettingsListBoxData;
    self->ConstructLD( KAknsIIDQsnAnimList );

    _AKNTRACE_FUNC_EXIT;
    return(self);
    }

void CFormattedCellListBoxData::SetupSkinContextL()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    // list's own rect cannot be used since it might be unknown at this point
    TRect mainPane;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane );
    
    TRect mainPaneRect( mainPane.Size() );

    if ( !iExtension->iSkinControlContext )
        {
        iExtension->iSkinControlContext =
            CAknsListBoxBackgroundControlContext::NewL( KAknsIIDQsnBgAreaMainListGene,
                                                        mainPaneRect,
                                                        EFalse,  // Changed to EFalse: See TSW defect avao-6eelpv
                                                        KAknsIIDNone,
                                                        mainPaneRect );
        }
    else
        {
        iExtension->iSkinControlContext->SetRect( mainPaneRect );
        }

    if ( iExtension->iPopupFrame )
        {
        iExtension->iPopupFrame->SetRect( mainPaneRect );
        }
        
    iExtension->iSkinHighlightFrameId = &KAknsIIDQsnFrList;
    iExtension->iSkinHighlightFrameCenterId = &KAknsIIDQsnFrListCenter;
    }

// extended skin support
void CFormattedCellListBoxData::SetESSTextColor( TAknsQsnTextColorsIndex aIndex )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    
    TRgb color;
    
    TInt error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
                                            color,
                                            KAknsIIDQsnTextColors,
                                            aIndex );
    if ( !error && iExtension )
        {
        iExtension->iTextColor = color;
        }
    }


// extended skin support
void CFormattedCellListBoxData::SetESSHighlightedTextColor( TAknsQsnTextColorsIndex aIndex )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TRgb color;
    
    TInt error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
                                            color,
                                            KAknsIIDQsnTextColors,
                                            aIndex );
    if ( !error )
        {
        iExtension->iHighlightedTextColor = color;
        }
    }


void CFormattedCellListBoxData::SetGraphicSubCellL( TInt aSubCell,
                                                    const TAknWindowLineLayout &aGraphicLayout )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    CEikFormattedCellListBox* list = static_cast<CEikFormattedCellListBox*>( iExtension->iControl );
    // this does happen with caknsetstyle, caknform(wide)style lists.
    // eventually they'll get here again with list!=0, so this check is enough
    if ( !list ) return;  
    
    TInt index = 0;
    iExtension->FindSLSubCellIndexOrAddL(index,aSubCell);
    iExtension->SLAt(index).iTextLayout=NULL;
    iExtension->SLAt(index).iGraphicLayout=aGraphicLayout;
    iExtension->SLAt(index).iSubCellType=CFormattedCellListBoxDataExtension::EAknSLGraphic;

    // For compabitility - needed at least for text wrapping.
    // Beware - some of these WILL be overriden if you got here trough
    // old layout methods like AknListBoxLayouts::SetupFormTextCell()
    // & friends.
    TAknLayoutRect r;
    
    r.LayoutRect( list->View()->ItemDrawer()->ItemCellSize(), aGraphicLayout );
    SetSubCellSizeL( aSubCell, r.Rect().Size() );
    SetSubCellPositionL( aSubCell, r.Rect().iTl );
    SetSubCellAlignmentL( aSubCell, CGraphicsContext::ECenter );
    SetGraphicsSubCellL( aSubCell, ETrue );
    UseScalableLayoutData( ETrue );
    if ( iExtension->iMarginRect == TRect::EUninitialized )
        {
        iExtension->iMarginRect = r.Rect();
        }
    else
        {
        iExtension->iMarginRect.BoundingRect( r.Rect() );
        }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi =
        CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() );
    if ( transApi )
        {
        transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl );
        TSize size = list->View()->ItemDrawer()->ItemCellSize();
        TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr );
        transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin,
            br );
        }
#endif
    }

void CFormattedCellListBoxData::SetTextSubCellL( TInt aSubCell,
                                                 const TAknTextLineLayout &aTextLayout )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    CEikFormattedCellListBox* list = static_cast<CEikFormattedCellListBox*>( iExtension->iControl );
    // this does happen with caknsetstyle, caknform(wide)style lists.
    // eventually they'll get here again with list!=0, so this check is enough
    if ( !list ) return;  

    TInt index = 0;
    iExtension->FindSLSubCellIndexOrAddL(index,aSubCell);
    iExtension->SLAt(index).iTextLayout=aTextLayout;
    iExtension->SLAt(index).iGraphicLayout=NULL;
    iExtension->SLAt(index).iSubCellType=CFormattedCellListBoxDataExtension::EAknSLText;

    
    // For compabitility - needed at least for text wrapping.
    // Beware - some of these WILL be overriden if you got here trough
    // old layout methods like AknListBoxLayouts::SetupFormTextCell()
    // & friends.
    TAknLayoutText t;
    t.LayoutText( list->View()->ItemDrawer()->ItemCellSize(), aTextLayout );
    SetSubCellSizeL( aSubCell, t.TextRect().Size() );
    SetSubCellPositionL( aSubCell, t.TextRect().iTl );
    SetSubCellFontL( aSubCell, t.Font() );
    SetSubCellAlignmentL( aSubCell, AknLayoutUtils::TextAlignFromId( aTextLayout.iJ ) );
    TInt B = AknLayoutUtils::CorrectBaseline( list->View()->ItemDrawer()->ItemCellSize().iHeight, aTextLayout.iB, aTextLayout.FontId() );
    SetSubCellBaselinePosL( aSubCell, B );
    UseScalableLayoutData( ETrue );
    if ( iExtension->iMarginRect == TRect::EUninitialized )
        {
        iExtension->iMarginRect = t.TextRect();
        }
    else
        {
        iExtension->iMarginRect.BoundingRect( t.TextRect() );
        }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi =
        CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() );
    if ( transApi )
        {
        transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl );
        TSize size = list->View()->ItemDrawer()->ItemCellSize();
        TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr );
        transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin,
            br );
        }
#endif

    }

void CFormattedCellListBoxData::SetConditionalSubCellL(TInt aSubCell,
                                                       const TAknTextLineLayout &aTextLayout,
                                                       TInt aAffectedSubCell)  
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    // iConditionValue of affected subcell (=text subcell, which has different layouts)
    // contains index of graphical subcell, which existence should be checked first.
    // This graphical subcell has in iConditionValue index of graphical subcell,
    // which existence should be checked second etc. Each graphical subcell can
    // affect only to 1 text subcell (or none).

    // for compabitility - needed at least for text wrapping
    SetNotAlwaysDrawnSubCellL( aSubCell, ETrue );

    TInt i = 0x01;
    i = i << aSubCell;
    iExtension->iConditionalCells = iExtension->iConditionalCells | i;

    TInt graphicalIndex = 0;
    if (iExtension->FindSLSubCellIndex(graphicalIndex, aSubCell)!=0) return; // subcell not found
    // conditional layoutline can be only added to graphical subcells
    if (iExtension->SLAt(graphicalIndex).iSubCellType!=CFormattedCellListBoxDataExtension::EAknSLGraphic) return;
    
    TInt textIndex = 0; // index of affected subcell
    if (iExtension->FindSLSubCellIndex(textIndex, aAffectedSubCell)!=0) return; // subcell not found
    // affected subcell can only be text subcell
    if (iExtension->SLAt(textIndex).iSubCellType==CFormattedCellListBoxDataExtension::EAknSLGraphic) return;
    
    TInt gSC = iExtension->SLAt(textIndex).iConditionValue; // text subcell to be added in priority chain

    while (gSC > -1)
        {
        if (iExtension->FindSLSubCellIndex(textIndex, gSC)!=0) return; // subcell not found
        gSC = iExtension->SLAt(textIndex).iConditionValue;
        }
    iExtension->SLAt(textIndex).iConditionValue = aSubCell; // add next subcell to chain
    iExtension->SLAt(graphicalIndex).iTextLayout=aTextLayout;

    iExtension->CreateColorBitmapsL( SubCellSize( aSubCell ) );
    
    TRect r( SubCellPosition( aSubCell ), SubCellSize( aSubCell ) );
    if ( iExtension->iMarginRect == TRect::EUninitialized )
        {
        iExtension->iMarginRect = r;
        }
    else
        {
        iExtension->iMarginRect.BoundingRect( r );
        }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    CEikFormattedCellListBox* list = static_cast<CEikFormattedCellListBox*>( iExtension->iControl );
    MAknListBoxTfxInternal* transApi =
        CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() );
    if ( transApi )
        {
        transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl );
        TSize size = list->View()->ItemDrawer()->ItemCellSize();
        TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr );
        transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin,
            br );
        }
#endif
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::UsesScalableLayoutData
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxData::UsesScalableLayoutData() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iSimpleList;
    }
void CFormattedCellListBoxData::UseScalableLayoutData( TBool aUse )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( !aUse && iExtension->iSimpleList )
        {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        CEikFormattedCellListBox* list = static_cast<CEikFormattedCellListBox*>( iExtension->iControl );
        MAknListBoxTfxInternal* transApi =
            CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() );
        if ( transApi )
            {
            transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, TPoint( 0, 0 ) );
            transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, TPoint( 0, 0 ) );
            }
#endif
        }
    iExtension->iSimpleList = aUse;
    }

EXPORT_C void CFormattedCellListBoxData::SetSubcellUnderlined( TBitFlags32 aUnderlinedCells )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iUnderlineFlagSet = ETrue;
    iExtension->iUnderlineFlags   = aUnderlinedCells;
    }

void CFormattedCellListBoxData::SetUnderlineStyle( TListItemProperties aProperties,
                                                   CWindowGc& aGc,
                                                   TInt aSubCell ) const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( !iExtension->iUnderlineFlagSet )
        {
        // underlining is already either on or off and
        // hardcoded off turning will ensure old style
        // behaviour
        return;
        }
    
    if ( aProperties.IsUnderlined()
         && iExtension->iUnderlineFlagSet
         && iExtension->iUnderlineFlags.IsSet( aSubCell ) )
        {
        aGc.SetUnderlineStyle( EUnderlineOn );
        }
    else
        {
        aGc.SetUnderlineStyle( EUnderlineOff );
        }
    }

void CFormattedCellListBoxData::UseHighlightIconSwapping( TBool aUse )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iUseHighligthIconSwapping = aUse;
    }

TBool CFormattedCellListBoxData::UseHighlightIconSwapping() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iUseHighligthIconSwapping;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SetStretchableGraphicSubCellL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::SetStretchableGraphicSubCellL(
    TInt aSubCell, 
    const TAknWindowComponentLayout& aNormalLayout, 
    const TAknWindowComponentLayout& aStretchedLayout )
    {
    if ( Layout_Meta_Data::IsLandscapeOrientation() &&
         Layout_Meta_Data::IsListStretchingEnabled() &&
         StretchingEnabled() )
        {
        SetGraphicSubCellL( aSubCell, aStretchedLayout.LayoutLine() );
        }
    else
        {
        SetGraphicSubCellL( aSubCell, aNormalLayout.LayoutLine() );
        }
    }
    
// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SetStretchableTextSubCellL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::SetStretchableTextSubCellL(
    TInt aSubCell, 
    const TAknTextComponentLayout& aNormalLayout, 
    const TAknTextComponentLayout& aStretchedLayout )
    {
    if ( Layout_Meta_Data::IsLandscapeOrientation() &&
         Layout_Meta_Data::IsListStretchingEnabled() &&
         StretchingEnabled() )
        {
        SetTextSubCellL( aSubCell, aStretchedLayout.LayoutLine() );
        }
    else
        {
        SetTextSubCellL( aSubCell, aNormalLayout.LayoutLine() );
        }
    }
    
// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SetStretchableConditionalSubCellL
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::SetStretchableConditionalSubCellL(
    TInt aSubCell,
    const TAknTextComponentLayout& aNormalLayout,
    const TAknTextComponentLayout& aStretchedLayout,
    TInt aNormalSubCell,
    TInt aStretchedSubCell )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( Layout_Meta_Data::IsLandscapeOrientation() &&
         Layout_Meta_Data::IsListStretchingEnabled() &&
         StretchingEnabled() )
        {
        _AKNTRACE("Layout_Meta_Data::IsListStretchingEnabled");
        SetConditionalSubCellL( aSubCell, aStretchedLayout.LayoutLine(), aStretchedSubCell );
        }
    else
        {
        SetConditionalSubCellL( aSubCell, aNormalLayout.LayoutLine(), aNormalSubCell );
        }
    _AKNTRACE_FUNC_EXIT;
    }


// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::ResetSLSubCellArray
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::ResetSLSubCellArray()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iMarginRect = TRect::EUninitialized;

    UseScalableLayoutData( EFalse );
    iExtension->ResetSLSubCellArray();        
    // This function gets called always when size changes, so here is called
    // SetupSkinContextL to update the layout rect of the background skin 
    // context (mainpane rect can change for example if toolbar is hidden.
    TRAP_IGNORE( SetupSkinContextL() );
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::StretchingEnabled
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxData::StretchingEnabled() const
    {
#ifdef RD_LIST_STRETCH    
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));        
    return iExtension->iStretchingEnabled;
#else
    return EFalse;
#endif // #ifdef RD_LIST_STRETCH        
    }

#ifdef RD_LIST_STRETCH    
// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::EnableStretching
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::EnableStretching( const TBool aEnabled )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));        
    iExtension->iStretchingEnabled = aEnabled;        
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::HideSecondRow
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::HideSecondRow( const TBool aHide )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));        
    iExtension->iHideSecondRow = aHide;        
    }
#endif // RD_LIST_STRETCH

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SecondRowHidden
// -----------------------------------------------------------------------------
//
TBool CFormattedCellListBoxData::SecondRowHidden() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));        
    return iExtension->iHideSecondRow;        
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::ToggleDropShadows
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::ToggleDropShadows( const TBool aEnable )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iUseDropShadows = aEnable;
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::CheckIfSubCellsIntersect
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::CheckIfSubCellsIntersect( 
    TAknTextLineLayout* aLayouts, 
    TBool* aResults, 
    const TDesC& aText, 
    const TRect& aItemRect ) const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    TInt subCell = 0;
    TInt subCell2;
    TInt subCellIndex;
    TInt subCellIndex2;
    TInt lastSubCell = Min( KMaxSubCellIndex, LastSubCell() );
    TPtrC text;
    TBool isEmpty[KMaxSubCellIndex];

    // cache the empty text states
    while ( ETrue )
        {
        if ( subCell > lastSubCell )
            {
            break;
            }
        
        TextUtils::ColumnText( text, subCell, &aText );

        if ( text == KNullDesC && SubCellIsNotAlwaysDrawn( subCell ) )
            {
            isEmpty[subCell] = ETrue;
            }
        else
            {
            isEmpty[subCell] = EFalse;
            }

        ++subCell;
        }

    subCell = 0;

    while ( ETrue )
        {
        if ( subCell > lastSubCell )
            {
            break;
            }

        if ( iExtension->FindSLSubCellIndex( subCellIndex, subCell ) != 0 ) 
            {
            break;
            }
        
        if ( isEmpty[subCell] )
            {
            ++subCell;
            continue;
            }
        
        TRect bRect( SubCellPosition( subCell ), SubCellSize( subCell ) );
        
        for ( subCell2 = subCell + 1; subCell2 <= lastSubCell; ++subCell2 )
            {
            if ( isEmpty[subCell2] )
                {
                continue;
                }

            if ( iExtension->FindSLSubCellIndex( subCellIndex2, subCell2 ) != 0 ) 
                {
                break;
                }

            TRect bRect2( SubCellPosition( subCell2 ), SubCellSize( subCell2 ) );

            if ( bRect.Intersects( bRect2 ) && !SubCellIsTransparent( subCell ) && !SubCellIsTransparent( subCell2 ) ) 
                {
                aResults[subCell] = ETrue;

                if ( !AknLayoutUtils::LayoutMirrored() )
                    {
                    bRect.iBr.iX = bRect2.iTl.iX;
                    }
                else
                    {
                    bRect.iTl.iX = bRect2.iBr.iX;
                    }
                }
            }
            
        if ( aResults[subCell] )
            {
            if ( iExtension->SLAt( subCellIndex ).iSubCellType == CFormattedCellListBoxDataExtension::EAknSLText )
                {
                TAknTextLineLayout textLine = iExtension->SLAt( subCellIndex ).iTextLayout;
                
                textLine.iW = bRect.Width();

                if ( !AknLayoutUtils::LayoutMirrored() )
                    {
                    textLine.ir = aItemRect.iBr.iX - bRect.iBr.iX;
                    }
                else
                    {
                    textLine.il = bRect.iTl.iX - aItemRect.iTl.iX;
                    }
                
                aLayouts[subCell] = textLine;
                }
            }

        ++subCell;
        }
    }

// -----------------------------------------------------------------------------
// CFormattedCellListBoxData::SubCellsMightIntersect
// -----------------------------------------------------------------------------
//
void CFormattedCellListBoxData::SubCellsMightIntersect( const TBool aMightIntersect )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iSubCellsMightIntersect = aMightIntersect;
    }


void CFormattedCellListBoxDataExtension::CreateColorBitmapsL( )
    {
    if ( iColorBmp )
        {
        CreateColorBitmapsL( iColorBmp->SizeInPixels() );
        }
    }

void CFormattedCellListBoxDataExtension::CreateColorBitmapsL( TSize aSize )
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("CreateColorBitmapsL: aSize=(%d,%d)", aSize.iWidth, aSize.iHeight);
    
    TRgb color, hiliColor;
    TInt error;
    // icon #13 main area   additional list icons   #215
    // icon #16 list highlight  additional list iconsform checkbox, radio button    #215

    error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
                                       color,
                                       KAknsIIDQsnIconColors,
                                       EAknsCIQsnIconColorsCG13 );
    if ( error )
        {
        _AKNTRACE("CreateColorBitmapsL: Get EAknsCIQsnIconColorsCG13 error, return");
        return;
        }
    
    error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(),
                                       hiliColor,
                                       KAknsIIDQsnIconColors,
                                       EAknsCIQsnIconColorsCG16 );
    if ( error )
        {
        _AKNTRACE("CreateColorBitmapsL: Get EAknsCIQsnIconColorsCG16 error, return");
        return;
        }
    
    if ( iColorBmp && iColorBmp->SizeInPixels() == aSize
         && color == iIconColor && hiliColor == iHiliIconColor )
        {
        _AKNTRACE("CreateColorBitmapsL: no change happened, ignore and return");
        return;
        }

    iIconColor = color;
    iHiliIconColor = hiliColor;

    if ( !iColorBmp )
        {
        iColorBmp = new( ELeave ) CFbsBitmap();
        iColorBmp->Create( aSize, CCoeEnv::Static()->ScreenDevice()->DisplayMode() );
        }
    else if ( iColorBmp->SizeInPixels() != aSize )
        {
        iColorBmp->Resize( aSize );
        }
    if ( !iHiliBmp )
        {
        iHiliBmp = new( ELeave ) CFbsBitmap();
        iHiliBmp->Create( aSize, CCoeEnv::Static()->ScreenDevice()->DisplayMode() );
        }
    else if ( iHiliBmp->SizeInPixels() != aSize )
        {
        iHiliBmp->Resize( aSize );
        }

    CFbsBitGc* fbsBitGc = CFbsBitGc::NewL();
    CleanupStack::PushL( fbsBitGc );

    CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL( iColorBmp );
    CleanupStack::PushL( bmpDevice );
    fbsBitGc->Activate( bmpDevice );
    fbsBitGc->SetPenStyle(CGraphicsContext::ENullPen);
    fbsBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
    fbsBitGc->SetBrushColor( color );
    fbsBitGc->Clear();
    CleanupStack::PopAndDestroy( bmpDevice );
    bmpDevice = NULL;
    
    bmpDevice = CFbsBitmapDevice::NewL( iHiliBmp );
    CleanupStack::PushL( bmpDevice );
    fbsBitGc->Activate( bmpDevice );
    fbsBitGc->SetPenStyle(CGraphicsContext::ENullPen);
    fbsBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
    fbsBitGc->SetBrushColor( hiliColor );
    fbsBitGc->Clear();
    CleanupStack::PopAndDestroy( bmpDevice );
    bmpDevice = NULL;

    CleanupStack::PopAndDestroy( fbsBitGc );
    _AKNTRACE_FUNC_EXIT;
    }


struct TCellInfo
    {
    TBool iTextNull;
    TPtrC iTextPtr;
    };

void 
CFormattedCellListBoxData::DrawFormattedOld( TListItemProperties& aProperties,
                                             CWindowGc& aGc,
                                             const TDesC* aText,
                                             const TRect& aItemRect,
                                             TBool aHighlight,
                                             const TColors& aColors ) const
    {
    _AKNTRACE_FUNC_ENTER;
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    _AKNTRACE( "DrawFormattedOld: aText=%S, aItemRect=(%d,%d,%d,%d)",
               aText, aItemRect.iTl.iX,
               aItemRect.iTl.iY,
               aItemRect.iBr.iX, 
               aItemRect.iBr.iY );

    TRect itemRect( aItemRect );
    
    TInt lastSubCell = LastSubCell();
    if ( lastSubCell == KErrNotFound )
        {
        aGc.UseFont( CEikonEnv::Static()->NormalFont() );
        // Use draw text so that there's no need to change pen color/style.
        aGc.DrawText( TPtrC(), itemRect, 0 );
        aGc.DiscardFont(); // Release the font cache
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    
    CEikListBox* listbox = static_cast<CEikListBox*>( Control() ); 
    
    DrawMarkingModeIcons( aProperties, aGc, itemRect );
    TInt iconOffset = aItemRect.Width() - itemRect.Width();
    
    const TColors* subcellColors = &aColors;
    
    const CFont* font=SubCellFont(0);
    if (font==NULL)
        {
        font=CEikonEnv::Static()->NormalFont();
        }
    
    TRect textRect( itemRect );
    textRect.iBr.iX = itemRect.iTl.iX;
    TInt subcell=0;
    TInt subcell2=0;

    TCellInfo textNull[30];
    TRect textShadowRect;           // For transparent list
    TRgb textShadowColour = AKN_LAF_COLOR_STATIC(215);    // Black shadow for item text.

    TBool layoutMirrored = AknLayoutUtils::LayoutMirrored();
    TBool skinEnabled = AknsUtils::AvkonSkinEnabled();
    

    // cache the text states.
    subcell = 0;
    
    SSubCell defaultCell;
    TMargins tm = {0,0,0,0};
    defaultCell.iPosition = TPoint(0,0);
    defaultCell.iSize = TSize(0,0);
    defaultCell.iRealSize = TSize(0,0);
    defaultCell.iRealTextSize = TSize(0,0);
    defaultCell.iMargin = tm;
    defaultCell.iUseSubCellColors = EFalse;
    defaultCell.iColors = defaultcolors;
    defaultCell.iGraphics = EFalse;
    defaultCell.iAlign = CGraphicsContext::ELeft;
    defaultCell.iBaseline = 0;
    defaultCell.iNumberCell = EFalse;
    defaultCell.iTextClipGap = 0;
    defaultCell.iNotAlwaysDrawn = EFalse;
    defaultCell.iTransparent = EFalse;
    defaultCell.iBaseFont = 0;
    SSubCell* sc;
    
    
    for(;;)
        {
        if (subcell>lastSubCell)
            {
            break;
            }
        
        TInt subcellindex = 0;
        TInt subcellfound = 0;
        subcellfound = FindSubCellIndex(subcellindex,subcell);
        if (subcellfound != KErrNotFound)
            {
            sc = &(iSubCellArray->At(subcellindex));
            }
        else
            {
            sc = &defaultCell;
            }
        
        TextUtils::ColumnText(textNull[subcell].iTextPtr,subcell, aText);
        
        if (textNull[subcell].iTextPtr == KNullDesC && sc->iNotAlwaysDrawn)
            {
            textNull[subcell].iTextNull = ETrue;
            }
        else
            {
            textNull[subcell].iTextNull = EFalse;
            }

        subcell++;
        }
    
    
    // this loop handles rectangles that are clipped because of other subcells.
    subcell=0;
    for(;;)
        {
        if (subcell>lastSubCell)
            {
            break;
            }
        
        if (textNull[subcell].iTextNull)
            {
            ++subcell;
            continue;
            }
        
        TInt subcellindex = 0;
        TInt subcellfound = 0;
        subcellfound = FindSubCellIndex(subcellindex,subcell);
        if (subcellfound != KErrNotFound)
            {
            sc = &(iSubCellArray->At(subcellindex));
            }
        else
            {
            sc = &defaultCell;
            }
        
        TRect bRect = TRect(sc->iPosition,sc->iSize);
        bRect.iBr.iX -= iconOffset;
        TMargins m = sc->iMargin;
        TRect cRect = TRect(bRect.iTl+TSize(m.iLeft,m.iTop),bRect.Size()-TSize(m.iRight+m.iLeft,m.iBottom+m.iTop));
        const TBool istrans = sc->iTransparent;
        if (!layoutMirrored)
            {
            for (subcell2=subcell+1; subcell2<=lastSubCell; subcell2++) 
                {
                if (textNull[subcell2].iTextNull)
                    {
                    continue;
                    }
                
                // This is called O(N^2) times - Do not put anything extra to it, it'll slow down drawing!
                TRect bRect2( SubCellPosition( subcell2 ), SubCellSize( subcell2 ) );
                if (cRect.Intersects(bRect2) && bRect.Intersects(bRect2) && !istrans && !SubCellIsTransparent(subcell2)) 
                    {
                    cRect.iBr.iX = bRect2.iTl.iX;
                    bRect.iBr.iX = bRect2.iTl.iX;
                    }
                }
            }
        else
            {
            for (subcell2=subcell+1; subcell2<=lastSubCell; subcell2++) 
                {
                if (textNull[subcell2].iTextNull)
                    {
                    continue;
                    }
                
                // This is called O(N^2) times - Do not put anything extra to it, it'll slow down drawing!
                TRect bRect2( SubCellPosition( subcell2 ), SubCellSize( subcell2 ) );
                if (cRect.Intersects(bRect2) && bRect.Intersects(bRect2) && !istrans && !SubCellIsTransparent(subcell2)) 
                    {
                    cRect.iTl.iX = bRect2.iBr.iX;
                    bRect.iTl.iX = bRect2.iBr.iX;
                    }
                }
            }
        SetSubCellRealTextSize(subcell, cRect.Size());
        SetSubCellRealSize(subcell, bRect.Size());
        sc->iRealTextSize = cRect.Size();
        sc->iRealSize = bRect.Size();
        subcell++;
        }
    
    // This loop does the drawing.    
    aGc.SetPenStyle(CGraphicsContext::ENullPen);
    subcell=0;
    for(;;)
        {        
        if (subcell>lastSubCell)
            {
            break;
            }
        
        if (textNull[subcell].iTextNull)
            {
            ++ subcell;
            continue;
            }
        
        
        TInt subcellindex = 0;
        TInt subcellfound = 0;
        subcellfound = FindSubCellIndex(subcellindex,subcell);
        if (subcellfound != KErrNotFound)
            {
            sc = &(iSubCellArray->At(subcellindex));
            }
        else
            {
            sc = &defaultCell;
            }
        
        // SetPosition, SetSize and margins support
        TRect bRect = TRect(sc->iPosition,sc->iRealSize);
        TMargins m = sc->iMargin;
        TRect cRect = TRect(bRect.iTl+TSize(m.iLeft,m.iTop),sc->iRealTextSize);
        
        
        if (bRect.iBr.iX == 0)
            {
            ++subcell;
            continue;
            }
        
        if ( layoutMirrored ) 
            {
            TRect bRect( sc->iPosition, sc->iSize );
            bRect.iBr.iX -= iconOffset;
            TRect cRect2( bRect.iTl + TSize( m.iLeft, m.iTop ),
                          bRect.Size() - TSize( m.iRight + m.iLeft,
                                                m.iBottom + m.iTop ) );
            
            TInt shift = (cRect2.Size() - sc->iRealTextSize).iWidth;
            cRect.iTl.iX += shift;
            cRect.iBr.iX += shift;
            }
        
        textRect = TRect( itemRect.iTl + cRect.iTl, cRect.Size() );
        
        if (sc->iUseSubCellColors)
            {
            subcellColors = &sc->iColors;
            }
        else
            {
            subcellColors = &aColors;
            }
        CListBoxView* view = listbox->View();
        TBool useOverrideColor = view->ItemDrawer()->Flags() & CListItemDrawer::EUseOverrideSkinTextColor; 
        if (aHighlight)
            {
            aGc.SetPenColor(subcellColors->iHighlightedText);
            aGc.SetBrushColor(subcellColors->iHighlightedBack); 
            if ( skinEnabled && !useOverrideColor )
                {
                if ( iExtension->iHighlightedTextColor != NULL )
                    {
                    aGc.SetPenColor( iExtension->iHighlightedTextColor );
                    }
                }
            }
        else
            {
            aGc.SetPenColor(subcellColors->iText);
            aGc.SetBrushColor(subcellColors->iBack);
            
            if ( skinEnabled && !useOverrideColor )
                {
                if ( iExtension->iTextColor != NULL )
                    {
                    aGc.SetPenColor( iExtension->iTextColor );
                    }
                }
            }
        
        aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
        
        // The following draws subcells to textRect
        if (textRect.iBr.iX!=textRect.iTl.iX)
            {          
            // graphics or text column
            CGraphicsContext::TTextAlign align=sc->iAlign;
            if (!sc->iGraphics)
                {
                const CFont* rowAndCellFont=RowAndSubCellFont(iExtension->iCurrentlyDrawnItemIndex,subcell);
                const CFont* cellFont=sc->iBaseFont;
                const CFont* tempFont=(cellFont) ? cellFont : font;
                const CFont* usedFont=(rowAndCellFont) ? rowAndCellFont : tempFont;
                aGc.UseFont(usedFont);
                SetUnderlineStyle( aProperties, aGc, subcell );
                
                // baseline calc needed for each cell.
                TInt baseLineOffset = sc->iBaseline;
                baseLineOffset -= cRect.iTl.iY;
                if (!baseLineOffset)
                    {
                    baseLineOffset = (cRect.Size().iHeight-usedFont->HeightInPixels())/2 + usedFont->AscentInPixels();
                    }
                
                TBuf<KMaxColumnDataLength + KAknBidiExtraSpacePerLine> clipbuf;// = sc->iColumnText.Left(KMaxColumnDataLength);
                
                // Note that this potentially modifies the text so its lenght in pixels
                // might increase. Therefore, this should always be done before
                // wrapping/clipping text. In some cases, WordWrapListItem is called
                // before coming here. Is it certain that it is not done for number subcells?
                TBool bufset = EFalse;
                if (sc->iNumberCell)
                    {
                    clipbuf = textNull[subcell].iTextPtr.Left(KMaxColumnDataLength);
                    AknTextUtils::LanguageSpecificNumberConversion(clipbuf);
                    bufset = ETrue;
                    }
                
                TBool clipped( EFalse );
                TInt clipgap = sc->iTextClipGap;
                
                if ( iExtension->iUseLogicalToVisualConversion &&
                     subcell != iExtension->iFirstWordWrappedSubcellIndex &&
                     subcell != iExtension->iSecondWordWrappedSubcellIndex )
                    {
                    TInt maxClipWidth = textRect.Size().iWidth + clipgap;
                
                    clipped = AknBidiTextUtils::ConvertToVisualAndClip(
                        textNull[subcell].iTextPtr.Left(KMaxColumnDataLength), 
                        clipbuf,
                        *usedFont,
                        textRect.Width(), 
                        maxClipWidth );
                    }
                else if (!bufset)
                    {
                    clipbuf = textNull[subcell].iTextPtr.Left(KMaxColumnDataLength);
                    }
                
                if (clipped) 
                    {
                    if (!layoutMirrored)
                        {
                        textRect.iBr.iX+=clipgap;
                        }
                    else
                        {
                        textRect.iTl.iX-=clipgap;
                        }
                    }

                if ( aHighlight )
                    {
                    if ( clipped )
                        {
                        iExtension->iClippedSubcells |= ( 1 << subcell );
                        }
                    else 
                        {
                        iExtension->iClippedSubcells &= ~( 1 << subcell );
                        }
                
                    if ( iExtension->iUseClippedByWrap ) // override if already clipped
                        {
                        iExtension->iClippedSubcells = iExtension->iClippedByWrap;
                        }
                    }

                CAknMarqueeControl* marquee =
                    subcell == 1 ? iExtension->iMarquee :
                                   iExtension->i2ndLineMarquee;
                
                TBool marqueeDisabled =
                    listbox->View()->ItemDrawer()->Flags() & CListItemDrawer::EDisableMarquee;
                
                if ( aHighlight && iExtension->IsMarqueeOn() && clipped && !marqueeDisabled )
                    {                    
                    // Let marquee know if it needs to do bidi conversion.
                    marquee->UseLogicalToVisualConversion( clipped );
                    
                    if ( marquee->DrawText( aGc, textRect, textNull[subcell].iTextPtr, baseLineOffset, align, *usedFont ) )
                        {
                        // All the loops have been executed -> the text needs to be truncated.
                        aGc.DrawText( clipbuf, textRect, baseLineOffset, align, 0 );
                        }
                    }
                else
                    {
                    if ( marquee && marqueeDisabled )
                        {
                        marquee->Stop();
                        }
                    
                    if ( IsBackgroundDrawingEnabled() )
                        {
                        aGc.DrawText( clipbuf, textRect, baseLineOffset, align, 0 );
                        }
                    else  // "Transparent" list, draw text shadow first, then the actual text.
                        {
                        textShadowRect = textRect;
                        textShadowRect.Move( 1, 1 );
                        aGc.SetPenColor( textShadowColour );
                        aGc.DrawText( clipbuf, textShadowRect, baseLineOffset, align, 0 );
                        if ( aHighlight )
                            {
                            aGc.SetPenColor( subcellColors->iHighlightedText );
                            }
                        else
                            {
                            aGc.SetPenColor( subcellColors->iText );
                            }
                        aGc.DrawText( clipbuf, textRect, baseLineOffset, align, 0 );
                        }
                    }
                
                if ( iExtension->iPictoInterface )
                    {
                    iExtension->iPictoInterface->Interface()->DrawPictographsInText(
                        aGc, *usedFont, clipbuf, textRect, baseLineOffset, align, 0 );
                    }
                // disable underline after first text.
                // at least phonebook uses this. See SetSubcellUnderlined to override
                aGc.SetUnderlineStyle(EUnderlineOff);
                aGc.DiscardFont(); // Release the font cache
                }
            else // Graphics subcell
                {
                TLex lex(textNull[subcell].iTextPtr);
                TInt index;
                __ASSERT_ALWAYS(lex.Val(index)==KErrNone,Panic(EAknPanicFormattedCellListInvalidBitmapIndex));
                __ASSERT_DEBUG(iIconArray, Panic(EAknPanicOutOfRange));
                if ( index == KColorIconFlag ) index = KColorIconIdx;
                __ASSERT_DEBUG((index>=0 && index<iIconArray->Count()),Panic(EAknPanicFormattedCellListInvalidBitmapIndex));
                TRect bmpRect;
                bmpRect.iTl=textRect.iTl;
                
                if (index>=0 && iIconArray)
                    {
                    CGulIcon* icon=(*iIconArray)[index];
                    CFbsBitmap* bitmap=icon->Bitmap();
                    

                    TInt w, h;
                    TSize sz = bitmap->SizeInPixels();

                    w = iExtension->iSubCellIconSize[subcell].iWidth;
                    h = iExtension->iSubCellIconSize[subcell].iHeight;

                    if (h != 0 && w != 0 && !( sz.iWidth == w || sz.iHeight == h ) )
                        {
                        AknIconUtils::SetSize( bitmap,
                                               iExtension->iSubCellIconSize[subcell],
                                               EAspectRatioPreservedAndUnusedSpaceRemoved );
                        }
                    else if ( sz.iWidth == 0 || sz.iHeight == 0 ) // check if size is set at all
                        {
                        // just in case fallback
                        AknIconUtils::SetSize( bitmap,
                                               textRect.Size(),
                                               EAspectRatioPreservedAndUnusedSpaceRemoved );
                        }

                    
                    TSize size=bitmap->SizeInPixels();
                    
                    if (size.iWidth>textRect.Width())
                        {
                        size.iWidth = textRect.Width();
                        }
                    
                    if (size.iHeight>textRect.Height())
                        {
                        size.iHeight = textRect.Height();
                        }
                    
                    TPoint bmpPos=textRect.iTl;
                    bmpPos.iY+=(textRect.Height()-size.iHeight)>>1;
                    switch (align)
                        {
                        case ELeft:
                            break;
                        case ECenter:
                            bmpPos.iX+=(textRect.Width()-size.iWidth)>>1;
                            break;
                        case ERight:
                            bmpPos.iX=textRect.iBr.iX-size.iWidth;
                            break;
                        }
                    bmpRect=TRect(bmpPos,size);
                    TPoint posInBitmap = TPoint(0,0) + bitmap->SizeInPixels() - textRect.Size();
                    posInBitmap.iX /= 2;
                    posInBitmap.iY /= 2;
                    if (posInBitmap.iX < 0)
                        {
                        posInBitmap.iX = 0;
                        }
                    if (posInBitmap.iY < 0)
                        {
                        posInBitmap.iY = 0;
                        }
                    TRect rect(posInBitmap,textRect.Size());
                    
                    if (icon->Mask())
                        {
                        aGc.BitBltMasked( bmpPos, bitmap, rect, icon->Mask(), ETrue );
                        }
                    else
                        {
                        aGc.BitBlt( bmpPos, bitmap ,rect );
                        }
                    }
                aGc.SetPenStyle(CGraphicsContext::ESolidPen);
                }
            }
        aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
        ++subcell;
        }    
    
    // Clear information of wordwrapped and bidi-reordered subcells.
    const_cast<CFormattedCellListBoxData*>( this )->
        SetWordWrappedSubcellIndices( -1, -1 );
    _AKNTRACE_FUNC_EXIT;
    }

void CFormattedCellListBoxData::SetClippedByWrap( TUint32 aClippedCells, TBool aUseClippedByWrap )
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    iExtension->iClippedByWrap = aClippedCells;
    iExtension->iUseClippedByWrap = aUseClippedByWrap;
    }

EXPORT_C TUint32 CFormattedCellListBoxData::CurrentItemTextWasClipped() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iClippedSubcells;
    }



TBool CFormattedCellListBoxData::KineticScrollingEnabled() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    return iExtension->iKineticScrolling;
    }
    
    
CEikListBox* CFormattedCellListBoxData::ListBox() const
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicNullPointer ));
    if ( iExtension->iControl )
        {
        return static_cast<CEikListBox*>( iExtension->iControl );
        }
    return NULL;
    }
void CFormattedCellListBoxData::InitSmileyL()
    {
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicObjectNotFullyConstructed ));
    if ( !iExtension->iSmileyMan )
        {
        iExtension->iSmileyMan = CAknSmileyManager::NewL( iExtension );
        }
    }

void CFormattedCellListBoxData::SetSmileySubCellL( TInt aSubCell )
    {    
    __ASSERT_DEBUG( iExtension, Panic( EAknPanicObjectNotFullyConstructed ));
    TInt index = 0;
    if ( iExtension )
        {
        iExtension->FindSLSubCellIndexOrAddL( index,aSubCell );
        iExtension->SLAt(index).iSmileyCell = ETrue;
        }
    }
#ifdef __ARMCC__
#pragma pop
#endif // __ARMCC__
    
// End of File
