uifw/AvKon/src/AknCharMap.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
child 14 3320e4e6e8bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/AknCharMap.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,8166 @@
+/*
+* 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: Special character table.
+*
+*/
+
+
+// INCLUDE FILES
+#include <txtetext.h>
+#include <barsread.h>
+#include <eikappui.h>
+#include <eikenv.h>
+#include <aknenv.h>
+#include <eiksbfrm.h>
+#include <eikscrlb.h>
+#include <eikdialogext.h>
+#include <bidivisual.h>
+#include <avkon.rsg>
+#include "AknPanic.h"
+#include "avkon.hrh"
+#include "AknUtils.h"
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <AknLayout.lag>
+#include "aknCharMap.h"
+#include "aknappui.h"
+#include "aknconsts.h"
+#include "AknDef.h"
+#include <PUAcodes.hrh>
+#include <s32file.h>
+#include <AknPanic.h>
+#include "aknSctDialog.h" // CAknCharmapDialog
+#include <aknPopupHeadingPane.h>
+#include <aknfep.rsg>
+#include <bautils.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uikon/eikenvinterface.h>
+#endif
+
+#include <AknTasHook.h>
+// For the TEikScrollBarModelType
+#include <eikscrlb.h>
+
+#include <AknsDrawUtils.h>
+#include <AknPictographInterface.h>
+#include <featmgr.h>
+#include <StringLoader.h>
+
+#include <AvkonInternalCRKeys.h>    // KCRUidAvkon, KAknRecentSctData
+#include <centralrepository.h>      // CRepository
+#include <AknsFrameBackgroundControlContext.h>
+
+#include <aknbutton.h>
+#include <gdi.h>
+#include <eikedwin.h>
+#include <gulbordr.h>
+#include <touchfeedback.h>
+#include <eiklabel.h>
+#include <aknphysics.h>
+#include <AknPriv.hrh>
+
+#include "PictograhGrouping.h"
+#include "AknSettingCache.h"
+#include "aknsctfocushandler.h"
+
+#include "AknSmileyModel.h"
+
+_LIT(KResFileName, "z:\\resource\\avkon.r");
+
+const TInt KAknSctCBaButtonDirections = 3; // bottom, right and left
+
+const TUint KThaiSCTCombiningSymbolAdd = 0xE900;
+
+enum
+    {
+    EAknCharMapButton1DownInGrid = 0x00000001,
+    EAknCharMapHasBeenScrolledByDrag = 0x00000002,
+    EAknCharMapCharsAllocated = 0x00000004, // flag that iChars points to HBufC
+    EAknCharMapPressedDown = 0x00000008   // flag for press down effect
+    };
+
+
+const TUint KHistoryEmptyChar = CEditableText::ETabCharacter;
+const TUint KHistoryEmptyCharForDisplay = CEditableText::ESpace;
+
+const TInt KAknSctRadioOn = 1;
+const TInt KAknSctRadioOff = 0;
+const TInt KAreaIdRecent = 0;
+const TInt KAreaIdMain   = 1;
+const TInt KAreaIdTail   = 2;
+
+
+// ----------------------------------------------------------------------------
+// TEmotionUtils definition
+// ----------------------------------------------------------------------------
+//
+
+const TUint KEmotionCharBase = 0xf880;
+
+class TEmotionUtils
+    {
+public:
+    static TBool IsEmotionChar(TChar aChar);
+    static TChar EmotionChar(TInt aId);
+    static TInt EmotionId(TChar aChar);
+    static TChar EmotionSwitchToSmileyChar();
+    static TChar EmotionSwitchToSctChar();
+    };
+
+TBool TEmotionUtils::IsEmotionChar(TChar aChar)
+    {
+    return (aChar >= KEmotionCharBase);
+    }
+
+TChar TEmotionUtils::EmotionChar(TInt aId)
+    {
+    return (KEmotionCharBase + aId);
+    }
+
+TInt TEmotionUtils::EmotionId(TChar aChar)
+    {
+    return (TInt)(aChar - KEmotionCharBase);
+    }
+
+TChar TEmotionUtils::EmotionSwitchToSmileyChar()
+    {
+    return KEmotionCharBase + CSmileyModel::EIconSwitchToSmiley;
+    }
+
+TChar TEmotionUtils::EmotionSwitchToSctChar()
+    {
+    return KEmotionCharBase + CSmileyModel::EIconSwitchToSct;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CAknCharMapHistory definition
+// ----------------------------------------------------------------------------
+//
+/**
+ *  Recent data management when a Special characters or a Pictograph characters 
+ *  @lib avkon.lib
+ *  @since 2.8
+ *
+ */
+class CAknCharMapHistory : public CBase
+    {
+    public: // Constructors and destructor
+        /**
+        * Two-phased constructor.
+        */
+        static CAknCharMapHistory* NewL();
+
+        /**
+        * Destructor.
+        */
+        ~CAknCharMapHistory();
+
+    public: // enum
+        enum THistoryType
+            {
+            EHistoryTypeNull = -1,
+            EHistoryTypeFull = 0,
+            EHistoryTypeHalf,
+            EHistoryTypePicto,
+            EHistoryTypePicto2,
+            EHistoryTypeMax
+            };
+        
+        enum THistoryFilter
+            {
+            EHistoryFilterMixed = 0, // text and emotion
+            EHistoryFilterTextOnly,
+            EHistoryFilterEmotionOnly,
+            EHistoryFilterMax
+            };
+        
+        enum THistorySize
+            {
+            KHistoryBufferSize = 15
+            };
+
+    public: // New functions
+        /**
+        * Load recent characters from file.
+        * @since 2.8
+        */
+        TInt LoadL();
+        /**
+        * Reset recent data arrary.
+        * @since 2.8
+        */
+        void ResetArray();
+        /**
+        * Store recent data to file.
+        * @since 2.8
+        */
+        TInt SaveL();
+        /**
+        * Get recent data.
+        * @since 2.8
+        * @param aHistoryType The kind of charctor map, refer to THistoryType
+        */
+        const TDesC& RecentString(THistoryType aHistoryType, THistoryFilter aHistoryFilter=EHistoryFilterMixed);
+        /**
+        * Insert a character which select on SCT/Picto.
+        * @since 2.8
+        * @param aHistoryType The kind of charctor map, refer to THistoryType
+        * @param aChar    Insert a character
+        */
+        void InsertChar(THistoryType aHistoryType, const TChar aChar);
+
+    private:
+        /**
+        * C++ default constructor.
+        * @since 2.8
+        */
+        CAknCharMapHistory();
+
+        /**
+        * By default Symbian 2nd phase constructor is private.
+        * @since 2.8
+        */
+        void ConstructL();
+        
+    private:
+        /**
+        * Insert a character to a HBufC.
+        * @param aHistoryBuf ahistory buffer
+        * @param aChar    Insert a character
+        */
+        void InsertCharToHistoryBuf(TDes& aHistoryBuf, const TChar aChar);
+
+    private:    // Data
+        // Recent characters
+        TBuf<KHistoryBufferSize> iMixedHistoryArray[EHistoryTypeMax];
+        TBuf<KHistoryBufferSize> iTextHistoryArray[EHistoryTypeMax];
+        TBuf<KHistoryBufferSize> iEmotionHistory;
+        
+        enum TBufferCount
+            {
+            KHistoryBufferCount = (EHistoryTypeMax+EHistoryTypeMax+1)
+            };
+    };
+
+
+// ----------------------------------------------------------------------------
+// Navi button class definition
+// ----------------------------------------------------------------------------
+//
+NONSHARABLE_CLASS(CAknSctNaviButton) : public CBase
+    {
+    public:
+        static CAknSctNaviButton* NewL(
+            const CCoeControl& aParent,
+            TInt aButtonId,
+            TResourceReader& reader);
+        ~CAknSctNaviButton();
+
+    private:
+        CAknSctNaviButton(TInt aButtonId);
+        void ConstructL(
+            const CCoeControl& aParent,
+            TResourceReader& reader);
+
+    public:
+        void SetFocused(TBool aState);
+        void SetEnabled(TBool aState);
+        TBool IsFocused();
+        TBool IsEnabled();
+
+    public:
+        CAknButton* iButtonControl;
+        TInt iButtonId;
+        TBool iPressed;
+        TBool iRepeat;
+    };
+
+// ----------------------------------------------------------------------------
+// Table Navi class definition
+// ----------------------------------------------------------------------------
+//
+NONSHARABLE_CLASS(CAknSctTableNavi) : public CAknControl, public MAknSctFocusHandler
+    {
+    public:
+        CAknSctTableNavi(CAknCharMap* aCharMap, CAknCharMapExtension* aExtension);
+        ~CAknSctTableNavi();
+
+    public:  // from CCoeControl
+        TInt CountComponentControls() const;
+        CCoeControl* ComponentControl( TInt aIndex ) const;
+        virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode);
+        void ConstructFromResourceL(TResourceReader& aReader);
+        virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent);
+        virtual TSize MinimumSize();
+        virtual void SizeChanged();
+
+    public: // from MAknSctFocusHandler
+        virtual CCoeControl* FocusedControl();
+        virtual TBool EnterControl(TInt aX, TInt aY);
+        virtual void MoveFocus(TInt aX, TInt aY);
+        virtual TBool ExitWithKey(TInt aKeycode);
+        virtual TBool LeaveControl();
+
+    public:
+        TInt TableCount();
+        void TableExitL();
+        static TInt DoTableExit(TAny* aThis);
+        void UpdateNextTableButtonL();
+
+    private:
+        TInt ButtonPosition(TInt aButtonIndex) const;
+        TInt SetStatusChanged();
+        void NextTableL();
+
+    private:  // data
+        TInt iButtonIndex;
+        RPointerArray<CAknSctNaviButton> iButtonArray;
+        CAknCharMap* iCharMap;
+        CAknCharMapExtension* iExtension;
+        CIdle *iIdle;
+        
+        TInt iPressedButtonIndex;
+    };
+
+// ----------------------------------------------------------------------------
+// Navigator class definition
+// ----------------------------------------------------------------------------
+//
+NONSHARABLE_CLASS(CAknSctPageNavi) : public CAknControl, public MAknSctFocusHandler, public MCoeControlObserver
+    {
+    public:
+        CAknSctPageNavi( CAknCharMap* aCharMap, CAknCharMapExtension* aExtension);
+        ~CAknSctPageNavi();
+
+    public: // new methods
+       void UpdatePageTitleL() const;
+
+    public:  // from CCoeControl
+        TInt CountComponentControls() const;
+        CCoeControl* ComponentControl( TInt aIndex ) const;
+        virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode);
+        void ConstructFromResourceL(TResourceReader& aReader);
+        virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent);
+        virtual TSize MinimumSize();
+        virtual void SizeChanged();
+        virtual void Draw(const TRect& aRect) const;
+
+    public: // from MCoeControlObserver
+        void HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType); // for button repeat
+
+    public:  // from MAknSctFocusHandler
+        virtual CCoeControl* FocusedControl();
+        virtual TBool EnterControl(TInt aX, TInt aY);
+        virtual void MoveFocus(TInt aX, TInt aY);
+        virtual TBool ExitWithKey(TInt aKeycode);
+        virtual TBool LeaveControl();
+
+    private:
+        TBool IsNextButton() const;
+
+    private:  // data
+        TInt iButtonIndex;
+        RPointerArray<CAknSctNaviButton> iButtonArray;
+        CAknCharMap* iCharMap;
+        CAknCharMapExtension* iExtension;
+        CEikLabel* iTitle;
+    };
+
+// ----------------------------------------------------------------------------
+// Category button class defintion
+// ----------------------------------------------------------------------------
+//
+class CAknSctCategoryButton : public CBase
+    {
+    public:
+        static CAknSctCategoryButton* NewL(
+            const CCoeControl& aParent,
+            TResourceReader& reader,
+            TInt aCategoryButtonId,
+            TInt aSctCaseId);
+        ~CAknSctCategoryButton();
+    private:
+        CAknSctCategoryButton(
+            TInt aCategoryButtonId,
+            TInt aSctCaseId);
+        void ConstructL(
+            const CCoeControl& aParent,
+            TResourceReader& reader);
+
+    public:
+        void SetFocused(TBool aState);
+
+    public:
+        CAknButton* iButtonControl;     // own
+        TInt        iButtonId;
+        TInt        iSctCaseId;
+        TBool       iValid;
+    };
+
+// ----------------------------------------------------------------------------
+// Radio button class defintion
+// ----------------------------------------------------------------------------
+//
+class CAknSctRadioButton : public CAknControl, public MAknSctFocusHandler
+    {
+    public:
+        enum TAknSctRadioButtonFlags
+            {
+            EAknSctRadioButtonResize = 0x1,
+            EAknSctRadioButtonEnd
+            };
+    public:
+        CAknSctRadioButton();
+        CAknSctRadioButton(CAknCharMap* aCharMap,
+                           CAknCharMapExtension* aExtension);
+        ~CAknSctRadioButton();
+    public: // from MAknSctFocusHandler
+        virtual CCoeControl* FocusedControl();
+        virtual TBool EnterControl(TInt aX, TInt aY);
+        virtual void MoveFocus(TInt aX, TInt aY);
+        virtual TBool ExitWithKey(TInt aKeycode);
+        virtual TBool LeaveControl();
+
+    public:  // from CCoeControl
+        TInt CountComponentControls() const;
+        CCoeControl* ComponentControl( TInt aIndex ) const;
+        virtual TKeyResponse OfferKeyEventL(
+            const TKeyEvent& aKeyEvent, TEventCode);
+        void ConstructFromResourceL(TResourceReader& aReader);
+
+        /**
+         * This function handles pointer events directed at the charmapdialog.
+         * @param aPointerEvent The pointer event directed at the charmapdialog.
+         */
+        virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent);
+
+        virtual TSize MinimumSize();
+        virtual void SizeChanged();
+        virtual void Draw(const TRect& aRect) const;
+
+    public:  // New function
+        // The number of Buttons
+        inline TInt Count() const;
+
+        void SetCurrentCategory(TInt aCategory);
+        void SetValidSctCase(TInt aSctCase);
+        void RemoveInvalidButton();
+
+    private:  // data
+        RPointerArray<CAknSctCategoryButton> iButtonArray;
+        MCoeControlObserver* iObserver;
+        TInt iFlags;
+        CAknCharMapExtension* iExtension;
+        CAknCharMap* iCharMap;
+        TInt iButtonIndex;
+        TInt iEntryIndex;
+    };
+// end of CAknSctRadioButton class definition
+
+// ----------------------------------------------------------------------------
+// Extension class defintion
+// ----------------------------------------------------------------------------
+//
+NONSHARABLE_CLASS(CAknCharMapExtension) : 
+    public CBase,
+    public MObjectProvider,
+    public MAknSctFocusHandler,
+    public MSmileyIconObserver
+    {
+    public:
+        CAknCharMapExtension();
+        ~CAknCharMapExtension();
+
+    public: // new methods
+        void SetCharMapControl(CAknCharMap* aCtrl);
+        MAknSctFocusHandler* FocusHandler();
+
+    public: // from MAknSctFocusHandler
+        virtual CCoeControl* FocusedControl();
+        virtual TBool EnterControl(TInt aX, TInt aY);
+        virtual void MoveFocus(TInt aX, TInt aY);
+        virtual TBool ExitWithKey(TInt aKeycode);
+        virtual TBool LeaveControl();
+
+    protected:
+        TTypeUid::Ptr MopSupplyObject(TTypeUid aId);
+        MObjectProvider* MopNext();
+        
+    private: // from MSmileyIconObserver
+        virtual void ThumbnailLoaded(CSmileyIcon* aSmileyIcon);
+        virtual void AnimationChanged(CSmileyIcon* aSmileyIcon);
+        
+    public:
+        TBool IsEmotionEnabled() const;
+        TBool IsShowingEmotion() const;
+        TBool NeedEmotionSwitchIcon() const;
+        HBufC* ReadEmotionHBufCL();
+        void LoadEmotionTumbnails(const TDesC& aSctChars);
+        void SetEmotionSize(const TSize& aSize);
+
+        CSmileyIcon* EmotionIcon(TChar aEmotionChar);
+        TBool DrawEmotion(CWindowGc& aGc, const TRect& aRect, TChar aEmotionChar);
+        void HandleFocusStatusChanged(TChar aChar, TBool aIsFocused);
+
+    public: // data
+        MCoeControlObserver *iObserver;
+        HBufC* iCharsQwerty;
+        HBufC* iTitleBuf;
+
+        TUint iFlags;
+        TInt iMaxVisibleRows;
+        CAknsFrameBackgroundControlContext* iBgContext;
+        MObjectProvider* iCharMap;
+        TBool iMenuSct; // Is SCT used in editing menu
+        TBool iKeyOkEvent; // ETrue is set after pressing OK Key
+
+        // FeatureManager
+        TBool iPictographsBuffer;         // ETrue means Picto is valid.
+        TBool iPictographsBufferGrouping; // ETrue means Picto grouping is valid.
+        TBool iJapaneseSctUi;       // Title and Softkey for Japanese varinat
+        TBool iHasCategoryButtonUi; // Has Category button UI
+        CAknSctRadioButton* iRadioButton;
+        TInt  iCurrentCategory;     // defined enum TAknSCTCategoryButton on avkon.hrh
+
+        // QHD layout.
+        CAknCharMap* iCharMapProxy;
+        MAknSctFocusHandler* iFocusHandler;
+        CAknSctTableNavi* iTableNavi;
+        CAknSctPageNavi* iPageNavi;
+        HBufC* iEntryBuf;
+        CEikLabel* iCategoryTitle;
+        CEikLabel* iCategoryEntry;
+        TBool iSelectAllowed;
+        
+        // Whether or not kinetic scrolling is enabled in the device.
+        // Focus scrolling is disabled if kinetic scrolling is used.
+        TBool iKineticScrolling;
+        // Indicates whether menu sct is highlighted or not.
+        TBool iMenuSctHighlighted;
+        
+    public: // for Emotion
+        HBufC* iCharsSmiley;
+        CSmileyModel iSmileyModel;
+        TChar iLastFocusedSmileyChar;
+        TBool iIsShowingEmotion;
+        TBool iIsEnableEmotion;
+
+    public: // Single click        
+       /**
+        * Is single click mode enabled
+        */
+        TBool iSingleClickEnabled;
+
+       /**
+        * Is highlight visible
+        */
+        TBool iHighlightVisible;         
+    };
+
+// ----------------------------------------------------------------------------
+// Navi button class implementation
+// ----------------------------------------------------------------------------
+//
+CAknSctNaviButton* CAknSctNaviButton::NewL(const CCoeControl& aParent, TInt aButtonId, TResourceReader& aReader)
+    {
+    CAknSctNaviButton* self = new( ELeave ) CAknSctNaviButton(aButtonId);
+    CleanupStack::PushL( self );
+    self->ConstructL(aParent, aReader);
+    CleanupStack::Pop();
+    return self;
+    }
+
+CAknSctNaviButton::CAknSctNaviButton(TInt aButtonId) : iButtonId(aButtonId)
+    {
+    }
+
+void CAknSctNaviButton::ConstructL(const CCoeControl& aParent, TResourceReader& aReader)
+    {
+    iButtonControl = CAknButton::NewL(aReader);
+    iButtonControl->SetContainerWindowL(aParent);
+    }
+
+CAknSctNaviButton::~CAknSctNaviButton()
+    {
+    delete iButtonControl;
+    }
+
+void CAknSctNaviButton::SetFocused(TBool aState)
+    {
+    iButtonControl->SetFocus(aState);
+    iButtonControl->DrawNow();
+    }
+
+void CAknSctNaviButton::SetEnabled(TBool aState)
+    {
+    iButtonControl->MakeVisible(aState);
+    }
+
+TBool CAknSctNaviButton::IsFocused()
+    {
+    return iButtonControl->IsFocused();
+    }
+
+TBool CAknSctNaviButton::IsEnabled()
+    {
+    return iButtonControl->IsVisible();
+    }
+
+// ----------------------------------------------------------------------------
+// Table navi class implementation
+// ----------------------------------------------------------------------------
+//
+CAknSctTableNavi::CAknSctTableNavi(CAknCharMap* aCharMap, CAknCharMapExtension* aExtension) : 
+iCharMap(aCharMap), iExtension(aExtension)
+    {
+    }
+
+CAknSctTableNavi::~CAknSctTableNavi()
+    {
+    if (iButtonArray.Count())
+        {
+        iButtonArray.ResetAndDestroy();
+        }
+    iButtonArray.Close();
+    delete iIdle;
+    }
+
+TInt CAknSctTableNavi::CountComponentControls() const
+    {
+    return iButtonArray.Count();
+    }
+
+CCoeControl* CAknSctTableNavi::ComponentControl( TInt aIndex ) const
+    {
+    CCoeControl* rtn;
+    if (aIndex < iButtonArray.Count())
+        {
+        rtn = iButtonArray[aIndex]->iButtonControl;
+        }
+    else
+        {
+        rtn = NULL;
+        }
+    return rtn;
+    }
+
+TKeyResponse CAknSctTableNavi::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aModifiers)
+    {
+    CAknSctNaviButton* buttonObj = iButtonArray[iButtonIndex];
+    buttonObj->iButtonControl->OfferKeyEventL(aKeyEvent,aModifiers);
+    TKeyResponse response = EKeyWasNotConsumed;
+    TUint code=aKeyEvent.iCode;
+    switch (code)
+        {
+        case EKeyEnter:
+        case EKeyOK:
+            {
+            switch (buttonObj->iButtonId)
+                {
+                case EAknSctTableNaviExit:
+                    {
+                    iExtension->iKeyOkEvent = ETrue;
+                    TableExitL();
+                    response = EKeyWasConsumed;
+                    }
+                    break;
+                // add all supported table types here.
+                case EAknSctTableNaviSpecialChar:
+                case EAknSctTableNaviEmotion:
+                    {
+                    NextTableL();
+                    response = EKeyWasConsumed;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
+        case EKeyLeftArrow:
+        case '4':
+            {
+            MoveFocus(-1,0);
+            response = EKeyWasConsumed;
+            }
+            break;
+        case EKeyRightArrow:
+        case '6':
+            {
+            MoveFocus(1,0);
+            response = EKeyWasConsumed;
+            }
+            break;
+        case EKeyUpArrow:
+        case '2':
+            {
+            response = EKeyWasConsumed;
+            if ((iButtonIndex==0) && !Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                // Left page button.
+                if (iExtension->iPageNavi && iExtension->iPageNavi->EnterControl(0,0))
+                    {
+                    LeaveControl();
+                    }
+                }
+            else
+                {
+                // Last radio button.
+                if ((iButtonIndex==0) && iExtension->iRadioButton)
+                    {
+                    if (iExtension->iRadioButton->EnterControl(0,iExtension->iRadioButton->Count()-1))
+                        {
+                        LeaveControl();
+                        }
+                    break;
+                    }
+
+                // Grid bottom row.
+                TInt xPos = ButtonPosition(iButtonIndex);
+                if (iCharMap->ColMax(0) > iCharMap->ColMax(xPos))
+                    {
+                    xPos = iCharMap->RowMax(iCharMap->ColMax(0));
+                    }
+
+                if (iExtension->EnterControl(xPos,iCharMap->ColMax(xPos)))
+                    {
+                    LeaveControl();
+                    break;
+                    }
+                }
+            }
+            break;
+            
+        case EKeyDownArrow:
+        case '8':
+            {
+            response = EKeyWasConsumed;
+            
+            // First radio button.
+            if ((iButtonIndex==0) && iExtension->iRadioButton)
+                {
+                if (iExtension->iRadioButton->EnterControl(0,0))
+                    {
+                    LeaveControl();
+                    }
+                break;
+                }
+            
+            // Grid top row.
+            TInt xPos = ButtonPosition(iButtonIndex);
+            if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos)))
+                {
+                LeaveControl();
+                break;
+                }
+            }
+            break;
+            
+        default:
+            break;
+        }
+    return response;
+    }
+
+void CAknSctTableNavi::TableExitL()
+    {
+    delete iIdle;
+    iIdle = 0;
+    iIdle = CIdle::NewL(CActive::EPriorityIdle);
+    iIdle->Start(TCallBack(DoTableExit, this));
+    }
+
+TInt CAknSctTableNavi::DoTableExit(TAny* aThis)
+    {
+    return ((CAknSctTableNavi*)aThis)->SetStatusChanged();
+    }
+
+TInt CAknSctTableNavi::ButtonPosition(TInt aButtonIndex) const
+    {
+    // buttons behind the 1th are behavior as one button
+    return (aButtonIndex==0) ? 0 : 1;
+    }
+
+TInt CAknSctTableNavi::SetStatusChanged()
+    {
+    TRAPD(err, iCharMap->SetStatusChanged(EAknCharSelectedTableExitButton));
+    return err;
+    }
+
+void CAknSctTableNavi::NextTableL()
+    {
+    iCharMap->SetStatusChanged(EAknCharSelectedNextTableButton);
+    }
+
+void CAknSctTableNavi::ConstructFromResourceL(TResourceReader& aReader)
+    {
+    // Table navi buttons.
+    TInt counts = aReader.ReadInt16();
+    for (TInt i = 0; i < counts; i++)
+        {
+        TInt buttonId = aReader.ReadInt16();
+        TInt resId = aReader.ReadInt32();
+        TResourceReader buttonReader;
+        iCoeEnv->CreateResourceReaderLC(buttonReader, resId);
+        CAknSctNaviButton* buttonObj = CAknSctNaviButton::NewL(*this, buttonId, buttonReader);
+        iButtonArray.Append(buttonObj);
+        CleanupStack::PopAndDestroy(); // buttonReader
+        }
+    }
+
+void CAknSctTableNavi::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition))
+        {
+        if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+            {
+            iPressedButtonIndex = -1;
+            
+            for (TInt index = 0; index < iButtonArray.Count(); index++)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[index];
+                if(buttonObj->IsEnabled())
+                    {
+                    TRect buttonRect = buttonObj->iButtonControl->Rect();
+                    if (buttonRect.Contains(aPointerEvent.iPosition))
+                        {
+                        iPressedButtonIndex = index;
+                        }
+                    }
+                }
+            }
+        else if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+            {
+            if(iPressedButtonIndex >= 0)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[iPressedButtonIndex];
+                if(buttonObj->IsEnabled())
+                    {
+                    iButtonIndex = iPressedButtonIndex;
+                    
+                    TRect buttonRect = buttonObj->iButtonControl->Rect();
+                    if (buttonRect.Contains(aPointerEvent.iPosition))
+                        {
+                        switch (buttonObj->iButtonId)
+                            {
+                            case EAknSctTableNaviExit:
+                                {
+                                iExtension->iKeyOkEvent = ETrue;
+                                TableExitL();
+                                }
+                                return;
+                                
+                            case EAknSctTableNaviSpecialChar:
+                            case EAknSctTableNaviEmotion:
+                                {
+                                NextTableL();
+                                }
+                                return;
+                                
+                            default:
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    
+    CCoeControl::HandlePointerEventL(aPointerEvent);
+    }
+
+TSize CAknSctTableNavi::MinimumSize()
+    {
+    return Rect().Size();
+    }
+
+void CAknSctTableNavi::SizeChanged()
+    {
+    if (iButtonArray.Count()>0)
+        {
+
+        TInt ctrlVariety = 2;
+        TInt cellVariety = 1;
+        if(!iCharMap->IsJapaneseSctUi())
+            {
+            ctrlVariety = (iCharMap->TableCount()>1) ? 0 : 1;
+            cellVariety = 0;
+            }
+        
+        TAknLayoutRect cellLayRect, buttonLayRect;
+        TRect buttonRect;
+
+        // Table exit.
+        cellLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::cell_graphic2_control_pane(ctrlVariety,0));
+        buttonLayRect.LayoutRect(cellLayRect.Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp05(cellVariety));
+        buttonRect = buttonLayRect.Rect();
+
+        TAknLayoutRect iconLayRect;
+        iconLayRect.LayoutRect(buttonRect, AknLayoutScalable_Avkon::cell_graphic2_control_pane_g1(cellVariety));
+        TSize iconSize = iconLayRect.Rect().Size();
+
+        CAknSctNaviButton* buttonObj = iButtonArray[0];
+        buttonObj->iButtonControl->SetRect(buttonRect);
+        buttonObj->iButtonControl->SetHighlightRect(buttonRect);
+        buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved);
+        buttonObj->iButtonControl->SetIconSize(iconSize);
+        buttonObj->SetEnabled(ETrue);
+
+        // Table change.
+        if (iCharMap->TableCount() > 1)
+            {
+            cellLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::cell_graphic2_control_pane(ctrlVariety,1));
+            buttonLayRect.LayoutRect(cellLayRect.Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp05(cellVariety));
+            buttonRect = buttonLayRect.Rect();
+            
+            for (TInt i(1); i<iButtonArray.Count(); i++)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[i];
+                buttonObj->iButtonControl->SetRect(buttonRect);
+                buttonObj->iButtonControl->SetHighlightRect(buttonRect);
+                buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved);
+                buttonObj->iButtonControl->SetIconSize(iconSize);
+                buttonObj->SetEnabled(ETrue);
+                }
+            }
+
+        TRAP_IGNORE(UpdateNextTableButtonL());
+        }
+    }
+
+
+void CAknSctTableNavi::UpdateNextTableButtonL()
+    {
+    
+    TBool isFocused = EFalse;
+    
+    // table switch buttons stay in one place.
+    for(TInt index(1); index<iButtonArray.Count(); index++)
+        {
+        CAknSctNaviButton* buttonObj = iButtonArray[index];
+        if(buttonObj->IsEnabled())
+            {
+            isFocused = buttonObj->IsFocused();
+            }
+        }
+    
+    // fresh focused button
+    for (TInt index(1); index<iButtonArray.Count(); index++)
+        {
+        CAknSctNaviButton* buttonObj = iButtonArray[index];
+        if (iCharMap->TableCount() > 1)
+            {
+            switch (iCharMap->NextTableCase())
+                {
+                case EAknCharMapTableSpecialChar:
+                    {
+                    TBool isShown = EFalse;
+                    if(iExtension->IsShowingEmotion())
+                        {
+                        isShown = (buttonObj->iButtonId==EAknSctTableNaviSpecialChar);
+                        }
+                    else
+                        {
+                        isShown = (buttonObj->iButtonId==EAknSctTableNaviEmotion);
+                        }
+                    buttonObj->SetEnabled(isShown);
+                    buttonObj->SetFocused(isShown && isFocused);
+                    if(isShown && isFocused)
+                        {
+                        iButtonIndex = index;
+                        }
+                    }
+                    break;
+
+                default:
+                    buttonObj->SetEnabled(EFalse);
+                    break;
+                }
+            }
+        else
+            {
+            buttonObj->SetEnabled(EFalse);
+            }
+        }
+    }
+
+CCoeControl* CAknSctTableNavi::FocusedControl()
+    {
+    return this;
+    }
+
+TBool CAknSctTableNavi::EnterControl(TInt aX, TInt /*aY*/)
+    {
+    if (IsVisible())
+        {
+        if ((aX >= 0) && (aX < iButtonArray.Count()))
+            {
+            TInt index = aX;
+            if (AknLayoutUtils::LayoutMirrored()) // reverse.
+                {
+                index = (iButtonArray.Count() - 1) - aX;
+                }
+
+            index = ButtonPosition(index);
+
+            for(; index<iButtonArray.Count(); index++)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[index];
+                if (buttonObj->IsEnabled())
+                    {
+                    iButtonIndex = index;
+                    iExtension->iFocusHandler = this;
+                    buttonObj->SetFocused(ETrue);
+                    return ETrue;
+                    }
+                }
+            }
+        }
+    return EFalse;
+    }
+
+void CAknSctTableNavi::MoveFocus(TInt aX, TInt /*aY*/)
+    {
+    TInt delta = aX;
+    if (AknLayoutUtils::LayoutMirrored()) // reverse.
+        {
+        delta = -aX;
+        }
+
+    TInt buttonIndex = iButtonIndex + delta;
+
+    // loop until find next position
+    for (TInt i = 0; i < iButtonArray.Count(); i++)
+        {
+
+        if (buttonIndex > iButtonArray.Count() - 1) // goto Next control
+            {
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                // First radio button.
+                if (iExtension->iRadioButton)
+                    {
+                    if (iExtension->iRadioButton->EnterControl(0,0))
+                        {
+                        LeaveControl();
+                        }
+                    break;
+                    }
+                // Grid start.
+                if (iExtension->EnterControl(0,iCharMap->ColMin(0)))
+                    {
+                    LeaveControl();
+                    }
+                }
+            else
+                {
+                // Left page button.
+                if (iExtension->iPageNavi &&
+                    iExtension->iPageNavi->EnterControl(0,0))
+                    {
+                    LeaveControl();
+                    }
+                }
+            break;
+            }
+
+        else if (buttonIndex < 0) // goto Prev control
+            {
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                // Right page button.
+                if (iExtension->iPageNavi &&
+                    iExtension->iPageNavi->EnterControl(1,0))
+                    {
+                    LeaveControl();
+                    }
+                }
+            else
+                {
+                // Grid end.
+                TInt posY = iCharMap->ColMax(0);
+                if (iExtension->EnterControl(iCharMap->RowMax(posY),posY))
+                    {
+                    LeaveControl();
+                    }
+                }
+            break;
+            }
+
+        if (iButtonArray[buttonIndex]->IsEnabled()) // goto next button in This control
+            {
+            CAknSctNaviButton* buttonObj;
+            buttonObj = iButtonArray[iButtonIndex];
+            buttonObj->SetFocused(EFalse);
+            iButtonIndex = buttonIndex;
+            buttonObj = iButtonArray[iButtonIndex];
+            buttonObj->SetFocused(ETrue);
+            break;
+            }
+        
+        buttonIndex += (delta < 0) ? -1 : 1; // get next position
+        }
+    }
+
+TBool CAknSctTableNavi::LeaveControl()
+    {
+    for (TInt i = 0; i < iButtonArray.Count(); i++ )
+        {
+        iButtonArray[i]->SetFocused(EFalse);
+        }
+    return ETrue;
+    }
+
+TBool CAknSctTableNavi::ExitWithKey(TInt /*aKeycode*/)
+    {
+    if (iButtonArray[iButtonIndex]->iButtonId != EAknSctTableNaviExit)
+        {
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Page Navi class implementation
+// ----------------------------------------------------------------------------
+//
+CAknSctPageNavi::CAknSctPageNavi(
+    CAknCharMap* aCharMap,
+    CAknCharMapExtension* aExtension)
+    :iCharMap(aCharMap),
+    iExtension(aExtension)
+    {
+    }
+
+CAknSctPageNavi::~CAknSctPageNavi()
+    {
+    if (iButtonArray.Count())
+        {
+        iButtonArray.ResetAndDestroy();
+        }
+    iButtonArray.Close();
+    delete iTitle;
+    }
+
+TInt CAknSctPageNavi::CountComponentControls() const
+    {
+    TInt num= 0;
+    if (iTitle)
+        {
+        num++;
+        }
+    if (iButtonArray.Count() > 0)
+        {
+        num += iButtonArray.Count();
+        }
+    return num;
+    }
+
+CCoeControl* CAknSctPageNavi::ComponentControl( TInt aIndex ) const
+    {
+    if (iTitle)
+        {
+        if ( aIndex == 0 )
+            {
+            return iTitle;
+            }
+        aIndex--;
+        }
+    if (iButtonArray.Count() > 0)
+        {
+        return iButtonArray[ aIndex ]->iButtonControl;
+        }
+    return NULL;
+    }
+
+TKeyResponse CAknSctPageNavi::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent,
+    TEventCode aModifiers)
+    {
+    CAknSctNaviButton* buttonObj = iButtonArray[iButtonIndex];
+    buttonObj->iButtonControl->OfferKeyEventL(aKeyEvent,aModifiers);
+    TKeyResponse response = EKeyWasNotConsumed;
+    TUint code=aKeyEvent.iCode;
+    switch (code)
+        {
+        case EKeyEnter:
+        case EKeyOK:
+            {
+            switch (buttonObj->iButtonId)
+                {
+                case EAknSctPageNaviPrevPage:
+                    {
+                    iCharMap->PrevPageL();
+                    }
+                    break;
+                case EAknSctPageNaviNextPage:
+                    {
+                    iCharMap->NextPageL();
+                    }
+                    break;
+                default:
+                    return EKeyWasConsumed;
+                }
+            buttonObj->SetFocused(ETrue);
+            response = EKeyWasConsumed;
+            UpdatePageTitleL();
+            }
+            break;
+        case EKeyLeftArrow:
+        case '4':
+            {
+            MoveFocus(-1,0);
+            response = EKeyWasConsumed;
+            }
+            break;
+        case EKeyRightArrow:
+        case '6':
+            {
+            MoveFocus(1,0);
+            response = EKeyWasConsumed;
+            }
+            break;
+        case EKeyUpArrow:
+        case '2':
+            {
+            response = EKeyWasConsumed;
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                if (iExtension->iRadioButton && !IsNextButton())
+                    {
+                    // Last radio button.
+                    if (iExtension->iRadioButton->EnterControl(
+                        0,iExtension->iRadioButton->Count()-1))
+                        {
+                        LeaveControl();
+                        }
+                    break;
+                    }
+                }
+            TInt xPos;
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                xPos = IsNextButton() ? iCharMap->MaxCols() - 1 : 0;
+                }
+            else
+                {
+                if (IsNextButton())
+                    {
+                    xPos = iCharMap->MaxCols() - 1;
+                    }
+                else
+                    {
+                    xPos = !iExtension->iRadioButton ?
+                        iCharMap->TableCount() : iCharMap->MaxCols()-2;
+                    }
+                }
+            if (iCharMap->ColMax(0) > iCharMap->ColMax(xPos))
+                {
+                xPos = iCharMap->RowMax(iCharMap->ColMax(0));
+                }
+            // Grid bottom row.
+            if (iExtension->EnterControl(xPos,iCharMap->ColMax(xPos)))
+                {
+                LeaveControl();
+                break;
+                }
+            }
+            break;
+        case EKeyDownArrow:
+        case '8':
+            {
+            response = EKeyWasConsumed;
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                if (!IsNextButton())
+                    {
+                    // First table button.
+                    if (iExtension->iTableNavi &&
+                        iExtension->iTableNavi->EnterControl(0,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                else
+                    {
+                    // Grid top row.
+                    TInt xPos = iCharMap->MaxCols() - 1;
+                    if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos)))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                }
+            else
+                {
+                TInt xPos;
+                if (IsNextButton())
+                    {
+                    xPos = iCharMap->MaxCols() - 1;
+                    }
+                else
+                    {
+                    xPos = !iExtension->iRadioButton ?
+                        iCharMap->TableCount() : iCharMap->MaxCols() - 2;
+                    }
+                // Grid top row.
+                if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos)))
+                    {
+                    LeaveControl();
+                    break;
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    return response;
+    }
+
+TBool CAknSctPageNavi::IsNextButton() const
+    {
+    if (iButtonIndex < iButtonArray.Count() && iButtonArray[iButtonIndex])
+        {
+        return iButtonArray[iButtonIndex]->iButtonId == EAknSctPageNaviNextPage;
+        }
+    return EFalse;
+    }
+
+void CAknSctPageNavi::ConstructFromResourceL(TResourceReader& aReader)
+    {
+    TInt counts = aReader.ReadInt16();
+    for (TInt i = 0; i < counts; i++)
+        {
+        TInt buttonId = aReader.ReadInt16();
+        TInt resId = aReader.ReadInt32();
+        TResourceReader oneButtonReader;
+        iCoeEnv->CreateResourceReaderLC(oneButtonReader, resId);
+        CAknSctNaviButton* buttonObj =
+            CAknSctNaviButton::NewL(*this, buttonId, oneButtonReader);
+        buttonObj->iButtonControl->SetObserver(this); // for handling control events.
+        iButtonArray.Append(buttonObj);
+        CleanupStack::PopAndDestroy(); // oneButtonReader
+        }
+    iTitle = new (ELeave) CEikLabel;
+    }
+
+void CAknSctPageNavi::HandleControlEventL(
+    CCoeControl* aControl,
+    TCoeEvent aEventType)
+    {
+    if (aEventType == EEventStateChanged && AknLayoutUtils::PenEnabled()) // action on key repeat
+        {
+        for (TInt index=0; index < iButtonArray.Count(); index++)
+            {
+            CAknSctNaviButton* buttonObj = iButtonArray[index];
+            TRect buttonRect = buttonObj->iButtonControl->Rect();
+            if (buttonObj->iButtonControl == aControl)
+                {
+                if (buttonObj->IsEnabled() && buttonObj->iPressed)
+                    {
+                    iButtonIndex = index;
+                    switch (buttonObj->iButtonId)
+                        {
+                        case EAknSctPageNaviPrevPage:
+                            {
+                            buttonObj->iRepeat = ETrue; // Set button repeat.
+                            iCharMap->PrevPageL();
+                            UpdatePageTitleL();
+                            }
+                            break;
+                        case EAknSctPageNaviNextPage:
+                            {
+                            buttonObj->iRepeat = ETrue; // Set button repeat.
+                            iCharMap->NextPageL();
+                            UpdatePageTitleL();
+                            }
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+void CAknSctPageNavi::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition))
+        {
+        if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+            {
+            for (TInt index=0; index < iButtonArray.Count(); index++)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[index];
+                buttonObj->iPressed = EFalse;
+                buttonObj->iRepeat = EFalse;
+                TRect buttonRect = buttonObj->iButtonControl->Rect();
+                if (buttonRect.Contains(aPointerEvent.iPosition))
+                    {
+                    if (buttonObj->IsEnabled())
+                        {
+                        buttonObj->iButtonControl->SetButtonFlags(KAknButtonKeyRepeat);
+                        buttonObj->iPressed = ETrue; // Set button pressed.
+                        }
+                    }
+                }
+            }
+        else if (aPointerEvent.iType == TPointerEvent::EButton1Up) // action on button release.
+            {
+            for (TInt index=0; index < iButtonArray.Count(); index++)
+                {
+                CAknSctNaviButton* buttonObj = iButtonArray[index];
+                TRect buttonRect = buttonObj->iButtonControl->Rect();
+                if (buttonRect.Contains(aPointerEvent.iPosition))
+                    {
+                    if (buttonObj->IsEnabled())
+                        {
+                        if (buttonObj->iPressed && !buttonObj->iRepeat)
+                            {
+                            iButtonIndex = index;
+                            switch (buttonObj->iButtonId)
+                                {
+                                case EAknSctPageNaviPrevPage:
+                                    {
+                                    iCharMap->PrevPageL();
+                                    UpdatePageTitleL();
+                                    }
+                                    break;
+                                case EAknSctPageNaviNextPage:
+                                    {
+                                    iCharMap->NextPageL();
+                                    UpdatePageTitleL();
+                                    }
+                                    break;
+                                default:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                buttonObj->iPressed = EFalse; // Button released.
+                buttonObj->iRepeat = EFalse;
+                }
+            }
+        }
+    CCoeControl::HandlePointerEventL(aPointerEvent);
+    }
+
+TSize CAknSctPageNavi::MinimumSize()
+    {
+    return Rect().Size();
+    }
+
+void CAknSctPageNavi::SizeChanged()
+    {
+
+    TAknLayoutRect pageButtonLayRect;
+    TInt pageVariate = !iCharMap->IsJapaneseSctUi() ? ((iCharMap->TableCount() > 1) ? 0 : 1) : 2;
+                       
+    CAknSctNaviButton* buttonObj;
+    TRect rect;
+
+    buttonObj = iButtonArray[0];
+    buttonObj->iButtonControl->SetButtonFlags(0);
+    if (!AknLayoutUtils::LayoutMirrored())
+        {
+        buttonObj->iButtonId = EAknSctPageNaviPrevPage;
+        pageButtonLayRect.LayoutRect(Rect(),AknLayoutScalable_Avkon::bg_button_pane_cp10(pageVariate));
+        }
+    else
+        {
+        buttonObj->iButtonId = EAknSctPageNaviNextPage;
+        pageButtonLayRect.LayoutRect(Rect(),AknLayoutScalable_Avkon::bg_button_pane_cp11(pageVariate));
+        }
+    rect = pageButtonLayRect.Rect();
+    buttonObj->iButtonControl->SetRect(rect);
+    buttonObj->iButtonControl->SetHighlightRect(rect);
+    TAknLayoutRect pageButtonIconLayRect;
+    pageButtonIconLayRect.LayoutRect(pageButtonLayRect.Rect(), AknLayoutScalable_Avkon::graphic2_pages_pane_g1(pageVariate));
+    buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved);
+    TSize iconSize = pageButtonIconLayRect.Rect().Size();
+    buttonObj->iButtonControl->SetIconSize(iconSize);
+
+    buttonObj = iButtonArray[1];
+    buttonObj->iButtonControl->SetButtonFlags(0);
+    if (!AknLayoutUtils::LayoutMirrored())
+        {
+        buttonObj->iButtonId = EAknSctPageNaviNextPage;
+        pageButtonLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp11(pageVariate));
+        }
+    else
+        {
+        buttonObj->iButtonId = EAknSctPageNaviPrevPage;
+        pageButtonLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp10(pageVariate));
+        }
+    rect = pageButtonLayRect.Rect();
+    buttonObj->iButtonControl->SetRect(rect);
+    buttonObj->iButtonControl->SetHighlightRect(rect);
+    buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved);
+    buttonObj->iButtonControl->SetIconSize(iconSize);
+
+    // Page text.
+    TRect parentRect = Rect();
+    AknLayoutUtils::LayoutLabel(iTitle, parentRect, AknLayoutScalable_Avkon::graphic2_pages_pane_t1(pageVariate).LayoutLine());
+
+    // Page text color
+    TAknLayoutText textLayout;
+    textLayout.LayoutText(parentRect, AknLayoutScalable_Avkon::graphic2_pages_pane_t1(pageVariate));
+    TRect textRect = textLayout.TextRect();
+    TRgb color = textLayout.Color();
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    if (skin)
+        {
+        (void)AknsUtils::GetCachedColor(skin, color, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
+        }
+    TRAP_IGNORE(AknLayoutUtils::OverrideControlColorL(*iTitle, EColorLabelText, color));
+    TRAP_IGNORE(UpdatePageTitleL());
+    }
+
+void CAknSctPageNavi::Draw(const TRect& /*aRect*/) const
+    {
+    TRAP_IGNORE(UpdatePageTitleL());
+    }
+
+void CAknSctPageNavi::UpdatePageTitleL() const
+    {
+    CArrayFix<TInt>* numbers = new(ELeave)CArrayFixFlat<TInt>(2);
+    CleanupStack::PushL(numbers);
+    numbers->AppendL(iCharMap->CurrentPage());
+    numbers->AppendL(iCharMap->PageCount());
+    HBufC* page =
+        StringLoader::LoadL(
+            R_AVKON_SPECIAL_CHARACTERS_PAGE_INDICATOR, *numbers, iEikonEnv);
+    CleanupStack::PopAndDestroy(); // numbers
+    iTitle->SetTextL(page->Des());
+    iTitle->SetBrushStyle(CGraphicsContext::ENullBrush);
+    delete page;
+    }
+
+CCoeControl* CAknSctPageNavi::FocusedControl()
+    {
+    return this;
+    }
+
+TBool CAknSctPageNavi::EnterControl(TInt aX, TInt /*aY*/)
+    {
+    if (IsVisible())
+        {
+        if ((aX >= 0) && (aX < iButtonArray.Count()))
+            {
+            CAknSctNaviButton* buttonObj;
+            buttonObj = iButtonArray[iButtonIndex];
+            buttonObj->SetFocused(EFalse);
+            TInt index = aX;
+            if (AknLayoutUtils::LayoutMirrored()) // reverse.
+                {
+                index = iButtonArray.Count() - 1 - aX;
+                }
+            buttonObj = iButtonArray[index];
+            if (buttonObj->IsEnabled())
+                {
+                iButtonIndex = index;
+                iExtension->iFocusHandler = this;
+                buttonObj->SetFocused(ETrue);
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;
+    }
+
+void CAknSctPageNavi::MoveFocus(TInt aX, TInt /*aY*/)
+    {
+    TInt delta = aX;
+    TInt buttonIndex = iButtonIndex + delta;
+    for (TInt i = 0; i < iButtonArray.Count(); i++)
+        {
+        if (buttonIndex > iButtonArray.Count() - 1) // Next control.
+            {
+            if (!AknLayoutUtils::LayoutMirrored())
+                {
+                if (!Layout_Meta_Data::IsLandscapeOrientation())
+                    {
+                    // First table button.
+                    if (iExtension->iTableNavi &&
+                        iExtension->iTableNavi->EnterControl(0,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                else
+                    {
+                    // First radio button.
+                    if (iExtension->iRadioButton &&
+                        iExtension->iRadioButton->EnterControl(0,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    // Grid start.
+                    TInt yPos = iCharMap->ColMin(0);
+                    if (iExtension->EnterControl(iCharMap->RowMin(yPos),yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                }
+            else
+                {
+                if (!Layout_Meta_Data::IsLandscapeOrientation())
+                    {
+                    // Grid end.
+                    TInt yPos = iCharMap->ColMax(0);
+                    if (iExtension->EnterControl(iCharMap->RowMax(yPos),yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                else
+                    {
+                    // Last table button.
+                    TInt xPos = iCharMap->TableCount() - 1;
+                    if (iExtension->iTableNavi &&
+                        iExtension->iTableNavi->EnterControl(xPos,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                }
+            break;
+            }
+        else if (buttonIndex < 0) // Prev control
+            {
+            if (!AknLayoutUtils::LayoutMirrored())
+                {
+                if (!Layout_Meta_Data::IsLandscapeOrientation())
+                    {
+                    // Grid end.
+                    TInt yPos = iCharMap->ColMax(0);
+                    if (iExtension->EnterControl(iCharMap->RowMax(yPos),yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                else
+                    {
+                    // Last table button.
+                    if (iExtension->iTableNavi && 
+                        iExtension->iTableNavi->EnterControl(iCharMap->TableCount()-1,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                }
+            else
+                {
+                if (!Layout_Meta_Data::IsLandscapeOrientation())
+                    {
+                    // First table button.
+                    if (iExtension->iTableNavi &&
+                        iExtension->iTableNavi->EnterControl(0,0))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                else
+                    {
+                    // Grid start.
+                    TInt yPos = iCharMap->ColMin(0);
+                    if (iExtension->EnterControl(iCharMap->RowMin(yPos),yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                }
+            }
+
+        if (iButtonArray[buttonIndex]->IsEnabled()) // This control
+            {
+            CAknSctNaviButton* buttonObj;
+            buttonObj = iButtonArray[iButtonIndex];
+            buttonObj->SetFocused(EFalse);
+            iButtonIndex = buttonIndex;
+            buttonObj = iButtonArray[iButtonIndex];
+            buttonObj->SetFocused(ETrue);
+            break;
+            }
+        buttonIndex += (delta < 0) ? -1 : 1;
+        }
+    }
+
+TBool CAknSctPageNavi::LeaveControl()
+    {
+    for (TInt i = 0; i < iButtonArray.Count(); i++ )
+        {
+        iButtonArray[i]->SetFocused(EFalse);
+        }
+    return ETrue;
+    }
+
+TBool CAknSctPageNavi::ExitWithKey(TInt /*aKeycode*/)
+    {
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// Category button class implementation
+// ----------------------------------------------------------------------------
+//
+CAknSctCategoryButton* CAknSctCategoryButton::NewL(
+    const CCoeControl& aParent,
+    TResourceReader& reader,
+    TInt aCategoryButtonId,
+    TInt aSctCaseId)
+    {
+    CAknSctCategoryButton* self =
+        new( ELeave ) CAknSctCategoryButton(aCategoryButtonId, aSctCaseId);
+
+    CleanupStack::PushL( self );
+    self->ConstructL(aParent, reader);
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+CAknSctCategoryButton::CAknSctCategoryButton(
+    TInt aCategoryButtonId,
+    TInt aSctCaseId)
+    : iButtonId(aCategoryButtonId)
+    , iSctCaseId(aSctCaseId)
+    {
+    }
+
+void CAknSctCategoryButton::ConstructL(
+    const CCoeControl& aParent,
+    TResourceReader& aReader)
+    {
+    iButtonControl = CAknButton::NewL(aReader);
+    iButtonControl->SetContainerWindowL(aParent);
+    }
+
+CAknSctCategoryButton::~CAknSctCategoryButton()
+    {
+    delete iButtonControl;
+    }
+
+void CAknSctCategoryButton::SetFocused(TBool aState)
+    {
+    iButtonControl->SetFocus(aState);
+    iButtonControl->DrawNow();
+    }
+
+
+// ----------------------------------------------------------------------------
+// Radio button class implementation
+// ----------------------------------------------------------------------------
+//
+CAknSctRadioButton::CAknSctRadioButton()
+    {
+    }
+
+CAknSctRadioButton::CAknSctRadioButton(
+    CAknCharMap* aCharMap,
+    CAknCharMapExtension* aExtension)
+    :iExtension(aExtension),
+    iCharMap(aCharMap)
+    {
+    }
+
+CAknSctRadioButton::~CAknSctRadioButton()
+    {
+    iButtonArray.ResetAndDestroy();
+    iButtonArray.Close();
+    }
+
+TInt CAknSctRadioButton::CountComponentControls() const
+    {
+    return iButtonArray.Count();
+    }
+
+CCoeControl* CAknSctRadioButton::ComponentControl( TInt aIndex ) const
+    {
+    if (aIndex < iButtonArray.Count())
+        {
+        return iButtonArray[aIndex]->iButtonControl;
+        }
+    return NULL;
+    }
+
+TKeyResponse CAknSctRadioButton::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent,
+    TEventCode /*aModifiers*/)
+    {
+    TKeyResponse responce = EKeyWasNotConsumed;
+    TUint code=aKeyEvent.iCode;
+    switch (code)
+        {
+        case EKeyEnter:
+        case EKeyOK:
+            {
+            if (AknLayoutUtils::PenEnabled())
+                {
+                // Grid.
+                TInt yPos = iCharMap->ColMin(0);
+                TInt xPos = iCharMap->RowMin(yPos);
+                if (iExtension->EnterControl(xPos,yPos))
+                    {
+                    CAknButton* buttonCtrlObj;
+                    TInt currentIndex;
+                    TInt newIndex;
+                    for (TInt index=0; index < iButtonArray.Count(); index++)
+                        {
+                        buttonCtrlObj = iButtonArray[index]->iButtonControl;
+                        currentIndex = buttonCtrlObj->StateIndex();
+                        if (index == iButtonIndex)
+                            {
+                            newIndex = KAknSctRadioOn;
+                            }
+                        else
+                            {
+                            newIndex = KAknSctRadioOff;
+                            }
+                        if (currentIndex != newIndex)
+                            {
+                            buttonCtrlObj->SetCurrentState(newIndex, ETrue);
+                            if (newIndex == KAknSctRadioOn)
+                                {
+                                iExtension->iCurrentCategory =
+                                    iButtonArray[index]->iButtonId;
+                                iCharMap->SetStatusChanged(EAknCharChangedCategory);
+                                }
+                            }
+                        }
+                    LeaveControl();
+                    }
+                }
+            responce = EKeyWasConsumed;
+            }
+            break;
+        case EKeyLeftArrow:
+        case '4':
+            {
+            responce = EKeyWasConsumed;
+            if (AknLayoutUtils::PenEnabled())
+                {
+                TInt yPos = iButtonIndex - 1;
+                if (iCharMap->RowMax(yPos) < 0)
+                    {
+                    if (Layout_Meta_Data::IsLandscapeOrientation())
+                        {
+                        if (iExtension->iRadioButton)
+                            {
+                            // Right page button.
+                            if (iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(1,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        }
+                    // Next button up.
+                    MoveFocus(0,-1);
+                    break;
+                    }
+                else
+                    {
+                    //Previous row end.
+                    TInt xPos = iCharMap->RowMax(yPos);
+                    if (iExtension->EnterControl(xPos,yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                break;
+                }
+            // Move by grid.
+            iCharMap->TakeFocus();
+            TInt xPos = iCharMap->CursorPos().iX;
+            TInt yPos = iCharMap->CursorPos().iY;
+            if (xPos == 0)
+                {
+                iCharMap->MoveFocus(-1,0);
+                }
+            iCharMap->ShowFocus();
+            }
+            break;
+        case EKeyRightArrow:
+        case '6':
+            {
+            responce = EKeyWasConsumed;
+            if (AknLayoutUtils::PenEnabled())
+                {
+                TInt yPos = iButtonIndex;
+                if (iCharMap->RowMax(yPos) < 0)
+                    {
+                    // Next button down.
+                    MoveFocus(0,1);
+                    break;
+                    }
+                else
+                    {
+                    // 1st cell in the row.
+                    if (iExtension->EnterControl(0,yPos))
+                        {
+                        LeaveControl();
+                        break;
+                        }
+                    }
+                break;
+                }
+            // Move by grid.
+            iCharMap->TakeFocus();
+            TInt xPos = iCharMap->CursorPos().iX;
+            TInt yPos = iCharMap->CursorPos().iY;
+            if (xPos == iCharMap->RowMax(yPos))
+                {
+                iCharMap->MoveFocus(1,0);
+                }
+            iCharMap->ShowFocus();
+            }
+            break;
+        case EKeyDownArrow:
+        case '8':
+            {
+            MoveFocus(0, 1);
+            responce = EKeyWasConsumed;
+            }
+            break;
+        case EKeyUpArrow:
+        case '2':
+            {
+            MoveFocus(0,-1);
+            responce = EKeyWasConsumed;
+            }
+            break;
+        default:
+            break;
+        }
+    return responce;
+    }
+
+void CAknSctRadioButton::ConstructFromResourceL(TResourceReader& aReader)
+    {
+    TInt counts = aReader.ReadInt16();
+    TResourceReader reader;
+    TInt categorybutton_id;
+    TInt sctcase_id;
+    TInt resId;
+    CAknSctCategoryButton* buttonObj;
+    TBool allowCreation;
+
+    for (TInt index=0; index < counts; index++)
+        {
+        allowCreation = EFalse;
+        // button id
+        categorybutton_id = aReader.ReadInt16();
+        sctcase_id = aReader.ReadInt16();
+        switch (categorybutton_id)
+            {
+            case EAknSCTCategoryButtonHalfCase:
+            case EAknSCTCategoryButtonFullCase:
+                allowCreation = ETrue;
+                break;
+            case EAknSCTCategoryButtonPicto:
+                if (iExtension->iPictographsBuffer)
+                    {
+                    allowCreation = ETrue;
+                    }
+                break;
+            case EAknSCTCategoryButtonPicto1:
+            case EAknSCTCategoryButtonPicto2:
+                if (iExtension->iPictographsBuffer &&
+                    iExtension->iPictographsBufferGrouping)
+                    {
+                    allowCreation = ETrue;
+                    }
+                break;
+            default:
+                break;
+            }
+
+        if (allowCreation)
+            {
+            // read the button resource
+            resId = aReader.ReadInt32();
+            iCoeEnv->CreateResourceReaderLC( reader, resId );
+            // create Category button object
+            buttonObj = CAknSctCategoryButton::NewL(
+                *this, reader, categorybutton_id, sctcase_id);
+            // Append button
+            iButtonArray.Append(buttonObj);
+            CleanupStack::PopAndDestroy(); // reader
+            }
+        else
+            {
+            // Skip data
+            resId = aReader.ReadInt32();
+            }
+        }
+
+    }
+
+void CAknSctRadioButton::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    TRect rect(Rect());
+    if (AknLayoutUtils::PenEnabled() && rect.Contains(aPointerEvent.iPosition))
+        {
+        if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+            {
+            CAknButton* buttonCtrlObj;
+            TRect rectButton;
+            TInt currentIndex;
+            TInt newIndex;
+            for (TInt index=0; index < iButtonArray.Count(); index++)
+                {
+                buttonCtrlObj = iButtonArray[index]->iButtonControl;
+                rectButton = buttonCtrlObj->Rect();
+                currentIndex = buttonCtrlObj->StateIndex();
+
+                if (rectButton.Contains(aPointerEvent.iPosition))
+                    {
+                    newIndex = KAknSctRadioOn;
+                    }
+                else
+                    {
+                    newIndex = KAknSctRadioOff;
+                    }
+                if (currentIndex != newIndex)
+                    {
+                    buttonCtrlObj->SetCurrentState(newIndex, ETrue);
+                    if (newIndex == KAknSctRadioOn)
+                        {
+                        if (AknLayoutUtils::PenEnabled())
+                            {
+                            iButtonIndex = index;
+                            }
+                        iExtension->iCurrentCategory =
+                            iButtonArray[index]->iButtonId;
+                        iCharMap->SetStatusChanged(EAknCharChangedCategory);
+                        }
+                    }
+                }
+            }
+        else if (aPointerEvent.iType == TPointerEvent::EDrag)
+            {
+            }
+        else if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+            {
+            }
+        }
+    else
+        {
+        CCoeControl::HandlePointerEventL(aPointerEvent);
+        }
+    }
+
+TSize CAknSctRadioButton::MinimumSize()
+    {
+    TAknLayoutRect oneButtonLayRect;
+    if (!AknLayoutUtils::PenEnabled())
+        {
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        // Main pane without softkeys
+        TRect mainPaneRect;
+        if(!AknLayoutUtils::LayoutMetricsRect(
+            AknLayoutUtils::EPopupParent, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        // Calc the variety
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(mainPaneRect,
+            AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVariety));
+
+        // Calculate the size relatively
+        TRect relativeDialog(TPoint(0,0),popupGridLayRect.Rect().Size());
+
+        // Get the layout of the actual character grid with scrollbar
+        TAknLayoutRect gridWithScrollLayRect;
+        gridWithScrollLayRect.LayoutRect(relativeDialog,
+            AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+        TAknLayoutRect categoryButtonLayRect;
+        categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(),
+            AknLayoutScalable_Avkon::grid_sct_catagory_button_pane());
+
+        oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(),
+            AknLayoutScalable_Avkon::cell_sct_catagory_button_pane());
+        }
+    else
+        {
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+        TAknLayoutRect oneButtonLayRect;
+        TAknLayoutRect categoryButtonLayRect;
+        if (!Layout_Meta_Data::IsLandscapeOrientation())
+            {
+            oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_control_pane(4));
+
+            categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_catg_pane(0));
+            }
+        else
+            {
+            oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_control_pane(5));
+
+            categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_catg_pane(1));
+
+            }
+        }
+
+    TSize size(oneButtonLayRect.Rect().Width(),
+        oneButtonLayRect.Rect().Height() * iButtonArray.Count());
+    return size;
+    }
+
+void CAknSctRadioButton::SizeChanged()
+    {
+    TRect base;
+    if (!AknLayoutUtils::PenEnabled())
+        {
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        // Main pane without softkeys
+        TRect mainPaneRect;
+        if(!AknLayoutUtils::LayoutMetricsRect(
+            AknLayoutUtils::EPopupParent, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        // Calc the variety
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(mainPaneRect,
+            AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVariety));
+
+        // Calculate the size relatively
+        TRect relativeDialog(TPoint(0,0), popupGridLayRect.Rect().Size());
+
+        // Get the layout of the actual character grid with scrollbar
+        TAknLayoutRect gridWithScrollLayRect;
+        gridWithScrollLayRect.LayoutRect(relativeDialog,
+            AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+        TAknLayoutRect categoryButtonLayRect;
+        categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(),
+            AknLayoutScalable_Avkon::grid_sct_catagory_button_pane());
+
+        TAknLayoutRect oneButtonLayRect;
+        oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(),
+            AknLayoutScalable_Avkon::cell_sct_catagory_button_pane());
+
+        base = oneButtonLayRect.Rect();
+        }
+    else
+        {
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+        TAknLayoutRect oneButtonLayRect;
+        TAknLayoutRect categoryButtonLayRect;
+        if ( !Layout_Meta_Data::IsLandscapeOrientation() )
+            {
+            oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_control_pane(4));
+
+            categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_catg_pane(0));
+            }
+        else
+            {
+            oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_control_pane(5));
+
+            categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic2_catg_pane(1));
+
+            }
+        base.iTl = categoryButtonLayRect.Rect().iTl;
+        base.SetSize(oneButtonLayRect.Rect().Size());
+        }
+
+    if (iButtonArray.Count() > 0)
+        {
+        CAknButton* buttonCtrlObj;
+
+        TMargins8 margins;
+        margins.iTop = 1;
+        margins.iBottom = 0;
+        margins.iLeft = 0;
+        margins.iRight = 0;
+
+        // Change the size of buttons
+        for (TInt index=0; index < iButtonArray.Count(); index++)
+            {
+            buttonCtrlObj = iButtonArray[index]->iButtonControl;
+            if (buttonCtrlObj)
+                {
+                if (AknLayoutUtils::PenEnabled())
+                    {
+                    buttonCtrlObj->SetHighlightRect(base);
+                    }
+                buttonCtrlObj->SetRect( base );
+                buttonCtrlObj->SetIconSize( base.Size() );
+                buttonCtrlObj->SetMargins( margins );
+                buttonCtrlObj->SetIconScaleMode(EAspectRatioPreserved);
+                base.Move(TPoint(0, base.Size().iHeight));
+                }
+            }
+        }
+    }
+
+void CAknSctRadioButton::Draw(const TRect& /*aRect*/) const
+    {
+    // no draw
+    }
+
+/**
+ * Returns ETrue if the aFlag bitfield in iFlags is set, EFalse if it
+ * is clear
+ */
+inline TInt CAknSctRadioButton::Count() const
+    {
+    return iButtonArray.Count();
+    }
+
+void CAknSctRadioButton::SetCurrentCategory(TInt aCategory)
+    {
+    CAknSctCategoryButton* buttonObj;
+    TInt status;
+
+    for (TInt index=0; index < iButtonArray.Count(); index++)
+        {
+        buttonObj = iButtonArray[index];
+        status = (buttonObj->iButtonId == aCategory)?
+                     KAknSctRadioOn : KAknSctRadioOff;
+        buttonObj->iButtonControl->SetCurrentState(status, ETrue);
+        }
+    }
+
+void CAknSctRadioButton::SetValidSctCase(TInt aSctCase)
+    {
+    CAknSctCategoryButton* buttonObj;
+
+    for (TInt index=0; index < iButtonArray.Count(); index++)
+        {
+        buttonObj = iButtonArray[index];
+        if (buttonObj->iSctCaseId == aSctCase)
+            {
+            buttonObj->iValid = ETrue;
+            break;
+            }
+        // Here is the special case for Half-width/Lower/Upper
+        else if (buttonObj->iSctCaseId == EAknSCTHalfCase
+              && (aSctCase == EAknSCTLowerCase
+                 || aSctCase == EAknSCTUpperCase)
+                )
+            {
+            buttonObj->iValid = ETrue;
+            break;
+            }
+        }
+    }
+
+void CAknSctRadioButton::RemoveInvalidButton()
+    {
+    CAknSctCategoryButton* buttonObj;
+
+    for (TInt index=iButtonArray.Count()-1; index >= 0; index--)
+        {
+        buttonObj = iButtonArray[index];
+        if (!buttonObj->iValid)
+            {
+            if (buttonObj->iSctCaseId == EAknSCTHalfCase)
+                {
+                if (iButtonArray.Count() > 1)
+                    {
+                    delete buttonObj;
+                    iButtonArray.Remove(index);
+                    }
+                }
+            else
+                {
+                delete buttonObj;
+                iButtonArray.Remove(index);
+                }
+            }
+        }
+    }
+
+CCoeControl* CAknSctRadioButton::FocusedControl()
+    {
+    return this;
+    }
+
+TBool CAknSctRadioButton::EnterControl(TInt /*aX*/, TInt aY)
+    {
+    if (IsVisible())
+        {
+        if ((aY >= 0) && (aY < Count()))
+            {
+            if (iExtension->iHasCategoryButtonUi)
+                {
+                iEntryIndex = aY;
+                iExtension->iFocusHandler = this;
+                if (AknLayoutUtils::PenEnabled())
+                    {
+                    iButtonIndex = aY;
+                    CAknSctCategoryButton* buttonObj =
+                        iButtonArray[iButtonIndex];
+                    buttonObj->SetFocused(ETrue);
+                    }
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;
+    }
+
+void CAknSctRadioButton::MoveFocus(TInt /*aX*/, TInt aY)
+    {
+    CAknSctCategoryButton* buttonObj;
+    CAknButton* buttonCtrlObj;
+    TInt buttonIndex = iButtonIndex + aY;
+    if (buttonIndex > iButtonArray.Count() - 1)
+        {
+        if (!AknLayoutUtils::PenEnabled())
+            {
+             // First radio button.
+            buttonIndex = 0;
+            }
+        else
+            {
+            if (!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                // Left page button.
+                if (iExtension->iPageNavi &&
+                    iExtension->iPageNavi->EnterControl(0,0))
+                    {
+                    LeaveControl();
+                    return;
+                    }
+                }
+            else
+                {
+                // First table button.
+                if (iExtension->iTableNavi &&
+                    iExtension->iTableNavi->EnterControl(0,0))
+                    {
+                    LeaveControl();
+                    return;
+                    }
+                }
+            }
+        }
+    else if (buttonIndex < 0)
+        {
+         if (!AknLayoutUtils::PenEnabled())
+            {
+            // Last radio button.
+            buttonIndex = iButtonArray.Count() - 1;
+            }
+         else
+            {
+            // First table button.
+            if (iExtension->iTableNavi &&
+                iExtension->iTableNavi->EnterControl(0,0))
+                {
+                LeaveControl();
+                return;
+                }
+            }
+        }
+
+    if (!AknLayoutUtils::PenEnabled())
+        {
+        buttonObj = iButtonArray[iButtonIndex];
+        buttonCtrlObj = buttonObj->iButtonControl;
+        buttonCtrlObj->SetCurrentState(KAknSctRadioOff, ETrue);
+        iButtonIndex = buttonIndex;
+        buttonObj = iButtonArray[iButtonIndex];
+        buttonCtrlObj = buttonObj->iButtonControl;
+        buttonCtrlObj->SetCurrentState(KAknSctRadioOn, ETrue);
+        iExtension->iCurrentCategory =
+            iButtonArray[buttonIndex]->iButtonId;
+        iCharMap->SetStatusChanged(EAknCharChangedCategory);
+        }
+    else
+        {
+        buttonObj = iButtonArray[iButtonIndex];
+        buttonObj->SetFocused(EFalse);
+        iButtonIndex = buttonIndex;
+        buttonObj = iButtonArray[iButtonIndex];
+        buttonObj->SetFocused(ETrue);
+        }
+    }
+
+TBool CAknSctRadioButton::LeaveControl()
+    {
+    for (TInt i = 0; i < iButtonArray.Count(); i++ )
+        {
+        iButtonArray[i]->SetFocused(EFalse);
+        }
+    return ETrue;
+    }
+
+TBool CAknSctRadioButton::ExitWithKey(TInt /*aKeycode*/)
+    {
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// Extension class implementation
+// ----------------------------------------------------------------------------
+//
+CAknCharMapExtension::CAknCharMapExtension() : iSmileyModel(this)
+,iSingleClickEnabled( iAvkonAppUi->IsSingleClickCompatible() )
+    {
+    iObserver = NULL;
+    iPictographsBuffer = FeatureManager::FeatureSupported(KFeatureIdJapanesePicto);
+    iPictographsBufferGrouping = FeatureManager::FeatureSupported(KFeatureIdJapanesePictographsGrouping);
+    iKineticScrolling = CAknPhysics::FeatureEnabled();
+
+    TRAP_IGNORE(iSmileyModel.LoadResourceL());
+    }
+
+TTypeUid::Ptr CAknCharMapExtension::MopSupplyObject(TTypeUid aId)
+    {
+    return MAknsControlContext::SupplyMopObject(aId, iBgContext );
+    }
+
+MObjectProvider* CAknCharMapExtension::MopNext()
+    {
+    return iCharMap;
+    }
+
+CAknCharMapExtension::~CAknCharMapExtension()
+    {
+    delete iCharsSmiley;
+    delete iCharsQwerty;
+    delete iBgContext;
+
+    delete iRadioButton;
+    delete iTitleBuf;
+
+    delete iPageNavi;
+    delete iTableNavi;
+    delete iCategoryTitle;
+    delete iCategoryEntry;
+    delete iEntryBuf;
+    }
+
+void CAknCharMapExtension::SetCharMapControl(CAknCharMap* aCtrl)
+    {
+    iCharMapProxy = aCtrl;
+    }
+
+MAknSctFocusHandler* CAknCharMapExtension::FocusHandler()
+    {
+    return iFocusHandler;
+    }
+
+CCoeControl* CAknCharMapExtension::FocusedControl()
+    {
+    return iCharMapProxy;
+    }
+
+TBool CAknCharMapExtension::EnterControl(TInt aX, TInt aY)
+    {
+    if(iCharMapProxy->EnterControl(aX, aY))
+        {
+        iFocusHandler = this;
+        iCharMapProxy->HandleFocusStatusChanged();
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+void CAknCharMapExtension::MoveFocus(TInt aX, TInt aY)
+    {
+    iCharMapProxy->TakeFocus();
+    TRAP_IGNORE(iCharMapProxy->MoveFocus(aX, aY));
+    }
+
+TBool CAknCharMapExtension::LeaveControl()
+    {
+    return iCharMapProxy->LeaveControl();
+    }
+
+TBool CAknCharMapExtension::ExitWithKey(TInt /*aKeycode*/)
+    {
+    return ETrue;
+    }
+
+void CAknCharMapExtension::ThumbnailLoaded(CSmileyIcon* /*aSmileyIcon*/)
+    {
+    iCharMapProxy->DrawDeferred();
+    }
+
+void CAknCharMapExtension::AnimationChanged(CSmileyIcon* /*aSmileyIcon*/)
+    {
+    iCharMapProxy->DrawCursor();
+    }
+
+TBool CAknCharMapExtension::IsEmotionEnabled() const
+    {
+    return iIsEnableEmotion;
+    }
+
+TBool CAknCharMapExtension::IsShowingEmotion() const
+    {
+    return iIsShowingEmotion;
+    }
+
+TBool CAknCharMapExtension::NeedEmotionSwitchIcon() const
+    {
+    // Emotion switch char
+    TBool needEmotionSwitchIcon = (!AknLayoutUtils::PenEnabled() && IsEmotionEnabled() && !iMenuSct);
+    return needEmotionSwitchIcon;
+    }
+
+HBufC* CAknCharMapExtension::ReadEmotionHBufCL()
+    {
+    TInt smileyCount = iSmileyModel.Count();
+    HBufC* charsSmiley = HBufC::NewL(smileyCount);
+    TPtr charsSmileyPtr(charsSmiley->Des());
+    for(TInt id(CSmileyModel::EIconSmiley); id<smileyCount; id++)
+        {
+        charsSmileyPtr.Append(TEmotionUtils::EmotionChar(id));
+        }
+    
+    return charsSmiley;
+    }
+
+void CAknCharMapExtension::LoadEmotionTumbnails(const TDesC& aSctChars)
+    {
+    for(TInt i(0); i<aSctChars.Length(); i++)
+        {
+        iSmileyModel.LoadThumbnailAsyn(TEmotionUtils::EmotionId(aSctChars[i]));
+        }
+    }
+
+void CAknCharMapExtension::SetEmotionSize(const TSize& aSize)
+    {
+    TInt unit = Min(aSize.iWidth, aSize.iHeight);
+    iSmileyModel.SetSize(TSize(unit,unit));
+    }
+
+CSmileyIcon* CAknCharMapExtension::EmotionIcon(TChar aEmotionChar)
+    {
+    if(TEmotionUtils::IsEmotionChar(aEmotionChar))
+        {
+        return iSmileyModel[TEmotionUtils::EmotionId(aEmotionChar)];
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+TBool CAknCharMapExtension::DrawEmotion(CWindowGc& aGc, const TRect& aRect, TChar aEmotionChar)
+    {
+    CSmileyIcon* icon = EmotionIcon(aEmotionChar);
+    if(icon && icon->ReadyToDraw())
+        {
+        TRect iconRect(TPoint(),icon->Size());
+        TInt xoffset = (aRect.Width() - iconRect.Width()) / 2;
+        TInt yoffset = (aRect.Height() - iconRect.Height()) / 2;
+
+        aGc.BitBltMasked(aRect.iTl+TPoint(xoffset,yoffset), icon->Image(), iconRect, icon->Mask(), FALSE);
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+const TInt KEmotionAnimationRepeatCount = 30; // 30 times
+const TInt KEmotionAnimationDelay = 150*1000; // 0.15s
+
+void CAknCharMapExtension::HandleFocusStatusChanged(TChar aChar, TBool aIsFocused)
+    {
+    CSmileyIcon* lastIcon = EmotionIcon(iLastFocusedSmileyChar);
+    if(lastIcon)
+        {
+        lastIcon->StopAnimation();
+        }
+    
+    CSmileyIcon* focusedIcon = EmotionIcon(aChar);
+    if(focusedIcon)
+        {
+        if(aIsFocused)
+            {
+            if(iHighlightVisible)
+                {
+                TRAP_IGNORE(focusedIcon->PlayAnimationL(KEmotionAnimationRepeatCount, KEmotionAnimationDelay));
+                }
+            }
+        else
+            {
+            focusedIcon->StopAnimation();
+            }
+        }
+    
+    iLastFocusedSmileyChar = aChar;
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CAknCharMapHistory* CAknCharMapHistory::NewL()
+    {
+    CAknCharMapHistory* self = new (ELeave) CAknCharMapHistory;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMapHistory::ConstructL()
+    {
+    LoadL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::CAknCharMapHistory
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CAknCharMapHistory::CAknCharMapHistory()
+    {
+    }
+
+// Destructor
+CAknCharMapHistory::~CAknCharMapHistory()
+    {
+    ResetArray();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::LoadL()
+// Load recent characters from file
+// -----------------------------------------------------------------------------
+//
+TInt CAknCharMapHistory::LoadL()
+    {
+    // get the value of recently characters
+    const TInt length = KHistoryBufferSize * KHistoryBufferCount;
+    TBuf<length> buf;
+
+    CRepository* repository = CRepository::NewLC(KCRUidAvkon);
+    TInt err = repository->Get(KAknRecentSctData, buf); // Get KAknRecentSctData value
+    if (err == KErrNone)
+        {
+        if (buf.Length() != length) // buffer is not wanted
+            {
+            buf.Fill(KHistoryEmptyChar, length); // set default characters (default=tab character)
+            err = repository->Set(KAknRecentSctData, buf); // Create KAknRecentSctData key
+            }
+        }
+    CleanupStack::PopAndDestroy(repository); // repository
+    
+    // reset arrary
+    ResetArray();
+
+    // set recently characters to array
+    TInt parsePos = 0;
+    for (TInt i=0; i<EHistoryTypeMax; i++)
+        {
+        if (err != KErrNone)
+            {
+            // if err occurs, empty characters are set to recently characters.
+            iMixedHistoryArray[i].Fill(KHistoryEmptyChar, KHistoryBufferSize);
+            iTextHistoryArray[i].Fill(KHistoryEmptyChar, KHistoryBufferSize);
+            }
+        else
+            {
+            // parse from buf
+            iMixedHistoryArray[i].Copy(buf.Mid(parsePos, KHistoryBufferSize)); // mixed 
+            parsePos += KHistoryBufferSize;
+            
+            iTextHistoryArray[i].Copy(buf.Mid(parsePos, KHistoryBufferSize)); // text
+            parsePos += KHistoryBufferSize;
+            }
+        }
+
+    if (err != KErrNone)
+        {
+        iEmotionHistory.Fill(KHistoryEmptyChar, KHistoryBufferSize);
+        }
+    else
+        {
+        // parse from buf
+        iEmotionHistory.Copy(buf.Mid(parsePos, KHistoryBufferSize));
+        }
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::ResetArray()
+// Reset recent arrary
+// -----------------------------------------------------------------------------
+//
+void CAknCharMapHistory::ResetArray()
+    {
+    for(TInt i=0; i<EHistoryTypeMax; i++)
+        {
+        iMixedHistoryArray[i].Zero();
+        iTextHistoryArray[i].Zero();
+        }
+
+    iEmotionHistory.Zero();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::SaveL()
+// Save recent characters
+// -----------------------------------------------------------------------------
+//
+TInt CAknCharMapHistory::SaveL()
+    {
+    // save all recent used characters to buffer
+    const TInt length = KHistoryBufferSize * KHistoryBufferCount;
+    TBuf<length> buf;
+    
+    for (TInt i=0; i<EHistoryTypeMax; i++)
+        {
+        buf.Append(iMixedHistoryArray[i]);
+        buf.Append(iTextHistoryArray[i]);
+        }
+    
+    buf.Append(iEmotionHistory);
+
+    // Set KAknRecentSctData value
+    CRepository* repository = CRepository::NewLC(KCRUidAvkon);
+    TInt err = repository->Set(KAknRecentSctData, buf);
+    CleanupStack::PopAndDestroy(repository); // repository
+    
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::RecentString()
+// Get recent data
+// -----------------------------------------------------------------------------
+//
+const TDesC& CAknCharMapHistory::RecentString(THistoryType aHistoryType, THistoryFilter aHistoryFilter)
+    {
+    __ASSERT_ALWAYS((EHistoryTypeFull<=aHistoryType && aHistoryType<EHistoryTypeMax), Panic(EAknPanicInvalidValue));
+    
+    switch(aHistoryFilter)
+        {
+        case EHistoryFilterMixed:
+            break;
+            
+        case EHistoryFilterTextOnly:
+            return iTextHistoryArray[aHistoryType];
+            
+        case EHistoryFilterEmotionOnly:
+            return iEmotionHistory;
+
+        default:
+            break;
+        }
+    
+    return iMixedHistoryArray[aHistoryType];
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::InsertChar()
+// Insert a character which select on SCT/Picto.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMapHistory::InsertChar(THistoryType aHistoryType, const TChar aChar)
+    {
+    __ASSERT_ALWAYS((EHistoryTypeFull<=aHistoryType && aHistoryType<EHistoryTypeMax), Panic(EAknPanicInvalidValue));
+
+    InsertCharToHistoryBuf(iMixedHistoryArray[aHistoryType], aChar);
+
+    if(TEmotionUtils::IsEmotionChar(aChar))
+        {
+        InsertCharToHistoryBuf(iEmotionHistory, aChar);
+        }
+    else
+        {
+        InsertCharToHistoryBuf(iTextHistoryArray[aHistoryType], aChar);
+        }
+    }
+
+void CAknCharMapHistory::InsertCharToHistoryBuf(TDes& aHistoryBuf, const TChar aChar)
+    {
+    TInt pos = aHistoryBuf.Locate(aChar);
+    if(pos != 0)
+        {
+        if(pos == KErrNotFound)
+            {
+            aHistoryBuf.SetLength(aHistoryBuf.Length() - 1);
+            }
+        else
+            {
+            aHistoryBuf.Delete(pos, 1);
+            }
+        
+        TBuf<1> charBuf;
+        charBuf.Append(aChar);
+        aHistoryBuf.Insert(0, charBuf);
+        }
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::LengthOfRecentChar()
+// Get the length of the recent charactors.
+// -----------------------------------------------------------------------------
+//
+TInt CAknCharMap::LengthOfRecentChar()
+    {
+    TInt len(0);
+    if ( iChars != NULL )
+        {
+        for ( TInt index=0; index < iMaxColumns; index++ )
+            {
+            if ( (*iChars)[index] != KHistoryEmptyChar )
+                {
+                len++;
+                }
+            else
+                {
+                break;
+                }
+            }
+        }
+    return len;
+    }
+
+
+EXPORT_C CAknCharMap::CAknCharMap() : iMaxColumns(-1)
+    {
+    // Must be created here to get the member variables available
+    TRAPD(err, iExtension = new (ELeave) CAknCharMapExtension);
+    iExtension->iCharMap = this;
+
+    if(err)
+        return;
+
+    iExtension->iFlags = 0x00;
+
+    // if feature language is Japanese
+    CAknEnv* env = CAknEnv::Static();
+    if (env)
+        {
+        if (env->IsFeatureLanguage(KFeatureIdJapanese))
+            {
+            iExtension->iJapaneseSctUi = ETrue;
+            iExtension->iHasCategoryButtonUi = ETrue;
+            }
+        }
+    iExtension->iFocusHandler = iExtension;
+    iExtension->SetCharMapControl(this);
+	
+    if ( iExtension->iSingleClickEnabled )
+        {
+        iExtension->iHighlightVisible = EFalse;
+        }
+    
+    DoLayout();
+    
+    AKNTASHOOK_ADD( this, "CAknCharMap" );
+    }
+
+EXPORT_C CAknCharMap::~CAknCharMap()
+    {
+    AKNTASHOOK_REMOVE();
+
+    delete iCharsBufferFull;
+    delete iCharsBufferHalf;
+    delete iCharsBufferLower;
+    delete iCharsBufferUpper;
+    delete iCharsBufferNumeric;
+    delete iPictographsBuffer;
+    delete iPictographsBuffer2;
+    
+    delete iSBFrame;
+    delete iPictoInterface;
+
+
+    delete iTitleDefault;
+    delete iTitleFull;
+    delete iTitleHalf;
+    delete iTitlePicto;
+    delete iTitlePicto2;
+
+    // menu sct replaces the iChars with on HBufC
+    if (iExtension->iFlags & EAknCharMapCharsAllocated) // iChars  contains HBufC
+        {                                               // so delete it
+        delete iChars;
+        }
+
+
+    delete iExtension;
+    delete iCharMapHistory;
+
+    iSpecialCharCases.Close();
+    iSpecialCharPages.Close();
+    iPictographCases.Close();
+    iPictographPages.Close();
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    feedback->RemoveFeedbackForControl( this );
+   }
+
+void CAknCharMap::DoLayout()
+    {
+    TAknTextLineLayout specialCharItemLayout;
+    if (AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct)
+        {
+        if ( Layout_Meta_Data::IsLandscapeOrientation() )
+            {
+            specialCharItemLayout =
+                AknLayoutScalable_Avkon::cell_graphic2_pane_t1(1);
+            }
+        else if (IsJapaneseSctUi())
+            {
+            specialCharItemLayout =
+                AknLayoutScalable_Avkon::cell_graphic2_pane_t1(2);
+            }
+        else
+            {
+            specialCharItemLayout =
+                AknLayoutScalable_Avkon::cell_graphic2_pane_t1(0);
+            }
+        }
+    else
+        {
+        specialCharItemLayout =
+            AknLayoutScalable_Avkon::cell_graphic_popup_pane_t2();
+        }
+    iFont = AknLayoutUtils::FontFromId ( specialCharItemLayout.FontId() );
+    if (iPictoInterface)
+        {
+        __ASSERT_ALWAYS(iFont, Panic(EAknPanicNullPointer));
+        iCurrentPictographHeight = EHeight16;
+        iPictoInterface->Interface()->SelectPictographHeightForFont(*iFont,iCurrentPictographHeight);
+        }
+    iIsMirrored = AknLayoutUtils::LayoutMirrored();
+    iDrawnBefore = EFalse;
+    CountMaxColumnsAndCellSizes();
+    SizeChanged();
+
+    // load Emotion icon resource, but not load images
+    TSize iconSize(iGridItemWidth,iGridItemHeight);
+    iconSize.iWidth = iconSize.iWidth * 2 / 3;
+    iconSize.iHeight = iconSize.iHeight * 2 / 3;
+    Extension()->SetEmotionSize(iconSize);
+    }
+
+
+EXPORT_C void CAknCharMap::ConstructFromResourceL(TResourceReader& aReader)
+    {
+    CEikDialog* dlg;
+    MopGetObject(dlg);
+    CEikDialogExtension* dlgExtension = dlg ? dlg->Extension():NULL;
+    if (dlgExtension)
+        {
+        if (CAknEnv::Static()->TransparencyEnabled())
+            {
+            // CAknCharMapDialog doesn't have extension
+            dlgExtension->iPublicFlags.Set(
+                CEikDialogExtension::EClipChildControlRect);
+            }
+
+        if (AknLayoutUtils::PenEnabled()) // for full screen touch ui.
+            {
+            dlgExtension->iPublicFlags.Set(
+                CEikDialogExtension::EUseVirtualInput);
+            }
+        else
+            {
+            dlgExtension->iPublicFlags.Clear(
+                CEikDialogExtension::EUseVirtualInput);
+            }
+        }
+
+    // Special character set.
+    ReadCharSetFromResourceL(aReader);
+
+    // Pictograph character set.
+    TBool offscreen = EFalse;
+    if ( iExtension->iPictographsBuffer )
+        {
+        CreatePictoCharL();
+        offscreen = ETrue;
+        }
+
+    SetCharacterCaseL(EAknSCTLowerCase);
+
+    // Recent character set.
+    if (!iCharMapHistory)
+        {
+        iCharMapHistory = CAknCharMapHistory::NewL();
+        AppendRecentCharL();
+        }
+
+    // Touch support.
+    if (AknLayoutUtils::PenEnabled())
+        {
+        if ( DrawableWindow() )
+            {
+            EnableDragEvents();
+            SetGloballyCapturing(ETrue);
+            SetPointerCapture(ETrue);
+            }
+        }
+
+    // Alternate components.
+    if (AknLayoutUtils::PenEnabled())
+        {
+        if (iExtension->iHasCategoryButtonUi)
+            {
+            EnableCategoryInputFieldL();
+            EnableCategoryButtonsL();
+            }
+        EnableNavigationButtonsL();
+        }
+    else
+        {
+        if (iExtension->iHasCategoryButtonUi)
+            {
+            EnableCategoryButtonsL();
+            }
+        }
+
+    // Offscreen background.
+    if (offscreen)
+        {
+        CreateOffscreenBackgroundL();
+        }
+
+    iExtension->iBgContext = 
+    CAknsFrameBackgroundControlContext::NewL(KAknsIIDQsnFrPopup, TRect(0,0,1,1), TRect(0,0,1,1), EFalse);
+    }
+
+
+EXPORT_C TInt CAknCharMap::HeightInRows()
+    {
+    return (iShowCasesRef->Count()>1 ? iMaxColumns+1 : iRows);
+    }
+
+EXPORT_C void CAknCharMap::SetEmotionModeL(TAknCharMapEmotionMode aEmotionMode)
+    {
+    TBool isCurrentEnable = iExtension->iIsEnableEmotion;
+    
+    switch(aEmotionMode)
+        {
+        case EAknCharMapEmotionUse:
+            iExtension->iIsShowingEmotion = EFalse;
+            iExtension->iIsEnableEmotion = ETrue;
+            break;
+
+        case EAknCharMapEmotionFirst:
+            iExtension->iIsShowingEmotion = ETrue;
+            iExtension->iIsEnableEmotion = ETrue;
+            break;
+
+        default:
+            iExtension->iIsShowingEmotion = EFalse;
+            iExtension->iIsEnableEmotion = EFalse;
+            break;
+        }
+
+    if(isCurrentEnable!=iExtension->iIsEnableEmotion && iExtension->NeedEmotionSwitchIcon())
+        {
+        DisableRecentCharsRow();
+        AppendRecentCharL();
+        SetCharacterCaseL(iSpecialCharCase);
+        }
+    }
+
+EXPORT_C void CAknCharMap::SetCharacterCaseL(TInt aCharCase)
+    {
+    __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidResourceData));
+    
+    // PictoMode
+    if(aCharCase & EAknCharMapPictoNoUse)
+        {
+        SetPictoMode(EAknCharMapPictoNoUse);
+        }
+    else if(aCharCase & EAknCharMapPictoFirst)
+        {
+        SetPictoMode(EAknCharMapPictoFirst);
+        }
+
+    // EmotionMode
+    if(aCharCase & EAknCharMapEmotionNoUse)
+        {
+        SetEmotionModeL(EAknCharMapEmotionNoUse);
+        }
+    else if(aCharCase & EAknCharMapEmotionUse)
+        {
+        SetEmotionModeL(EAknCharMapEmotionUse);
+        }
+    else if(aCharCase & EAknCharMapEmotionFirst)
+        {
+        SetEmotionModeL(EAknCharMapEmotionFirst);
+        }
+    
+    // do set character case
+    iSpecialCharCase = aCharCase & KCharMapCaseMask;
+
+    if (iChaMapTableCase != EAknCharMapTableSpecialChar)
+        {
+        if (iCaseIndex == 1)
+            {
+            iChars = iPictographsBuffer2;
+            }
+        else
+            {
+            iChars = iPictographsBuffer;
+            }
+        iShowCasesRef = &iPictographCases;
+        iShowPagesRef = &iPictographPages;
+        }
+    else
+        {
+        iShowCasesRef = &iSpecialCharCases;
+        iShowPagesRef = &iSpecialCharPages;
+        
+        // default
+        iSpecialCharCase = EAknSCTLowerCase;
+        iChars = iCharsBufferLower;
+        
+        if(iExtension->iCharsSmiley && iExtension->IsShowingEmotion())
+            {
+            iChars = iExtension->iCharsSmiley;
+            }
+        else if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase)
+            {
+            iChars = iCharsBufferUpper;
+            }
+        else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric)
+            {
+            iChars = iCharsBufferNumeric;
+            }
+        else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase)
+            {
+            iChars = iCharsBufferFull;
+            }
+        else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase)
+            {
+            iChars = iCharsBufferHalf;
+            }
+        else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty)
+            {
+            iChars = iExtension->iCharsQwerty;
+            }
+        }
+
+    // calculate page count for all pages
+    iSpecialCharPages.Reset(); // reset the current page count for different charsets
+    TRAP_IGNORE(
+        {
+        iSpecialCharPages.AppendL( PageCountFromChars(*iChars) );
+        for (TInt i(1); i < iSpecialCharCases.Count(); ++i)
+            {
+            HBufC* chars = CharsFromCase(iSpecialCharCases[i]);
+            if (chars)
+                {
+                iSpecialCharPages.AppendL( PageCountFromChars(*chars) );
+                }
+            }
+        } );
+
+    __ASSERT_ALWAYS( iChars && iChars->Length()>0, Panic(EAknPanicInvalidResourceData));
+    
+    iRows = ((iChars->Length() - 1) / iMaxColumns ) + 1 ;
+    iFirstVisibleRow = 0;
+    iAnimated = EFalse;
+    iCursorPos = TPoint(0, 0);
+
+    if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+         (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar && !Extension()->iMenuSct) )
+        {
+        iCursorPos = TPoint(0, 1);
+        }
+
+    iExtension->iCurrentCategory = Category();
+    if (iExtension->iRadioButton)
+        {
+        iExtension->iRadioButton->SetCurrentCategory(iExtension->iCurrentCategory);
+        }
+
+    // Create and set the scb visible even though there is nothing to scroll
+    delete iSBFrame;
+    iSBFrame=NULL;
+
+    if ( !AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct )    // No scrollbars in use.
+        {
+        iSBFrame=new(ELeave) CEikScrollBarFrame(this, NULL, ETrue);
+        iSBFrame->CreateDoubleSpanScrollBarsL(EFalse, EFalse, ETrue, EFalse); // non-window owning scrollbar
+        iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto);
+        iSBFrame->VerticalScrollBar()->SetMopParent(iExtension);
+        UpdateScrollIndicatorL();
+        }
+    
+    iExtension->LoadEmotionTumbnails(*iChars);
+
+    CAknSctPageNavi* pageNavi = Extension()->iPageNavi;
+    if(pageNavi)
+        {
+        pageNavi->MakeVisible(PageCount()>1);
+        }
+    
+    HandleFocusStatusChanged();
+    
+    }
+
+EXPORT_C void CAknCharMap::SetBuffer(TDes& aSpecialChars)
+    {
+    iFetcherCharsBuffer = &aSpecialChars;
+    }
+
+void CAknCharMap::ReadCharSetFromResourceL(TResourceReader& aReader)
+    {
+    __ASSERT_DEBUG(iExtension, Panic(EAknPanicInvalidResourceData));
+
+    iChars = NULL;
+    
+    delete iCharsBufferHalf;
+    iCharsBufferHalf = NULL;
+    delete iCharsBufferFull;
+    iCharsBufferFull = NULL;
+    delete iCharsBufferLower;
+    iCharsBufferLower = NULL;
+    delete iCharsBufferUpper;
+    iCharsBufferUpper = NULL;
+    delete iCharsBufferNumeric;
+    iCharsBufferNumeric = NULL;
+    delete iExtension->iCharsQwerty;
+    iExtension->iCharsQwerty = NULL;
+    delete iExtension->iCharsSmiley;
+    iExtension->iCharsSmiley = NULL;
+
+    TInt component_count=aReader.ReadInt16();
+    for (TInt ii=0;ii<component_count;ii++)
+        {
+        TInt component_id=aReader.ReadInt16();
+        switch(component_id)
+            {
+            case EAknSCTLowerCase:
+                iCharsBufferLower = aReader.ReadHBufCL();
+                break;
+            case EAknSCTUpperCase:
+                iCharsBufferUpper = aReader.ReadHBufCL();
+                break;
+            case EAknSCTNumeric:
+                iCharsBufferNumeric = aReader.ReadHBufCL();
+                break;
+            case EAknSCTFullCase:
+                iCharsBufferFull = AppendTextL(iCharsBufferFull, aReader.ReadHBufCL());
+                break;
+            case EAknSCTHalfCase:
+                iCharsBufferHalf = AppendTextL(iCharsBufferHalf, aReader.ReadHBufCL());
+                break;
+            case EAknSCTQwerty:
+                 iExtension->iCharsQwerty = aReader.ReadHBufCL();
+                 break;
+            default:
+                break;
+            }
+        }
+    
+    iExtension->iCharsSmiley = iExtension->ReadEmotionHBufCL();
+
+    // EFalse is set to iSetRecentSct variable when setting special
+    // characters from resouce.
+    iSetRecentSct = EFalse;
+    }
+
+
+void CAknCharMap::ReadAndAddCharSetFromResourceL(TResourceReader& aReader)
+    {
+    ReadCharSetFromResourceL( aReader );
+
+    // Add recent used characters
+    if ( iCharMapHistory )
+        {
+        delete iCharMapHistory;
+        iCharMapHistory = NULL;
+        }
+    iCharMapHistory = CAknCharMapHistory::NewL();
+    AppendRecentCharL();
+    }
+
+EXPORT_C TSize CAknCharMap::MinimumSize()
+    {
+    TRect rect;
+    if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct)
+        {
+        TRect mainPaneRect;
+        if(!AknLayoutUtils::LayoutMetricsRect(
+            AknLayoutUtils::EPopupParent, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation();
+        TInt maxVarietyOffset = 0;
+        TInt varietyOffset = maxVariety + 1;
+
+        if(Layout_Meta_Data::IsLandscapeOrientation())
+            {
+            varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections;
+            }
+
+        if(location == AknLayoutUtils::EAknCbaLocationRight)
+            {
+            maxVarietyOffset = varietyOffset;
+            }
+        else if(location == AknLayoutUtils::EAknCbaLocationLeft)
+            {
+            maxVarietyOffset = varietyOffset + varietyOffset;
+            }
+
+        TInt varietyNumber = varietyOffset - iRows;
+
+        if(varietyNumber < 0)
+            {
+            varietyNumber = 0;
+            }
+        else if(iRows<=0)
+            {
+            varietyNumber -= 1;
+            }
+
+        varietyNumber += maxVarietyOffset;
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect( mainPaneRect,
+            AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber));
+
+        TAknLayoutRect gridWithScrollLayRect;
+        gridWithScrollLayRect.LayoutRect(popupGridLayRect.Rect(),
+            AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+        rect = gridWithScrollLayRect.Rect();
+        }
+    else
+        {
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+        rect = popupGridLayRect.Rect();
+        }
+
+    return rect.Size();
+    }
+
+
+// This method is needed to set correct initial value to scroll indicator.
+EXPORT_C void CAknCharMap::ActivateL()
+    {
+    CCoeControl::ActivateL();
+    if (iRows > iExtension->iMaxVisibleRows)
+        {
+        UpdateScrollIndicatorL();
+        }
+    }
+
+
+EXPORT_C TKeyResponse CAknCharMap::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aModifiers)
+    {
+    // Other key events.
+    if (iExtension->iFocusHandler->FocusedControl() != this)
+        {
+        return iExtension->iFocusHandler->FocusedControl()->OfferKeyEventL(aKeyEvent, aModifiers);
+        }
+
+    // Grid key events.
+    if( ((*iChars)[0] == KHistoryEmptyChar) &&
+        ((*iChars)[iChars->Length()-1] == KHistoryEmptyChar))
+        {
+        return EKeyWasConsumed;
+        }
+    
+    TUint code=aKeyEvent.iCode;
+	
+    // First key event enables the highlight
+    if ( iExtension->iSingleClickEnabled && !iExtension->iHighlightVisible )
+        {
+        if ( code == EKeyUpArrow || code == EKeyDownArrow || 
+             code == EKeyLeftArrow || code == EKeyRightArrow || 
+             code == EKeyEnter )
+            {
+            iExtension->iHighlightVisible = ETrue;
+            iCursorPos = TPoint( 0, 0 );
+            DrawCursor();
+            HandleFocusStatusChanged();
+            return EKeyWasConsumed;
+            }
+        }
+    
+    switch (code)
+        {
+        case EKeyLeftArrow:
+        case '4':
+            {
+            if (iExtension->iRadioButton && (iCursorPos.iX == 0)) // Radio button.
+                {
+                if (iExtension->iRadioButton->EnterControl(iCursorPos.iX,iCursorPos.iY))
+                    {
+                    LeaveControl();
+                    break;
+                    }
+                }
+
+            if (AknLayoutUtils::PenEnabled())
+                {
+                if (!iIsMirrored)
+                    {
+                    if ((iCursorPos.iX == 0) && (iCursorPos.iY == ColMin(0)))
+                        {
+                        if (!Layout_Meta_Data::IsLandscapeOrientation())
+                            {
+                            // Last table button.
+                            if (iExtension->iTableNavi &&
+                                iExtension->iTableNavi->EnterControl(TableCount() - 1,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        else
+                            {
+                            // Right page button.
+                            if (iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(1,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        }
+                    }
+                else
+                    {
+                    if (((iCursorPos.iY == ColMax(0)) && (iCursorPos.iX == RowMax(ColMax(0)))))
+                        {
+                        if (!Layout_Meta_Data::IsLandscapeOrientation())
+                            {
+                            // Left page button.
+                            if (iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(0,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        else
+                            {
+                            // First table button.
+                            if (iExtension->iTableNavi &&
+                                iExtension->iTableNavi->EnterControl(0,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        }
+                    }
+                }
+            MoveFocus(-1,0);
+            break;
+            }
+        case EKeyRightArrow:
+        case '6':
+            {
+            if (iExtension->iRadioButton &&
+                (iCursorPos.iX == RowMax(iCursorPos.iY)) &&
+                    (iCursorPos.iY <= (iExtension->iRadioButton->Count() - 2)))
+                {
+                // Radio button.
+                if (iExtension->iRadioButton->EnterControl(iCursorPos.iX,iCursorPos.iY+1))
+                    {
+                    LeaveControl();
+                    break;
+                    }
+                }
+            if (AknLayoutUtils::PenEnabled())
+                {
+                if (!iIsMirrored)
+                    {
+                    if ((iCursorPos.iY == ColMax(0)) &&
+                        (iCursorPos.iX == RowMax(ColMax(0))))
+                        {
+                        if (!Layout_Meta_Data::IsLandscapeOrientation())
+                            {
+                            // Left page button.
+                            if (iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(0,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        else
+                            {
+                            // First table button.
+                            if (iExtension->iTableNavi &&
+                                iExtension->iTableNavi->EnterControl(0,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        }
+                    }
+                else
+                    {
+                    if ((iCursorPos.iY == ColMin(0)) &&
+                        (iCursorPos.iX == 0))
+                        {
+                        if (!Layout_Meta_Data::IsLandscapeOrientation())
+                            {
+                            // First table button.
+                            if (iExtension->iTableNavi &&
+                                iExtension->iTableNavi->EnterControl(0,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+
+                            }
+                        else
+                            {
+                            // Left page button.
+                            if (iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(1,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        }
+                    }
+                }
+            MoveFocus(1,0);
+            break;
+            }
+        case EKeyUpArrow:
+        case '2':
+            {
+            if (AknLayoutUtils::PenEnabled())
+                {
+                if (iCursorPos.iY == ColMin(iCursorPos.iX))
+                    {
+                    if (!iExtension->iRadioButton && iCursorPos.iX < TableCount())
+                        {
+                        // Table button up.
+                        if ( iExtension->iTableNavi &&
+                            iExtension->iTableNavi->EnterControl(iCursorPos.iX,0))
+                            {
+                            LeaveControl();
+                            break;
+                            }
+                        }
+                    else
+                        {
+                        if (iCursorPos.iX == MaxCols() - 1)
+                            {
+                            // Right page button.
+                            if ( iExtension->iPageNavi &&
+                                iExtension->iPageNavi->EnterControl(1,0))
+                                {
+                                LeaveControl();
+                                break;
+                                }
+                            }
+                        if (Layout_Meta_Data::IsLandscapeOrientation())
+                            {
+                            if ((!iExtension->iRadioButton &&
+                                 (iCursorPos.iX == TableCount())) ||
+                               ((iExtension->iRadioButton) &&
+                                 (iCursorPos.iX == MaxCols()-2)))
+                                {
+                                // Left page button.
+                                if ( iExtension->iPageNavi &&
+                                    iExtension->iPageNavi->EnterControl(0,0))
+                                    {
+                                    LeaveControl();
+                                    break;
+                                    }
+                                }
+                            }
+                        // Grid bottom row.
+                        if (ColMax(0) > ColMax(iCursorPos.iX))
+                            {
+                            EnterControl(RowMax(ColMax(0)), ColMax(0));
+                            break;
+                            }
+                        EnterControl(iCursorPos.iX, ColMax( iCursorPos.iX));
+                        break;
+                        }
+                    }
+                }
+            MoveFocus(0,-1);
+            break;
+            }
+        case EKeyDownArrow:
+        case '8':
+            {
+            if (AknLayoutUtils::PenEnabled())
+                {
+                if (iCursorPos.iY == ColMax(iCursorPos.iX))
+                    {
+                    if (iCursorPos.iX > RowMax(ColMax(0)))
+                        {
+                        // Grid last item.
+                        EnterControl(RowMax(ColMax(0)), ColMax(0));
+                        break;
+                        }
+                    if ((iCursorPos.iX == MaxCols() - 1) ||
+                        (!Layout_Meta_Data::IsLandscapeOrientation() &&
+                            iExtension->iRadioButton &&
+                                (iCursorPos.iX == MaxCols() - 2)))
+                        {
+                        // Right page button.
+                        if (iExtension->iPageNavi &&
+                            iExtension->iPageNavi->EnterControl(1,0))
+                            {
+                            LeaveControl();
+                            break;
+                            }
+                        }
+                    if ((Layout_Meta_Data::IsLandscapeOrientation() &&
+                            !iExtension->iRadioButton &&
+                                (iCursorPos.iX == TableCount())) ||
+                        (!Layout_Meta_Data::IsLandscapeOrientation() &&
+                            (iCursorPos.iX == 0)) ||
+                        (Layout_Meta_Data::IsLandscapeOrientation() &&
+                            iExtension->iRadioButton &&
+                                (iCursorPos.iX == MaxCols() - 2)))
+                        {
+                        // Left page button.
+                        if (iExtension->iPageNavi &&
+                            iExtension->iPageNavi->EnterControl(0,0))
+                            {
+                            LeaveControl();
+                            break;
+                            }
+                        }
+                    if (!iExtension->iRadioButton &&
+                            iCursorPos.iX < TableCount())
+                        {
+                         // Table button down.
+                        if (iExtension->iTableNavi &&
+                            iExtension->iTableNavi->EnterControl(iCursorPos.iX,0))
+                            {
+                            LeaveControl();
+                            break;
+                            }
+                        }
+                    // Grid top row.
+                    EnterControl(iCursorPos.iX, ColMin(iCursorPos.iX));
+                    break;
+                    }
+                }
+            MoveFocus(0,1);
+            break;
+            }
+        case '5':
+        case EKeySpace:
+            {
+            AppendFocusSctToDestinationBufferL();
+            }
+            break;
+        case EKeyEnter:
+        case EKeyOK:
+            if(!Extension()->iKeyOkEvent)
+                {
+                if(AppendFocusSctToDestinationBufferL())
+                    {
+                    Extension()->iKeyOkEvent = ETrue;
+                    }
+                else
+                    {
+                    return EKeyWasNotConsumed;
+                    }
+                }
+            break;
+        default:
+            return EKeyWasNotConsumed;
+
+        }
+    return EKeyWasConsumed;
+    }
+
+EXPORT_C TCoeInputCapabilities CAknCharMap::InputCapabilities() const
+    {
+    return TCoeInputCapabilities(TCoeInputCapabilities::EAllText);
+    }
+
+/**
+* Control position of this control is registered for skin library when necessary
+* in CEikDialogPage::SetDataPosition, so we do not do that in this method.
+*/
+EXPORT_C void CAknCharMap::SizeChanged()
+    {
+    
+    if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct)
+        {
+        TRect mainPaneRect;
+        if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EPopupParent, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation();
+        TInt maxVarietyOffset = 0;
+        TInt varietyOffset = maxVariety + 1;
+        if(Layout_Meta_Data::IsLandscapeOrientation())
+            {
+            varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections;
+            }
+        if(location == AknLayoutUtils::EAknCbaLocationRight)
+            {
+            maxVarietyOffset = varietyOffset;
+            }
+        else if(location == AknLayoutUtils::EAknCbaLocationLeft)
+            {
+            maxVarietyOffset = varietyOffset + varietyOffset;
+            }
+
+        TInt varietyNumber = varietyOffset - iRows;
+        if(varietyNumber < 0)
+            {
+            varietyNumber = 0;
+            }
+        else if(iRows<=0)
+            {
+            varietyNumber -= 1;
+            }
+        varietyNumber += maxVarietyOffset;
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(mainPaneRect, AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber));
+
+        TRect relativePopup(TPoint(0,0), popupGridLayRect.Rect().Size());
+
+        TAknLayoutRect gridWithScrollLayRect;
+        gridWithScrollLayRect.LayoutRect(relativePopup, AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+        TAknLayoutRect gridLayRect;
+        if (iExtension->iHasCategoryButtonUi)
+            {
+            gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), AknLayoutScalable_Avkon::grid_graphic_popup_pane(2));
+            }
+        else
+            {
+            gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), AknLayoutScalable_Avkon::grid_graphic_popup_pane(0));
+            }
+
+        // Grid.
+        TRect contentRect = Extension()->iMenuSct ? Rect() : gridLayRect.Rect();
+        if ( Extension()->iMenuSct )
+            {
+            contentRect.iBr.iY -= (contentRect.Height() - Rect().Height());
+            }
+        iOffset.iY = contentRect.iTl.iY + 1;
+        iGridTopLeft.iY = contentRect.iTl.iY;
+        if ( iIsMirrored )
+            {
+            iOffset.iX = contentRect.iBr.iX - iGridItemWidth + 1;
+            iGridTopLeft.iX = contentRect.iBr.iX - iGridItemWidth;
+            }
+        else
+            {
+            iOffset.iX = contentRect.iTl.iX + 1;
+            iGridTopLeft.iX = contentRect.iTl.iX;
+            }
+
+        // Category buttons.
+        if (iExtension && iExtension->iHasCategoryButtonUi)
+            {
+            if (iExtension->iRadioButton)
+                {
+                TAknLayoutRect categoryButtonLayRect;
+                categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(),AknLayoutScalable_Avkon::grid_sct_catagory_button_pane());
+
+                TAknLayoutRect oneButtonLayRect;
+                oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(),AknLayoutScalable_Avkon::cell_sct_catagory_button_pane());
+
+                TSize size(oneButtonLayRect.Rect().Width(), oneButtonLayRect.Rect().Height()*iExtension->iRadioButton->Count());
+                TRect rectRadio(categoryButtonLayRect.Rect().iTl, size);
+                iExtension->iRadioButton->SetRect(rectRadio);
+                }
+            }
+
+
+        // Background context.
+        if(iExtension && iExtension->iBgContext)
+            {
+            TInt varietyNumber = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+            TAknLayoutRect innerRect;
+            innerRect.LayoutRect(relativePopup, AknLayoutScalable_Avkon::bg_popup_window_pane_g1(varietyNumber));
+            iExtension->iBgContext->SetFrameRects( relativePopup, innerRect.Rect() );
+            }
+
+        TRAP_IGNORE( UpdateScrollIndicatorL() );
+        }
+    else
+        {
+        
+        TInt variety;
+        if (!IsJapaneseSctUi())
+            {
+            variety = Layout_Meta_Data::IsLandscapeOrientation() ? 3 : 1;
+            if(TableCount() > 1) variety--;
+            }
+        else
+            {
+            variety = Layout_Meta_Data::IsLandscapeOrientation() ? 5 : 4;
+            }
+        
+        // Popup.
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+        TRect popupGridRect = popupGridLayRect.Rect();
+
+        // Grid.
+        TAknLayoutRect gridLayRect;
+        gridLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_pane(variety));
+        TRect gridRect = gridLayRect.Rect();
+
+        iOffset.iY = gridRect.iTl.iY + 1;
+        iGridTopLeft.iY = gridRect.iTl.iY;
+        if ( iIsMirrored )
+            {
+            iOffset.iX = gridRect.iBr.iX - iGridItemWidth + 1;
+            iGridTopLeft.iX = gridRect.iBr.iX - iGridItemWidth;
+            }
+        else
+            {
+            iOffset.iX = gridRect.iTl.iX + 1;
+            iGridTopLeft.iX = gridRect.iTl.iX;
+            }
+
+        // Category
+        if (iExtension->iHasCategoryButtonUi && iExtension->iRadioButton) // Radio buttons.
+            {
+            TAknLayoutRect oneButtonLayRect;
+            TAknLayoutRect categoryButtonLayRect;
+            TInt oneButtonLayVariety, categoryButtonLayVariety;
+            
+            if (Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                oneButtonLayVariety = 5;
+                categoryButtonLayVariety = 1;
+                }
+            else
+                {
+                oneButtonLayVariety = 4;
+                categoryButtonLayVariety = 0;
+                }
+            
+            oneButtonLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_control_pane(oneButtonLayVariety));
+            categoryButtonLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_catg_pane(categoryButtonLayVariety));
+
+            TSize size(oneButtonLayRect.Rect().Width(), 
+                       oneButtonLayRect.Rect().Height() * iExtension->iRadioButton->Count());
+            TRect rectRadio(categoryButtonLayRect.Rect().iTl, size);
+            iExtension->iRadioButton->SetRect(rectRadio);
+            }
+
+        // Table navigation.
+        if (iExtension->iTableNavi)
+            {
+            TAknLayoutRect tableNaviLayRect;
+            tableNaviLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_control_pane(variety));
+            iExtension->iTableNavi->SetRect(tableNaviLayRect.Rect());
+            }
+
+        // Page navigation.
+        if (iExtension->iPageNavi)
+            {
+            if (PageCount() > 1)
+                {
+                iExtension->iPageNavi->MakeVisible(ETrue);
+                
+                TAknLayoutRect pageNaviLayRect;
+                pageNaviLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::graphic2_pages_pane(variety));
+                iExtension->iPageNavi->SetRect(pageNaviLayRect.Rect());
+                }
+            else
+                {
+                iExtension->iPageNavi->MakeVisible(EFalse);
+                }
+            }
+
+        // Background context.
+        if(iExtension->iBgContext)
+            {
+            TAknLayoutRect innerRect;
+            innerRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::bg_popup_window_pane_cp21(variety));
+
+            TRect relativePopupRect(TPoint(0,0), popupGridRect.Size());
+            iExtension->iBgContext->SetFrameRects(relativePopupRect,innerRect.Rect());
+            }
+
+        }
+    }
+
+EXPORT_C void CAknCharMap::HandleResourceChange(TInt aType)
+    {
+    TRAP_IGNORE(DoHandleResourceChangeL(aType));
+    CCoeControl::HandleResourceChange(aType);
+    }
+
+void CAknCharMap::DoHandleResourceChangeL(TInt aType)
+    {
+    if (aType == KEikDynamicLayoutVariantSwitch)
+        {
+        TInt cursorIndexBeforeSwitch = (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns + iCursorPos.iX;
+        TInt recentLengthBeforeSwitch = iMaxColumns;
+        TBool recentWasSetBeforeSwitch = iSetRecentSct;
+
+        // Disabled because the buffer content may change due to diffent layout.
+        if (recentWasSetBeforeSwitch) DisableRecentCharsRow();
+
+        // Calculate the new magnitudes (iMaxColumns, etc.).
+        DoLayout();
+
+        // Append right amount of recent characters due to different layout.
+        if (recentWasSetBeforeSwitch) AppendRecentCharL();
+
+        // Sets the character case because the buffer content may have changed.
+        SetCharacterCaseL(iSpecialCharCase);
+
+        // status after layout switch.
+        TInt recentLengthAfterSwitch = iMaxColumns; // recentLength has changed after switch
+        TInt cursorIndexAfterSwitch;
+        if(cursorIndexBeforeSwitch < recentLengthBeforeSwitch)
+            {
+            cursorIndexAfterSwitch = cursorIndexBeforeSwitch;
+            }
+        else
+            {
+            cursorIndexAfterSwitch = cursorIndexBeforeSwitch - recentLengthBeforeSwitch + recentLengthAfterSwitch;
+            }
+
+        // the new first row is the top row on the page where the new focus is.
+        TInt pageVolume = iMaxColumns * iExtension->iMaxVisibleRows;
+        iFirstVisibleRow = (cursorIndexAfterSwitch / pageVolume * pageVolume) / iMaxColumns;
+
+        // the cursor positions are relative to current page
+        TInt cursorIndexAfterSwitchInPage = cursorIndexAfterSwitch - (iMaxColumns * iFirstVisibleRow);
+        iCursorPos.iX = cursorIndexAfterSwitchInPage % iMaxColumns;
+        iCursorPos.iY = cursorIndexAfterSwitchInPage / iMaxColumns;
+        
+        iOldCursorPos = iCursorPos;
+
+        // for full screen touch UI.
+        CEikDialog* dlg;
+        MopGetObject(dlg);
+        CEikDialogExtension* dlgExtension = dlg ? dlg->Extension() : NULL;
+        if (dlgExtension)
+            {
+            if (AknLayoutUtils::PenEnabled())
+                {
+                dlgExtension->iPublicFlags.Set(CEikDialogExtension::EUseVirtualInput);
+                }
+            else
+                {
+                dlgExtension->iPublicFlags.Clear(CEikDialogExtension::EUseVirtualInput);
+                }
+            }
+
+        // Sets alternate UI controls.
+        if (iExtension->iHasCategoryButtonUi)
+            {
+            if (AknLayoutUtils::PenEnabled())
+                {
+                EnableCategoryInputFieldL();
+                EnableNavigationButtonsL();
+                }
+            else
+                {
+                DisableCategoryInputFieldL();
+                DisableNavigationButtonsL();
+                }
+            EnableCategoryButtonsL();
+            }
+        else
+            {
+            DisableCategoryInputFieldL();
+            DisableCategoryButtonsL();
+            if (AknLayoutUtils::PenEnabled())
+                {
+                EnableNavigationButtonsL();
+                }
+            else
+                {
+                DisableNavigationButtonsL();
+                }
+            }
+
+        // and finally updates the page counts (from setcasetable)
+        iSpecialCharPages.Reset(); // reset the current page count for different charsets
+        iSpecialCharPages.AppendL( PageCountFromChars(*iChars) );
+        for (TInt i(1); i < iSpecialCharCases.Count(); ++i)
+            {
+            HBufC* chars = CharsFromCase(iSpecialCharCases[i]);
+            if (chars) iSpecialCharPages.AppendL( PageCountFromChars(*chars) );
+            }
+
+        if (iExtension->iPictographsBuffer && iPictoInterface)
+            {
+            __ASSERT_ALWAYS(iPictoInterface->Interface(), Panic(EAknPanicNullPointer));
+            iPictographPages.Reset();
+            iPictographCases.Reset();
+            iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer) );
+            iPictographCases.AppendL(EAknCharMapTablePicto);
+            if (iExtension->iPictographsBufferGrouping)
+                {
+                iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer2) );
+                iPictographCases.AppendL( EAknCharMapTablePicto2 );
+                }
+            }
+
+        UpdateScrollIndicatorL();
+        RefreshNaviPageL();
+
+        // create the background again as the background size has changed
+        // !resize an option but the cost only differs with the creation of the graphic objects!
+        CreateOffscreenBackgroundL();
+        iOffscreenBgDrawn = EFalse;
+        }
+
+    else if ( aType == KAknsMessageSkinChange )
+        {
+        iOffscreenBgDrawn = EFalse;
+        }
+    else if ( aType == KAknMessageFocusLost && iExtension->iHighlightVisible )
+        {
+        iExtension->iHighlightVisible = EFalse;
+        DrawCursor();
+        }
+    }
+
+void CAknCharMap::EnableNavigationButtonsL()
+    {
+    if ( iExtension )
+        {
+        if ( !iExtension->iTableNavi )
+            {
+            iExtension->iTableNavi = new(ELeave) CAknSctTableNavi(this, iExtension);
+            iExtension->iTableNavi->SetContainerWindowL(*this);
+            TResourceReader reader;
+            iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_TABLE_NAVI_CONTROL);
+            iExtension->iTableNavi->ConstructFromResourceL(reader);
+            iExtension->iTableNavi->SetNonFocusing();
+            iExtension->iTableNavi->SetMopParent(iExtension);
+            CleanupStack::PopAndDestroy(); // reader
+            }
+
+        iExtension->iTableNavi->MakeVisible(ETrue);
+
+        if ( !iExtension->iPageNavi )
+            {
+            iExtension->iPageNavi = new(ELeave) CAknSctPageNavi(this, iExtension);
+            iExtension->iPageNavi->SetContainerWindowL(*this);
+            TResourceReader reader;
+            iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_PAGE_NAVI_CONTROL);
+            iExtension->iPageNavi->ConstructFromResourceL(reader);
+            iExtension->iPageNavi->SetNonFocusing();
+            iExtension->iPageNavi->SetMopParent(iExtension);
+            CleanupStack::PopAndDestroy(); // reader
+            }
+
+        iExtension->iPageNavi->MakeVisible(ETrue);
+        }
+    }
+
+void CAknCharMap::DisableNavigationButtonsL()
+    {
+    if ( iExtension && iExtension->iTableNavi )
+        {
+        iExtension->iTableNavi->MakeVisible( EFalse );
+        }
+    if ( iExtension && iExtension->iPageNavi )
+        {
+        iExtension->iPageNavi->MakeVisible( EFalse );
+        }
+    }
+
+void CAknCharMap::EnableCategoryButtonsL()
+    {
+    if (!iExtension->iRadioButton)
+        {
+        iExtension->iRadioButton = new(ELeave) CAknSctRadioButton(this, iExtension);
+        iExtension->iRadioButton->SetContainerWindowL(*this);
+        TResourceReader reader;
+        iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_CATEGORY_BUTTON_CONTROL);
+        iExtension->iRadioButton->ConstructFromResourceL(reader);
+        iExtension->iRadioButton->SetNonFocusing();
+        iExtension->iRadioButton->SetMopParent(iExtension);
+        CleanupStack::PopAndDestroy(); // reader
+        }
+    iExtension->iRadioButton->MakeVisible(ETrue);
+    }
+
+void CAknCharMap::DisableCategoryButtonsL()
+    {
+    if (iExtension && iExtension->iRadioButton)
+        {
+        iExtension->iRadioButton->MakeVisible(EFalse);
+        }
+    }
+
+void CAknCharMap::EnableCategoryInputFieldL()
+    {
+    TAknLayoutRect popupGridLayRect;
+    popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+        AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+    // Enable title field.
+    if (!iExtension->iCategoryTitle)
+        {
+        iExtension->iCategoryTitle = new(ELeave) CEikLabel;
+        iExtension->iCategoryTitle->SetContainerWindowL(*this);
+        iExtension->iCategoryTitle->SetTextL(KNullDesC());
+        }
+    Extension()->iCategoryTitle->SetBrushStyle(CGraphicsContext::ENullBrush);
+    TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+    AknLayoutUtils::LayoutLabel(iExtension->iCategoryTitle, popupGridLayRect.Rect(),
+        AknLayoutScalable_Avkon::popup_grid_graphic2_window_t1(variety));
+    TAknLayoutText titleLayRect;
+    titleLayRect.LayoutText(popupGridLayRect.Rect(),
+        AknLayoutScalable_Avkon::popup_grid_graphic2_window_t1(variety).LayoutLine());
+    TRgb color = titleLayRect.Color();
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    if( skin )
+        {
+        (void)AknsUtils::GetCachedColor(skin, color,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
+        }
+    TRAP_IGNORE(AknLayoutUtils::OverrideControlColorL(*(iExtension->iCategoryTitle),
+        EColorLabelText, color));
+    if (iExtension->iPictographsBuffer && iPictoInterface)
+        {
+        iExtension->iCategoryTitle->EnablePictographsL(*iPictoInterface);
+        }
+    iExtension->iCategoryTitle->MakeVisible(ETrue);
+
+
+    // Enable entry field.
+    if (!iExtension->iCategoryEntry)
+        {
+        iExtension->iCategoryEntry = new(ELeave) CEikLabel;
+        iExtension->iCategoryEntry->SetContainerWindowL(*this);
+        iExtension->iCategoryEntry->SetTextL(KNullDesC());
+        }
+    Extension()->iCategoryEntry->SetBrushStyle(CGraphicsContext::ENullBrush);
+    AknLayoutUtils::LayoutLabel(iExtension->iCategoryEntry, popupGridLayRect.Rect(),
+        AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety));
+    TAknLayoutText entryLayRect;
+    entryLayRect.LayoutText(popupGridLayRect.Rect(),
+        AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety).LayoutLine());
+    color = entryLayRect.Color();
+    if( skin )
+        {
+        (void)AknsUtils::GetCachedColor(skin, color,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
+        }
+    TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL(*(iExtension->iCategoryEntry),
+        EColorLabelText, color));
+    if (iExtension->iPictographsBuffer && iPictoInterface)
+        {
+        iExtension->iCategoryEntry->EnablePictographsL(*iPictoInterface);
+        }
+    iExtension->iCategoryEntry->MakeVisible(ETrue);
+
+    UpdateInputFieldL();
+    }
+
+void CAknCharMap::DisableCategoryInputFieldL()
+    {
+    if (iExtension->iCategoryTitle)
+        {
+        iExtension->iCategoryTitle->MakeVisible(EFalse);
+        }
+
+    if (iExtension->iCategoryEntry)
+        {
+        iExtension->iCategoryEntry->MakeVisible(EFalse);
+        }
+    }
+
+
+void CAknCharMap::Draw(const TRect& /*aRect*/) const
+    {
+    TInt cursorPos = 0;
+
+    CWindowGc& gc=SystemGc();
+    gc.UseFont(iFont);
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+
+    TRect rect = Rect();
+
+    if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct)
+        {
+        TRect mainPaneRect;
+        if(!AknLayoutUtils::LayoutMetricsRect(
+            AknLayoutUtils::EPopupParent, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation();
+        TInt maxVarietyOffset = 0;
+        TInt varietyOffset = maxVariety + 1;
+
+        if(Layout_Meta_Data::IsLandscapeOrientation())
+            {
+            varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections;
+            }
+
+        if(location == AknLayoutUtils::EAknCbaLocationRight)
+            {
+            maxVarietyOffset = varietyOffset;
+            }
+        else if(location == AknLayoutUtils::EAknCbaLocationLeft)
+            {
+            maxVarietyOffset = varietyOffset + varietyOffset; // 2*
+            }
+
+        TInt varietyNumber = varietyOffset - iRows;
+
+        if(varietyNumber < 0)
+            {
+            varietyNumber = 0;
+            }
+        else if(iRows<=0)
+            {
+            varietyNumber -= 1;
+            }
+        varietyNumber += maxVarietyOffset;
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(mainPaneRect,
+            AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber));
+
+        // Background height.
+        TInt backgroundHeightOffset =
+            popupGridLayRect.Rect().Height() - rect.iBr.iY;
+
+        rect.iBr.iY += backgroundHeightOffset;
+        }
+    else
+        {
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+        // Background height.
+        TInt backgroundHeightOffset =
+            popupGridLayRect.Rect().Height() - rect.iBr.iY;
+
+        rect.iBr.iY += backgroundHeightOffset * 2;
+        }
+
+    // Grid (main).
+    if ( !Extension()->iMenuSct )
+        {
+        // 1) Draw the background
+
+        // Check if we got an offscreen bitmap allocated for skin background and
+        // there is bitmap background in the current skin.
+		if( CAknEnv::Static()->TransparencyEnabled() )
+			{
+			TRegionFix<10> clipReg;
+			clipReg.AddRect(rect);
+			if ( iFirstVisibleRow == 0 && iSetRecentSct )
+				{
+				TPoint pos = iGridTopLeft;
+				TInt endX = pos.iX + iGridItemWidth * iMaxColumns + 1;
+				TInt endY = pos.iY + iGridItemHeight;
+				// eliminate the overlap area between menu sct and the first menu item.
+				if ( Extension()->iMenuSct )
+					{
+					endY--;
+					}
+				clipReg.SubRect( TRect( pos, TPoint( endX, endY ) ) );
+				}
+			// Take scroll bar out of clip region
+			if (iSBFrame)
+				{
+				clipReg.SubRect(iSBFrame->GetScrollBarHandle(
+					CEikScrollBar::EVertical)->Rect());
+				}
+			gc.SetClippingRegion(clipReg);
+			}
+		AknsDrawUtils::Background( skin, cc, this, gc, rect,KAknsDrawParamNoClearUnderImage);
+		if( CAknEnv::Static()->TransparencyEnabled() )
+			{
+			gc.CancelClippingRegion();
+			}
+
+        gc.SetPenStyle(CGraphicsContext::ESolidPen);
+        gc.SetBrushStyle(CGraphicsContext::ENullBrush);
+        gc.SetPenSize(TSize(1,1));
+
+        // 2) Draw the grid
+        DrawGrid(gc);
+        }
+
+    // Grid (recent).
+    if (iFirstVisibleRow==0 && iSetRecentSct)
+        {
+        DrawRecentCharFrame(gc);
+        }
+
+    // Cell items.
+    TInt charIndex = iFirstVisibleRow * iMaxColumns;
+    cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    TInt numberOfChars = NumberOfVisibleChars();
+    TBool highlighted = EFalse;
+    for (TInt j = 0; j < numberOfChars; j++)
+        {
+
+        // emotions in next line are all ready to draw
+        if((j%iMaxColumns) == 0)
+            {
+            if(!EmotionsAreAllReadyToDraw(charIndex, iMaxColumns)) break;
+            }
+        
+        // grid is focused and cursor pos is same with the current index.
+        if ( iExtension->iMenuSct )
+        	{
+            highlighted = iExtension->iMenuSctHighlighted && 
+                          (iExtension->iFocusHandler->FocusedControl()==this) && 
+                          (j==cursorPos);
+        	}
+        else
+        	{
+        	highlighted = ((iExtension->iFocusHandler->FocusedControl()==this) && (j==cursorPos));
+        	}
+        DrawItem(gc, CursorRect(j, charIndex), charIndex, highlighted, EFalse);
+        charIndex++;
+        }
+    iDrawnBefore = ETrue;
+    gc.DiscardFont();
+    }
+
+//--------------------------------------------------------------
+// Return how many chars to be drawn
+//--------------------------------------------------------------
+//
+TInt CAknCharMap::NumberOfVisibleChars() const
+    {
+    TInt numberOfCharsToBeDrawn = iChars->Length();
+    numberOfCharsToBeDrawn -= (iFirstVisibleRow * iMaxColumns);
+    if ( numberOfCharsToBeDrawn > (iExtension->iMaxVisibleRows * iMaxColumns))
+        {
+        numberOfCharsToBeDrawn = iExtension->iMaxVisibleRows * iMaxColumns;
+        }
+    __ASSERT_DEBUG( numberOfCharsToBeDrawn >= 1, Panic(EAknPanicOutOfRange));
+
+    if(Extension()->iMenuSct)
+        {
+        return Min(iExtension->iMaxVisibleRows * iMaxColumns, iChars->Length());
+        }
+    return numberOfCharsToBeDrawn;
+    }
+
+/**
+*
+* Local method to return the RTL mirrored character for the (LTR) input character
+*
+* The method has buffers ready to accept surrogate pairs when they become supported in the
+* descriptor methods.
+*
+* The return buffer is padded with extra characters that in theory may arise in bidirectional
+* conversion, but since only one character is input, no leading "zero width joiner" will be
+* at index 0.  Hence, the resulting character at 0 is returned, with no check for the zero width
+* joiner.
+*/
+TChar MirrorChar(TChar a)
+    {
+    TBuf<2> buf; // ready for when surrogate pairs need handling
+    buf.Append(a);
+    TBidirectionalState::TRunInfo ri;
+    TBidiLogicalToVisual bl2v(buf, ETrue, &ri, 1); // Only 1 run info element passed
+    bl2v.Reorder();
+    TBuf<2+TBidiLogicalToVisual::KMinCharAvailable> result;
+    bl2v.GetVisualLine(result, 0, buf.Length(), 0xFFFF);
+    // Always use index 0 as this situation can not result in a zero-width joiner at index 0
+    return result[0];  // This return is not surrogate pair-ready
+    }
+
+//-------------------------------------------------------------------------
+// Set the pen, color, brush, etc. before drawing the frame of a special char
+// item.
+// Note: The frame is inside the cell.
+//-------------------------------------------------------------------------
+//
+void CAknCharMap::SetItemFrameStyle( CWindowGc& aGc) const
+    {
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+    TRgb colorFrame = AKN_LAF_COLOR(215);
+    AknsUtils::GetCachedColor( skin, colorFrame,
+        KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 );
+    aGc.SetPenColor(colorFrame);
+    aGc.SetPenSize(TSize(1,1));
+    }
+
+//--------------------------------------------------------------
+// Draw the rect edge lines which are inside the cell and around
+// the char.
+//--------------------------------------------------------------
+//
+void CAknCharMap::DrawItemFrame( CWindowGc& aGc,
+        const TRect& aItemRect, TInt aCharIndex,
+        TBool aHighlighted,
+        TBool /*aDrawBackground*/ ) const
+    {
+    SetItemFrameStyle(aGc);
+
+    if(IsRecentChar(aCharIndex))
+        {
+        // recent char hasn't inner frames.
+        return;
+        }
+    if( aHighlighted )
+        {
+        aGc.DrawRect( aItemRect );
+        }
+    }
+
+//--------------------------------------------------------------
+// brush the background rect inside the cell.
+//--------------------------------------------------------------
+//
+void CAknCharMap::DrawItemShade( CWindowGc& aGc,
+        const TRect& aItemRect, TInt /*aCharIndex*/,
+        TBool aHighlighted,
+        TBool aDrawBackground ) const
+    {
+
+    TRect innerRect = aItemRect;
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+
+    if( aHighlighted )
+        {
+        TRgb color = AKN_LAF_COLOR(210);
+		
+        if( !( iExtension->iFlags & EAknCharMapPressedDown ) 
+            || iExtension->iSingleClickEnabled )
+            {
+            AknsUtils::GetCachedColor( skin, 
+                    color, 
+                    KAknsIIDQsnHighlightColors, 
+                    EAknsCIQsnHighlightColorsCG1 );
+            }
+			
+        else
+            {
+            AknsUtils::GetCachedColor( skin, color, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG2 );
+            }
+        aGc.SetBrushColor(color);
+        aGc.Clear( innerRect );
+        }
+    else if( aDrawBackground )
+        {
+        if ( iExtension->iBgContext )
+            {
+            cc = iExtension->iBgContext;
+            }
+        AknsDrawUtils::Background( skin, cc, this, aGc, innerRect );
+        }
+    }
+
+void CAknCharMap::DrawItem(
+    CWindowGc& aGc,
+    const TRect& aSctPosition,
+    TInt aCharIndex,
+    TBool aHighlighted,
+    TBool aDrawBackground ) const
+    {
+    if (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface)
+        {
+        DrawPicto(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground);
+        return;
+        }
+    
+    if ( iExtension->iSingleClickEnabled &&
+         !iExtension->iHighlightVisible )
+        {
+        aHighlighted = EFalse;
+        }
+    
+    DrawItemShade(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground);
+    
+    DrawItemFrame(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground);
+
+    TAknTextLineLayout specialCharItemLayout;
+    if (AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct)
+        {
+        if ( Layout_Meta_Data::IsLandscapeOrientation() )
+            {
+            specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(1);
+            }
+        else if (IsJapaneseSctUi())
+            {
+            specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(2);
+            }
+        else
+            {
+            specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(0);
+            }
+        }
+    else
+        {
+        specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic_popup_pane_t2();
+        }
+
+    TRect textRect = aSctPosition;
+    if( IsRecentChar(aCharIndex) )
+        {
+        textRect.Move(0, -1);       //because height of recent char frame decreased 1.
+        if( Extension()->iMenuSct )
+            {
+            textRect.Move(0, -1);   //because menu sct will also shrink 1.
+            }
+        }
+    TAknLayoutText textLayout;
+    textLayout.LayoutText(textRect, specialCharItemLayout);
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+
+    TRgb color;
+    TBuf<1> symbol;
+    TChar character = '\t';
+    character = (*iChars)[ aCharIndex ];
+
+    // Is Mirrored language (Arabic or Hebrew) used as input language
+    TBool mirroredLanguage(
+        AknTextUtils::CurrentScriptDirectionality() == TBidiText::ERightToLeft);
+
+    //  Obtain mirrored forms
+    if ( mirroredLanguage )
+        {
+        TChar oldCharacter( character );
+        character = MirrorChar( oldCharacter );
+        }
+    // Note: the character is now mirrored.  The following visual substitution may need to be
+    // aware of this:
+
+    _LIT(KChar,"%c");
+
+    // Special cases if needed to use PUA symbols on screen
+    if ( (character == CEditableText::EParagraphDelimiter) || (character == 0x000A) ) // Line feed
+        {
+        if ( mirroredLanguage )
+            {
+            symbol.Format(KChar, KPuaCodeMirroredLineFeedSymbol); // Symbol for mirrored line feed
+            }
+        else
+            {
+            symbol.Format(KChar, KPuaCodeLineFeedSymbol); // Symbol for line feed
+            }
+        }
+    else if ( character == CEditableText::ESpace ) // Space
+        {
+        symbol.Format(KChar, KPuaCodeSpaceSymbol); // Symbol for space
+        }
+    else if ( character == 0x3000 ) // Full width Space
+        {
+        symbol.Format(KChar, KPuaCodeFullWidthSpaceSymbol); // Symbol for space
+        }
+    else if ( character == 0x200E ) // RLM
+        {
+        symbol.Format(KChar, KPuaCodeRightToLeftSymbol); // Symbol for RLM
+        }
+    else if ( character == 0x200F ) // LRM
+        {
+        symbol.Format(KChar, KPuaCodeLeftToRightSymbol); // Symbol for LRM
+        }
+    else if ( ( character == 0x0E31 ||
+        0x0E33 <= character && character <= 0x0E3A) ||
+        (0x0E47 <= character && character <= 0x0E4E) ) // Thai SCT-cases
+        {
+        symbol.Format(KChar, TUint(character)+KThaiSCTCombiningSymbolAdd);
+        }
+    else if ( character == KHistoryEmptyChar )
+        {
+        symbol.Format(KChar, KHistoryEmptyCharForDisplay);
+        }
+    else  // Defaul case - show symbol as it is
+        {
+        symbol.Format(KChar, static_cast<TInt>(character));
+        }
+
+    if ( aHighlighted )
+        {
+        AknsUtils::GetCachedColor( skin, color,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG24 );
+        }
+    else
+        {
+        AknsUtils::GetCachedColor( skin, color,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG19 );
+        }
+    
+    if(TEmotionUtils::IsEmotionChar(symbol[0]))
+        {
+        iExtension->DrawEmotion(aGc, textLayout.TextRect(), symbol[0]);
+        }
+    else
+        {
+        textLayout.DrawText( aGc, symbol, EFalse, color );
+        }
+    
+    }
+
+
+//-------------------------------------------------------
+// Set the color, pen, style for drawing recent char map
+// frame
+//-------------------------------------------------------
+//
+void CAknCharMap::SetRecentCharFrameStyle( CWindowGc& aGc) const
+    {
+    TRgb colorRecentLine = AKN_LAF_COLOR(215);
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    AknsUtils::GetCachedColor( skin, colorRecentLine,
+            KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 );
+    aGc.SetPenColor(colorRecentLine);
+    aGc.SetPenSize(TSize(2,2));
+    }
+
+//-------------------------------------------------------
+// Draw the outter thick frame for the all recent chars.
+//-------------------------------------------------------
+//
+void CAknCharMap::DrawRecentCharFrame( CWindowGc& aGc) const
+    {
+    MAknsSkinInstance*   skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = iExtension->iBgContext;
+    if ( !cc )
+        {
+        cc = AknsDrawUtils::ControlContext( this );
+        }
+
+    TPoint pos = iGridTopLeft;
+    TInt endX = pos.iX + iGridItemWidth * iMaxColumns + 1;
+    TInt endY = pos.iY + iGridItemHeight;
+    TRect drawRect(TPoint(pos.iX, pos.iY), TPoint(endX, endY));
+    // eliminate the overlap area between menu sct and the first menu item.
+    if ( Extension()->iMenuSct )
+        {
+        drawRect = Rect();
+        endY--;
+        }
+
+    AknsDrawUtils::Background( skin, cc, this, aGc, drawRect );
+
+    SetRecentCharFrameStyle(aGc);
+    if(iIsMirrored)
+        {
+        pos.iX = iGridTopLeft.iX - ((iMaxColumns - 1) * iGridItemWidth);
+        endX = iGridTopLeft.iX + iGridItemWidth + 1;
+        }
+
+    aGc.DrawRect( TRect(TPoint(pos.iX-1, pos.iY-1), TPoint(endX, endY)));
+    
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    CFeedbackSpec* spec = CFeedbackSpec::New();
+
+    if ( spec && feedback )
+        {
+        CAknCharMap* mutableThis = MUTABLE_CAST( CAknCharMap* ,this );
+        TInt recentChars = mutableThis->LengthOfRecentChar();
+        TRect rect;
+        spec->AddFeedback( ETouchEventStylusDown, 
+                           ETouchFeedbackList );
+        rect.SetRect( pos, TPoint( pos.iX + recentChars * iGridItemWidth, pos.iY + iGridItemHeight ));
+        if ( iIsMirrored )
+            {
+            TInt emptyRecentSlots = iMaxColumns - recentChars;
+            rect.Move( emptyRecentSlots * iGridItemWidth, 0 );
+            }
+        feedback->SetFeedbackArea( this, KAreaIdRecent, rect, spec );
+        
+        delete spec;
+        }
+    }
+
+//-------------------------------------------------------
+// Set the pen, color, brush, etc. to draw the char map
+// grid
+//-------------------------------------------------------
+//
+void CAknCharMap::SetGridStyle( CWindowGc& aGc) const
+    {
+    TRgb colorLine = AKN_LAF_COLOR(219);
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    AknsUtils::GetCachedColor( skin, colorLine,
+            KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG5 );
+    aGc.SetPenColor(colorLine);
+    aGc.SetPenSize(TSize(1,1));
+    }
+
+//-------------------------------------------------------
+// draw the char map grid
+// Note: only draw the grid, do not draw the recent char
+// map frame.
+//-------------------------------------------------------
+//
+void CAknCharMap::DrawGrid( CWindowGc& aGc) const
+    {
+    SetGridStyle(aGc);
+
+    //
+    // a better method: (0~MaxChars) do:[:each| each drawRect.]
+    //
+    const TSize gridItemRectSize( iGridItemWidth + 1, iGridItemHeight + 1);
+    TInt numberOfCells = NumberOfVisibleChars();
+    TPoint pos = iGridTopLeft;
+    TInt ii=0;
+    if (iFirstVisibleRow == 0 && iSetRecentSct)
+        {
+        pos.iY += iGridItemHeight;  //skip the recent char area
+        ii=iMaxColumns;
+        }
+    else
+        {
+        // remove area for recent characters because they does not exist in this view
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            feedback->RemoveFeedbackArea( this, KAreaIdRecent );
+            }
+        }
+    for(; ii < numberOfCells; ++ii)
+        {
+        aGc.DrawRect(TRect( pos, gridItemRectSize ));
+
+        if ( iIsMirrored )
+            {
+            pos.iX -= iGridItemWidth;
+            }
+        else
+            {
+            pos.iX += iGridItemWidth;
+            }
+
+        if( (ii+1) % iMaxColumns == 0 )
+            {
+            pos.iX  = iGridTopLeft.iX;   //reset for each row.
+            pos.iY += iGridItemHeight;
+            }
+        }
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    CFeedbackSpec* spec = CFeedbackSpec::New();
+
+    if ( feedback && spec )
+        {
+        TInt orphans = NumberOfVisibleChars() % iMaxColumns;
+        TInt rows = NumberOfVisibleChars() / iMaxColumns;
+        CAknCharMap* mutableThis = MUTABLE_CAST( CAknCharMap* ,this );
+        TInt recentChars = mutableThis->LengthOfRecentChar();    
+        TRect rectMain;
+        TPoint nextTopLeft = iGridTopLeft;    
+
+        if ( CurrentPage() == 1 )
+            {
+            nextTopLeft.iY += iGridItemHeight;
+            if ( rows > 0 )
+                rows--;
+            }
+
+        rectMain.SetRect( nextTopLeft, TPoint(nextTopLeft.iX + iMaxColumns * iGridItemWidth, nextTopLeft.iY + rows * iGridItemHeight) );
+        if ( iIsMirrored )
+            {
+            rectMain.Move( ( 1 - iMaxColumns ) * iGridItemWidth, 0 );
+            }
+
+        spec->AddFeedback( ETouchEventStylusDown, 
+                           ETouchFeedbackList );
+        if ( rows )
+            {
+            feedback->SetFeedbackArea( this, KAreaIdMain, rectMain, spec );
+            }
+        else
+            {
+            feedback->RemoveFeedbackArea( this, KAreaIdMain );
+            }
+
+        nextTopLeft.iY = rectMain.iBr.iY;
+            
+        if ( orphans )
+            {
+            TRect rectOrphans;
+            rectOrphans.SetRect( TPoint( iGridTopLeft.iX, pos.iY), TPoint( iGridTopLeft.iX + orphans * iGridItemWidth, pos.iY + iGridItemHeight) );
+            if ( iIsMirrored )
+                {
+                rectOrphans.Move( ( 1 - orphans ) * iGridItemWidth, 0 );
+                }
+
+            feedback->SetFeedbackArea( this, KAreaIdTail, rectOrphans, spec );
+            }
+        else
+            {
+            // remove feedback area for tail area because all rows of grid has maximum number of characters
+            feedback->RemoveFeedbackArea( this, KAreaIdTail );
+            }
+        
+        delete spec;
+        }        
+    }
+
+// Optimizes drawing. Only cursor is drawn.
+void CAknCharMap::DrawCursor() const
+    {
+    // Whole SCT has to be drawn at least once.
+    // If the user presses arrow key before SCT has been drawn,
+    // only cursor position is drawn without this check.
+    if ( !iDrawnBefore )
+        {
+        DrawNow();
+        }
+    else
+        {
+        CWindowGc& gc = SystemGc();
+        // Only redraw old and new cursor position cells
+        if( !CAknEnv::Static()->TransparencyEnabled() )
+            {
+            ActivateGc();
+            gc.UseFont(iFont);
+            }
+
+        TInt cursorPos = 0;
+        if ( iOldCursorPos != iCursorPos )
+            {
+            // Redraw only if old pos different from current pos
+            cursorPos = iOldCursorPos.iX + iOldCursorPos.iY * iMaxColumns;
+            DrawCell( cursorPos, EFalse );
+            }
+
+        cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+        DrawCell( cursorPos, (iExtension->iFocusHandler->FocusedControl()==this) );
+
+        if( !CAknEnv::Static()->TransparencyEnabled() )
+            {
+            gc.DiscardFont();
+            DeactivateGc();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::DrawCell
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::DrawCell(
+    TInt aCursorPos,
+    TBool aHighLighted ) const
+    {
+    // calculate character index
+    TInt charIndex = aCursorPos + iFirstVisibleRow * iMaxColumns;
+    if(charIndex >= iChars->Length())
+        {
+        return;
+        }
+
+    // If we are only redrawing for animations, no need to draw non-animated items.
+    if (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface)
+        {
+        if ( iAnimated && 
+             !iPictoInterface->Interface()->IsAnimated((*iChars)[charIndex],iCurrentPictographHeight) )
+            {
+            return;
+            }
+        }
+
+    TRect rect = CursorRect( aCursorPos, charIndex );
+
+    if( CAknEnv::Static()->TransparencyEnabled() )
+        {
+
+        const TBool backedUp = IsBackedUp();
+        if ( !backedUp )
+            {
+            Window().Invalidate( rect );
+            Window().BeginRedraw( rect );
+            }
+
+        ActivateGc();
+        CWindowGc& gc = SystemGc();
+        gc.UseFont(iFont);
+
+        DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue );
+
+        gc.DiscardFont();
+        DeactivateGc();
+
+        if ( !backedUp )
+            {
+            Window().EndRedraw();
+            }
+        }
+    else
+        {
+        if ( !Extension()->iMenuSct )
+            {
+            Window().Invalidate( rect );
+            Window().BeginRedraw( rect );
+            DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue );
+            Window().EndRedraw();
+            }
+        else
+            {
+            DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::CursorRect
+// -----------------------------------------------------------------------------
+//
+TRect CAknCharMap::CursorRect( TInt aCursorPos, TInt aCharIndex) const
+    {
+    TPoint pos = iOffset;
+
+    if (iIsMirrored)
+        {
+        pos.iX -= (aCursorPos % iMaxColumns) * iGridItemWidth;
+        }
+    else // Not mirrored
+        {
+        pos.iX += (aCursorPos % iMaxColumns) * iGridItemWidth;
+        }
+
+    pos.iY += (aCursorPos / iMaxColumns) * iGridItemHeight;
+    TRect res = TRect( pos, TSize( iGridItemWidth - 2, iGridItemHeight - 2 ) );
+    if(IsRecentChar(aCharIndex))
+        {
+        res.iBr.iY --; //because the width of recent char frame is 2 but not 1.
+        }
+     // Eliminate the overlap between menu sct and the first menu option' item
+     if ( Extension()->iMenuSct )
+        {
+        res.iBr.iY --;
+        }
+    return res;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::MoveCursorL
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::MoveCursorL(TInt aDeltaX, TInt aDeltaY)
+    {
+    __ASSERT_DEBUG(
+        (aDeltaX <= 1) && (aDeltaX >= -1) &&
+        (aDeltaY <= 1) && (aDeltaY >= -1) &&
+        ((aDeltaX * aDeltaY) == 0), Panic(EAknPanicOutOfRange));
+
+    if (iIsMirrored)
+        aDeltaX = -aDeltaX;
+
+    iOldCursorPos = iCursorPos;
+    TInt oldFirstVisibleRow = iFirstVisibleRow;
+
+    TInt globalYPos = iCursorPos.iY + iFirstVisibleRow;
+    TInt lastColumnOnLastRow(0);
+    if ( Extension()->iMenuSct )
+        {
+        lastColumnOnLastRow = LengthOfRecentChar() - 1;
+        }
+    else
+        {
+        lastColumnOnLastRow = (iChars->Length() - 1) % iMaxColumns;
+        }
+
+    TInt checktable(-1);
+    TInt skipchar = aDeltaX != 0 ? 1: 0;
+    TBool caseChange(EFalse);
+
+    // First line is NULL when Cursor was second line
+    if ( (iCursorPos.iY+iFirstVisibleRow == 1) && 
+         ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+           (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar) ) 
+       )
+        {
+        caseChange = ETrue;
+        // Cursor was on the second line
+        if (aDeltaY < 0)
+            {
+            globalYPos--;
+            }
+        // Cursor was on the second line and first position
+        if (aDeltaX < 0 && iCursorPos.iX == 0)
+            {
+            globalYPos--;
+            //iCursorPos.iY = 0;
+            iCursorPos.iX = 0;
+            }
+        }
+    else
+        {
+        TInt delta = aDeltaX != 0 ? aDeltaX: aDeltaY;
+        TInt next = aDeltaX != 0 ? aDeltaX: 0;
+        TInt charIndex = iCursorPos.iX +
+                (iCursorPos.iY + aDeltaY + iFirstVisibleRow) * iMaxColumns; //the x index includes the current row
+
+        for(TInt i(0); i <= iMaxColumns; ++i)
+            {
+            if (aDeltaY < 0 && charIndex < 0)
+                {
+                charIndex = 0;
+                caseChange = ETrue; // prev case
+                }
+            if (aDeltaY > 0 && iChars->Length() <= charIndex) // index 0 length 1 etc.
+                {
+                // set Position(iCursorPos.iX, 0)
+                charIndex = iChars->Length() - 1;//iCursorPos.iX;
+                i = charIndex;
+                caseChange = ETrue; // next case
+                }
+            if (aDeltaX < 0 && charIndex <= 0)
+                {
+                charIndex = iChars->Length() - 1;
+                caseChange = ETrue; // prev case
+                }
+            if (aDeltaX > 0 && iChars->Length() - 1 <= charIndex)
+                {
+                charIndex = 0;
+                caseChange = ETrue; // next case
+                }
+            if (caseChange && iShowCasesRef->Count() > 1)
+                {
+                // change case
+                break;
+                }
+            if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[charIndex+next])) || 
+                 (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[charIndex+next]!=KHistoryEmptyChar) )
+                {
+                break;
+                }
+            charIndex += delta;
+            skipchar++;
+            }
+        }
+
+    if (aDeltaX < 0)
+        {
+        // Cursor was moved to left.
+        if (iCursorPos.iX > skipchar - 1)
+            {
+            iCursorPos.iX -= skipchar;
+            }
+        else
+            {
+            if (skipchar > iMaxColumns)
+                {
+                globalYPos--;
+                iCursorPos.iX = iMaxColumns;
+                }
+            // Go to previous line
+            globalYPos--;
+            if (globalYPos < 0)
+                {
+                // Cursor was on the first line - go to last line.
+                globalYPos = iRows - 1;
+                // x - position to the last item on the last row.
+                iCursorPos.iX = lastColumnOnLastRow;
+                checktable = iMaxColumns;
+                }
+            else
+                {
+                // x - position to last column.
+                iCursorPos.iX = iMaxColumns - skipchar;
+                }
+            }
+        }
+
+    if (aDeltaX > 0)
+        {
+        // Cursor was moved to right.
+        if (globalYPos < iRows - 1)
+            {
+            // Not in the last row.
+            if (iCursorPos.iX < iMaxColumns - skipchar)
+                {
+                // If not on the last columns, move cursor to next column.
+                iCursorPos.iX += skipchar;
+                }
+            else
+                {
+                // Cursor was on last column,
+                // move to first column of the next line.
+                iCursorPos.iX = 0;
+                globalYPos++;
+                }
+            }
+        else
+            {
+            // Currently on the last row.
+            if ( iCursorPos.iX < lastColumnOnLastRow )
+                {
+                // If there are more items on this row, move cursor to next item.
+                iCursorPos.iX++;
+                }
+            else
+                {
+                // No more item on the current row.
+                // Move to first item on the first row.
+                iCursorPos.iX = 0;
+                checktable = 0;
+                globalYPos = 0;
+                }
+            }
+        }
+
+    if (aDeltaY < 0)
+        {
+        iCursorPos.iX -= skipchar;
+        if (iCursorPos.iX < 0)
+            {
+            iCursorPos.iX += (iMaxColumns - 1);
+            globalYPos--;
+            }
+        // Cursor was moved to up.
+        if (globalYPos > 0)
+            {
+            // Cursor was not on the first line - move it to previous row.
+            globalYPos--;
+            }
+        else
+            {
+            checktable = iCursorPos.iX;
+            // Move cursot to last to row.
+            globalYPos = iRows - 1;
+            if (iCursorPos.iX > lastColumnOnLastRow)
+                {
+                // No items in the current column on the last row -
+                // move cursor to last item on the row.
+                iCursorPos.iX = lastColumnOnLastRow;
+                }
+            }
+        }
+
+    if (aDeltaY > 0)
+        {
+        iCursorPos.iX = (iCursorPos.iX + skipchar) % iMaxColumns;
+        globalYPos += (iCursorPos.iX + skipchar) / iMaxColumns;
+        // Cursor was moved to down.
+        if (globalYPos < iRows - 1)
+            {
+            // Cursor is not on the last row. Move cursor to next row.
+            globalYPos++;
+            if (globalYPos == iRows - 1 && iCursorPos.iX > lastColumnOnLastRow)
+                {
+                // No items in the current column on the last row -
+                // move cursor to last item on the row.
+                iCursorPos.iX = lastColumnOnLastRow;
+                }
+            }
+        else
+            {
+            // Cursor was at the last row - move it to the first row.
+            globalYPos = 0;
+            checktable = iCursorPos.iX;
+            }
+        }
+    iCursorPos.iY = globalYPos - iFirstVisibleRow;
+
+    if (globalYPos < iFirstVisibleRow)
+        {
+        // Cursor was moved from the top row.
+        if (globalYPos <= 0)
+            {
+            iFirstVisibleRow = 0;
+            iCursorPos = TPoint(iCursorPos.iX, 0);
+            }
+        else
+            {
+            // If cursor was moved up out of the visible area - show it again.
+            iFirstVisibleRow -= iExtension->iMaxVisibleRows;
+            iCursorPos = TPoint(iCursorPos.iX, iExtension->iMaxVisibleRows - 1);
+            }
+        }
+
+    if (globalYPos > iFirstVisibleRow + iExtension->iMaxVisibleRows - 1)
+        {
+        if (globalYPos == iRows - 1)
+            {
+            // When cursor has moved from the top line,
+            // it is adjusted to a page boundary.
+            iFirstVisibleRow = VisibleRows();
+            iCursorPos = TPoint(
+                iCursorPos.iX,
+                (iRows - 1) % iExtension->iMaxVisibleRows
+                );
+            }
+        else
+            {
+            // If cursor was moved down out of the visible area - show it again.
+            iFirstVisibleRow += iExtension->iMaxVisibleRows;
+            iCursorPos = TPoint(iCursorPos.iX, 0);
+            }
+        }
+
+    TInt increment(1);
+    if (aDeltaY < 0 || aDeltaX < 0)
+        {
+        increment = -1;
+        }
+    if (checktable >= 0 && SwitchAnotherTableL(increment) > 0)
+        {
+        TInt lastColumnOnLastRow = ((iChars->Length() - 1) % iMaxColumns);
+        TPoint pt(checktable, 0);
+        if (aDeltaY < 0 || aDeltaX < 0)
+            {
+            iFirstVisibleRow =
+                ((*iShowPagesRef)[iCaseIndex] - 1) * iExtension->iMaxVisibleRows;
+            pt.iX = Min(pt.iX, lastColumnOnLastRow);
+            pt.iY = iRows - 1;
+            if (iRows > iExtension->iMaxVisibleRows)
+                {
+                pt.iY -= (((iRows-1) / iExtension->iMaxVisibleRows) * iExtension->iMaxVisibleRows);
+                }
+
+            }
+        else if (iRows == 1)
+            {
+            pt.iX = Min(pt.iX, lastColumnOnLastRow);
+            }
+        else if (caseChange)
+            {
+            // When first line is NULL, cursor is moved to the second line
+            TInt index = pt.iX + (pt.iY + iFirstVisibleRow) * iMaxColumns;
+            for (; index >= 0 ; index--)
+                {
+                if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[index])) || 
+                     (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[index] != KHistoryEmptyChar) )
+                    {
+                    break;
+                    }
+                }
+            if (index < 0)
+                {
+                pt.iY = 1;
+                }
+            else
+                {
+                pt.iX = index;
+                }
+            }
+        
+        HandleFocusStatusChanged();
+
+        iCursorPos = pt;
+        UpdateScrollIndicatorL();
+        DrawNow();
+        }
+    else
+        {
+        if (caseChange)
+            {
+            TPoint pt(iCursorPos);
+            // When first line is NULL, cursor is moved to the second line
+            TInt index = pt.iX + (pt.iY + iFirstVisibleRow) * iMaxColumns;
+            for (; index >= 0 ; index--)
+                {
+                if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[index])) || 
+                     (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[index]!=KHistoryEmptyChar) )
+                    {
+                    break;
+                    }
+                }
+            if (index < 0)
+                {
+                pt.iY = 1;
+                }
+            else
+                {
+                pt.iX = (index % iMaxColumns);
+                }
+            iCursorPos = pt;
+            }
+
+        if ((iRows > iExtension->iMaxVisibleRows) &&
+            (iOldCursorPos.iY + oldFirstVisibleRow != iCursorPos.iY + iFirstVisibleRow))
+            {
+            UpdateScrollIndicatorL();
+            }
+        
+        HandleFocusStatusChanged();
+
+        if (oldFirstVisibleRow == iFirstVisibleRow)
+            {
+                // Draw only cursor if the view to the content was not scrolled.
+            DrawCursor();
+            }
+        else
+            {
+            DrawNow();
+            }
+        }
+    }
+
+void CAknCharMap::UpdateScrollIndicatorL()
+    {
+    if ( !iSBFrame )
+        {
+        return;
+        }
+    TEikScrollBarModel hSbarModel;
+    TEikScrollBarModel vSbarModel;
+
+    TEikScrollBarFrameLayout layout;
+
+    // Main pane without softkeys
+    TRect mainPaneRect;
+    if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EPopupParent, mainPaneRect))
+        {
+        mainPaneRect = iAvkonAppUi->ClientRect();
+        }
+
+    // Dialog layout, check variety first
+    TAknLayoutScalableParameterLimits charMapDialogVariety =
+        AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+    TInt maxVariety = charMapDialogVariety.LastVariety();
+
+    // Check the CBA, if the orientation is not landscape
+    // there is not so much varieties
+    AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation();
+    TInt maxVarietyOffset = 0; // the offset for the certain cba location variety
+    TInt varietyOffset = maxVariety + 1;
+
+    // landscape variety number must be calculated offset == number of varieties
+    // same applies to the variety number for the biggest sized layout for the variety
+    if(Layout_Meta_Data::IsLandscapeOrientation())
+        {
+        varietyOffset = (maxVariety + 1)/KAknSctCBaButtonDirections; // the offset for one variety
+        }
+
+    // for right and left cba buttons the max variety is not zero
+    // the varities are ordered by the location of the cba and the descending order
+    // e.g the biggest sized layout first, the smallest last
+    if(location == AknLayoutUtils::EAknCbaLocationRight)
+        {
+        maxVarietyOffset = varietyOffset;
+        }
+    else if(location == AknLayoutUtils::EAknCbaLocationLeft)
+        {
+        maxVarietyOffset = varietyOffset + varietyOffset; // 2*
+        }
+
+    TInt varietyNumber = varietyOffset - iRows;
+
+    // if more lines than possible to show, use the default
+    // (the biggest grid) variety
+    if(varietyNumber < 0)
+        varietyNumber = 0;
+    // if zero rows, use the minimum
+    else if(iRows<=0)
+        varietyNumber -= 1;
+
+    //add the varietyoffset
+    varietyNumber += maxVarietyOffset;
+
+    // Layout the dialog size
+    TAknLayoutRect dialogLayRect;
+    dialogLayRect.LayoutRect( mainPaneRect,
+        AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber));
+
+    TRect dialogRect = dialogLayRect.Rect();
+
+    // Get the layout of the actual character grid with scrollbar
+    TAknLayoutRect gridWithScrollLayRect;
+
+    gridWithScrollLayRect.LayoutRect(TRect(TPoint(0,0),TSize(dialogRect.Size())),
+        AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+    // Calculate the relative rect for the grid
+    TRect parent = gridWithScrollLayRect.Rect();
+
+    TAknWindowComponentLayout scrollbarLayout;
+    if (iExtension->iHasCategoryButtonUi)
+        {
+        scrollbarLayout = AknLayoutScalable_Avkon::scroll_pane_cp5(1);
+        }
+    else
+        {
+        scrollbarLayout = AknLayoutScalable_Avkon::scroll_pane_cp5(0);
+        }
+
+    vSbarModel.iScrollSpan = PageCount() * iExtension->iMaxVisibleRows;
+    vSbarModel.iThumbSpan = iExtension->iMaxVisibleRows;
+
+    if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
+        {
+        // For EDoubleSpan type scrollbar
+        vSbarModel.iThumbPosition = (CurrentPage()-1) * iExtension->iMaxVisibleRows;
+        TAknDoubleSpanScrollBarModel hDsSbarModel(hSbarModel);
+        TAknDoubleSpanScrollBarModel vDsSbarModel(vSbarModel);
+
+        iSBFrame->Tile(&vDsSbarModel);
+        AknLayoutUtils::LayoutVerticalScrollBar(iSBFrame, parent,
+        scrollbarLayout);
+        iSBFrame->SetVFocusPosToThumbPos(vDsSbarModel.FocusPosition());
+        }
+    else
+        {
+        // For EArrowHead type scrollbar
+        vSbarModel.iThumbPosition = iCursorPos.iY + iFirstVisibleRow;
+        iSBFrame->TileL(&hSbarModel,&vSbarModel,parent,parent,layout);
+        iSBFrame->SetVFocusPosToThumbPos(vSbarModel.iThumbPosition);
+        }
+    }
+
+void CAknCharMap::Reserved_1()
+    {
+    }
+
+void CAknCharMap::Reserved_2()
+    {
+    }
+
+const TDesC* CAknCharMap::LowerCaseCharacters() const
+    {
+    return iCharsBufferLower;
+    }
+
+const TDesC* CAknCharMap::UpperCaseCharacters() const
+    {
+    return iCharsBufferUpper;
+    }
+
+const TDesC* CAknCharMap::NumericCharacters() const
+    {
+    return iCharsBufferNumeric;
+    }
+
+void CAknCharMap::CopyCharactersL( const CAknCharMap& aCharMap )
+    {
+    const TDesC* chars = aCharMap.LowerCaseCharacters();
+    if ( chars )
+        {
+        delete iCharsBufferLower;
+        iCharsBufferLower = NULL;
+        if (Extension()->iMenuSct)
+            {
+            iCharsBufferLower = chars->Mid(iMaxColumns).AllocL();
+            }
+        else
+            {
+            iCharsBufferLower = chars->AllocL();
+            }
+        }
+
+    chars = aCharMap.UpperCaseCharacters();
+    if ( chars )
+        {
+        delete iCharsBufferUpper;
+        iCharsBufferUpper = NULL;
+        if (Extension()->iMenuSct)
+            {
+            iCharsBufferUpper = chars->Mid(iMaxColumns).AllocL();
+            }
+        else
+            {
+            iCharsBufferUpper = chars->AllocL();
+            }
+        }
+
+    chars = aCharMap.NumericCharacters();
+    if ( chars )
+        {
+        delete iCharsBufferNumeric;
+        iCharsBufferNumeric = NULL;
+        if (Extension()->iMenuSct)
+            {
+            iCharsBufferNumeric = chars->Mid(iMaxColumns).AllocL();
+            }
+        else
+            {
+            iCharsBufferNumeric = chars->AllocL();
+            }
+        }
+
+    chars = NULL;
+    if (aCharMap.iExtension)
+        {
+        chars = aCharMap.iExtension->iCharsQwerty;
+        }
+    if ( chars )
+        {
+        delete iExtension->iCharsQwerty;
+        iExtension->iCharsQwerty = NULL;
+        if (Extension()->iMenuSct)
+            {
+            iExtension->iCharsQwerty = chars->Mid(iMaxColumns).AllocL();
+            }
+        else
+            {
+            iExtension->iCharsQwerty = chars->AllocL();
+            }
+        }
+    }
+
+void CAknCharMap::DrawPictographArea()
+    {
+    if (iChaMapTableCase != EAknCharMapTableSpecialChar)
+        {
+        CWindowGc& gc = SystemGc();
+        if( !CAknEnv::Static()->TransparencyEnabled() )
+            {
+            ActivateGc();
+            gc.UseFont( iFont );
+            }
+
+        // Calculate the number of items.
+        TInt numberOfCharsToBeDrawn = iChars->Length();
+        numberOfCharsToBeDrawn -= (iFirstVisibleRow * iMaxColumns);
+        if ( numberOfCharsToBeDrawn > (iExtension->iMaxVisibleRows * iMaxColumns))
+            {
+            numberOfCharsToBeDrawn = iExtension->iMaxVisibleRows * iMaxColumns;
+            }
+        __ASSERT_DEBUG( numberOfCharsToBeDrawn >= 1, Panic(EAknPanicOutOfRange));
+
+        // Draw all items. Implementation takes care that only animated
+        // items are actually redrawn.
+
+        iAnimated = ETrue;
+
+        TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+
+        for (TInt j = 0; j < numberOfCharsToBeDrawn; j++)
+            {
+            DrawCell( j, j == cursorPos );
+            }
+
+        iAnimated = EFalse;
+
+        if( !CAknEnv::Static()->TransparencyEnabled() )
+            {
+            gc.DiscardFont();
+            DeactivateGc();
+            }
+        }
+    }
+
+TInt CAknCharMap::PageCount() const
+    {
+    TInt page(0);
+    for (TInt i(0); i < iShowCasesRef->Count(); ++i)
+        {
+        page += (*iShowPagesRef)[i];
+        }
+
+    return page;
+    }
+
+TInt CAknCharMap::CurrentPage() const
+    {
+    TInt page(0);
+    for (TInt i(0); i < iCaseIndex; ++i)
+        {
+        page += (*iShowPagesRef)[i];
+        }
+
+    return ((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) + 1 + page;
+    }
+
+
+TBool CAknCharMap::HasPictoInterface() const
+    {
+    return (iPictoInterface != NULL);
+    }
+
+TBool CAknCharMap::SwitchTablesL(TBool& aLayoutChanged)
+    {
+    aLayoutChanged = EFalse;
+
+    TBool result(EFalse);
+
+    if (iPictoInterface)
+        {
+        TInt oldVisibleRows = Min(iRows, iExtension->iMaxVisibleRows);
+
+        iChaMapTableCase = (iChaMapTableCase!=EAknCharMapTableSpecialChar) ? EAknCharMapTableSpecialChar : EAknCharMapTablePicto;
+        iCaseIndex = 0;
+
+        // In case picto, char case must be kept same as previous value.
+        TInt charcase = (iChaMapTableCase==EAknCharMapTableSpecialChar) ? iSpecialCharCases[iCaseIndex] : iSpecialCharCase;
+        SetCharacterCaseL(charcase);
+
+        TInt visibleRows = Min(iRows, iExtension->iMaxVisibleRows);
+
+        // Return also information whether the layout changed or not.
+        aLayoutChanged = (oldVisibleRows != visibleRows);
+
+        if (!AknLayoutUtils::PenEnabled())
+            {
+            UpdateScrollIndicatorL();
+            }
+        else
+            {
+            UpdateInputFieldL();
+            }
+
+        if (aLayoutChanged)
+            {
+            // If the number of the visible row is changed,
+            // it is necessary to re-create the background.
+            CreateOffscreenBackgroundL();
+            }
+
+        result = ETrue;
+        }
+    else
+        {
+        result = SwitchSctAndEmotionL();
+        }
+
+    return result;
+    }
+
+void CAknCharMap::CreateOffscreenBackgroundL()
+    {
+	
+    }
+
+TInt CAknCharMap::NextPageL()
+    {
+    HandleFocusStatusChanged(EFalse);
+    
+    TInt page(0);
+    iFirstVisibleRow =
+        (((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) + 1)
+                                                    * iExtension->iMaxVisibleRows;
+    if (iFirstVisibleRow > VisibleRows())
+        {
+        iFirstVisibleRow = 0;
+
+        if(iFirstVisibleRow == 0 &&
+        ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+          (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) )
+            {
+            iCursorPos = TPoint(0, 1);
+            }
+        else
+            {
+            iCursorPos = TPoint(0, 0);
+            }
+
+        page = SwitchAnotherTableL(1);
+        }
+    else
+        {
+        if(iFirstVisibleRow == 0 &&
+        ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+          (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) )
+            {
+            iCursorPos = TPoint(0, 1);
+            }
+        else
+            {
+            iCursorPos = TPoint(0, 0);
+            }
+
+        }
+    UpdateHeadingPane( ETrue );
+    UpdateScrollIndicatorL();
+    HandleFocusStatusChanged();
+    DrawNow();
+
+    return page;
+    }
+
+TInt CAknCharMap::PrevPageL()
+    {
+    HandleFocusStatusChanged(EFalse);
+    
+    TInt page(0);
+    TInt firstVisibleRow =
+        (((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) - 1) *
+            iExtension->iMaxVisibleRows;
+    if (firstVisibleRow < 0)
+        {
+        SwitchAnotherTableL(-1);
+        iFirstVisibleRow = ((*iShowPagesRef)[iCaseIndex] - 1 ) * iExtension->iMaxVisibleRows;
+        if(iFirstVisibleRow == 0 &&
+            ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+              (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) )
+            {
+            iCursorPos = TPoint(0, 1);
+            }
+        else
+            {
+            iCursorPos = TPoint(0, 0);
+            }
+        }
+    else
+        {
+        iFirstVisibleRow = firstVisibleRow;
+        if(iFirstVisibleRow == 0 &&
+            ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+              (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) )
+            {
+            iCursorPos = TPoint(0, 1);
+            }
+        else
+            {
+            iCursorPos = TPoint(0, 0);
+            }
+        }
+    UpdateHeadingPane( ETrue );
+    UpdateScrollIndicatorL();
+    HandleFocusStatusChanged();
+    DrawNow();
+
+    return page;
+    }
+
+HBufC* CAknCharMap::AppendTextL(HBufC* aChars, HBufC* aText)
+    {
+    if (!aChars)
+        {
+        return aText;
+        }
+
+    aChars = aChars->ReAllocL(aChars->Length() + aText->Length());
+    aChars->Des().Append(aText->Des());
+    delete aText;
+
+    return aChars;
+    }
+
+void CAknCharMap::DrawPicto(
+    CWindowGc& aGc,
+    const TRect& aSctPosition,
+    TInt aCharIndex,
+    TBool aHighlighted,
+    TBool aDrawBackground ) const
+    {
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+    if (aHighlighted)
+        {
+        //aGc.SetPenColor(AKN_LAF_COLOR(215));
+        TRgb color = AKN_LAF_COLOR(215);
+        AknsUtils::GetCachedColor( skin, color,
+            KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 );
+        aGc.SetPenColor(color);
+        if (!IsRecentChar(aCharIndex))
+            {
+            aGc.DrawRect( aSctPosition );
+            }
+
+        // Shrink by one pixel in all directions.
+        TRect innerRect = aSctPosition;
+        if (!IsRecentChar(aCharIndex))
+            {
+            innerRect.Shrink(1,1);
+            }
+
+
+        color = AKN_LAF_COLOR(210);
+        AknsUtils::GetCachedColor(skin,color,
+            KAknsIIDQsnHighlightColors,EAknsCIQsnHighlightColorsCG1);
+        aGc.SetBrushColor(color);
+        aGc.Clear( innerRect );
+        }
+
+    // Draw the background of the item if requested
+    else if ( aDrawBackground )
+        {
+		aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+		aGc.SetBrushColor(AKN_LAF_COLOR(0));
+
+		TRect innerRect = aSctPosition;
+		if (IsRecentChar(aCharIndex))
+			{
+			innerRect.Shrink(1,1);
+			}
+		aGc.Clear( innerRect );
+        }
+    if (iPictoInterface->Interface()->IsPictograph((*iChars)[aCharIndex]))
+        {
+        if (iExtension->iPictographsBufferGrouping)
+            {
+            TAknPictographDrawingMode drawingMode =
+                aHighlighted?EDrawingModeWhite:EDrawingModeNormal;
+            iPictoInterface->Interface()->SetPictographDrawingMode(drawingMode);
+            }
+        iPictoInterface->Interface()->DrawPictograph(
+            aGc,
+            aSctPosition,
+            (*iChars)[aCharIndex],
+            iCurrentPictographHeight );
+        }
+    }
+
+void CAknCharMap::DrawOffscreenBackgroundIfRequired() const
+    {
+	
+    }
+
+EXPORT_C CCoeControl* CAknCharMap::ComponentControl(TInt aIndex) const
+    {
+    if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
+        {
+        if ( aIndex == 0 )
+            {
+            return iSBFrame->VerticalScrollBar();
+            }
+        aIndex--;
+        }
+
+    if (iExtension->iRadioButton)
+        {
+         if ( aIndex == 0 )
+            {
+            return iExtension->iRadioButton;
+            }
+        aIndex--;
+        }
+
+    if (iExtension->iCategoryTitle)
+        {
+        if ( aIndex == 0 )
+            {
+            return iExtension->iCategoryTitle;
+            }
+        aIndex--;
+        }
+    if (iExtension->iCategoryEntry)
+        {
+        if ( aIndex == 0 )
+            {
+            return iExtension->iCategoryEntry;
+            }
+        aIndex--;
+        }
+
+    if (iExtension->iTableNavi)
+        {
+         if ( aIndex == 0 )
+            {
+            return iExtension->iTableNavi;
+            }
+        aIndex--;
+        }
+    if (iExtension->iPageNavi)
+        {
+         if ( aIndex == 0 )
+            {
+            return iExtension->iPageNavi;
+            }
+        aIndex--;
+        }
+
+    return NULL;
+    }
+
+EXPORT_C TInt CAknCharMap::CountComponentControls() const
+    {
+    TInt num = 0;
+    if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
+        {
+        num++;
+        }
+    if (iExtension->iRadioButton)
+        {
+        num++;
+        }
+    if (iExtension->iCategoryTitle)
+        {
+        num++;
+        }
+    if (iExtension->iCategoryEntry)
+        {
+        num++;
+        }
+    if (iExtension->iTableNavi)
+        {
+        num++;
+        }
+    if (iExtension->iPageNavi)
+        {
+        num++;
+        }
+    return num;
+    }
+
+void CAknCharMap::SetPictoMode(TAknCharMapPictoMode aMode)
+    {
+    if (aMode == EAknCharMapPictoNoUse)
+        {
+        delete iPictoInterface;
+        iPictoInterface = NULL;
+        }
+    else if (aMode == EAknCharMapPictoFirst)
+        {
+        iChaMapTableCase = EAknCharMapTablePicto;
+        }
+    }
+
+void CAknCharMap::SetCaseTableL(const RArray<TInt> & aCase)
+    {
+
+    // set current case characters to display on SCT
+    HBufC* currentcasechars = iCharsBufferLower;
+    if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase)
+        currentcasechars = iCharsBufferUpper;
+    else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric)
+        currentcasechars = iCharsBufferNumeric;
+    else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase)
+        currentcasechars = iCharsBufferFull;
+    else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase)
+        currentcasechars = iCharsBufferHalf;
+    else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty)
+        currentcasechars = iExtension->iCharsQwerty;
+
+    iSpecialCharPages.AppendL( PageCountFromChars(*currentcasechars) );
+
+    iSpecialCharCases.AppendL( iSpecialCharCase );
+    if (iExtension->iRadioButton)
+        {
+        // Set the sct case mode to valid
+        iExtension->iRadioButton->SetValidSctCase(iSpecialCharCase);
+        }
+
+    if (aCase.Count() > 0)
+        {
+        for (TInt i(0); i < aCase.Count(); ++i)
+            {
+            HBufC* chars = CharsFromCase(aCase[i]);
+            if (chars)
+                {
+                iSpecialCharCases.AppendL( aCase[i] );
+                iSpecialCharPages.AppendL( PageCountFromChars(*chars) );
+                if (iExtension->iRadioButton)
+                    {
+                    // Set the sct case mode to valid
+                    iExtension->iRadioButton->SetValidSctCase(aCase[i]);
+                    }
+                }
+            }
+        }
+
+    if (iExtension->iPictographsBuffer && iPictoInterface)
+        {
+        __ASSERT_ALWAYS(
+            iPictoInterface->Interface(), Panic(EAknPanicNullPointer));
+
+        iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer) );
+        iPictographCases.AppendL(EAknCharMapTablePicto);
+        if (iExtension->iPictographsBufferGrouping)
+            {
+            iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer2) );
+            iPictographCases.AppendL(EAknCharMapTablePicto2);
+            if (iExtension->iRadioButton)
+                {
+                // Set the sct case mode to valid
+                iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph1);
+                iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph2);
+                }
+            }
+        else
+            {
+            if (iExtension->iRadioButton)
+                {
+                // Set the sct case mode to valid
+                iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph);
+                }
+            }
+        }
+
+    if (iExtension->iRadioButton)
+        {
+        // Remove invalid category buttons
+        iExtension->iRadioButton->RemoveInvalidButton();
+        __ASSERT_DEBUG( iExtension->iRadioButton->Count() > 0,
+            Panic(EAknPanicInvalidValue));
+        }
+    }
+
+void CAknCharMap::SetTitleL(TPtrC aTitle)
+    {
+    iTitleDefault = HBufC::NewL(aTitle.Length());
+    iTitleDefault->Des().Copy(aTitle);
+
+    HBufC* title;
+    if (iExtension->iPictographsBufferGrouping)
+        {
+        title = StringLoader::LoadLC(
+            R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH1, iCoeEnv);
+        iTitlePicto = HBufC::NewL(title->Length());
+        iTitlePicto->Des().Copy(*title);
+        CleanupStack::PopAndDestroy(title); // title
+
+        title = StringLoader::LoadLC(
+            R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH2, iCoeEnv);
+        iTitlePicto2 = HBufC::NewL(title->Length());
+        iTitlePicto2->Des().Copy(*title);
+        CleanupStack::PopAndDestroy(title); // title
+        }
+    else
+        {
+        title = StringLoader::LoadLC(
+            R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH, iCoeEnv);
+        iTitlePicto = HBufC::NewL(title->Length());
+        iTitlePicto->Des().Copy(*title);
+        CleanupStack::PopAndDestroy(title); // title
+        // Picto2 isn't used.
+        iTitlePicto2 = NULL;
+        }
+
+    title = StringLoader::LoadLC(
+        R_AVKON_SPECIAL_CHARACTERS_HALF_SYMBOL, iCoeEnv);
+    iTitleHalf = HBufC::NewL(title->Length());
+    iTitleHalf->Des().Copy(*title);
+    CleanupStack::PopAndDestroy(); // title
+
+    title = StringLoader::LoadLC(
+        R_AVKON_SPECIAL_CHARACTERS_FULL_SYMBOL, iCoeEnv);
+    iTitleFull = HBufC::NewL(title->Length());
+    iTitleFull->Des().Copy(*title);
+    CleanupStack::PopAndDestroy(); // title
+    }
+
+const TDesC* CAknCharMap::Title() const
+    {
+    HBufC* title = iTitleDefault;
+    if (iChaMapTableCase == EAknCharMapTableSpecialChar)
+        {
+        if (iSpecialCharCase == EAknSCTHalfCase)
+            {
+            title = iTitleHalf;
+            }
+        if (iSpecialCharCase == EAknSCTFullCase)
+            {
+            title = iTitleFull;
+            }
+        }
+    else
+        {
+        if (iCaseIndex == 1)
+            {
+            title = iTitlePicto2;
+            }
+        else
+            {
+            title = iTitlePicto;
+            }
+        }
+    return title;
+    }
+
+TInt CAknCharMap::SwitchAnotherTableL(TInt aIncrement)
+    {
+    TInt page(0);
+    if (iShowCasesRef->Count() > 1)
+        {
+        iCaseIndex += aIncrement;
+        if (iShowCasesRef->Count() - 1 < iCaseIndex)
+            {
+            iCaseIndex = 0;
+            }
+        if (iCaseIndex < 0)
+            {
+            iCaseIndex = iShowCasesRef->Count() - 1;
+            }
+        SetCharacterCaseL((*iShowCasesRef)[iCaseIndex]);
+        page = PageCount();
+        }
+    return page;
+    }
+
+void CAknCharMap::CountMaxColumnsAndCellSizes()
+    {
+    TRect mainPaneRect;
+    if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct)
+        {
+        if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect))
+            {
+            mainPaneRect = iAvkonAppUi->ClientRect();
+            }
+
+        TAknLayoutScalableParameterLimits charMapDialogVariety =
+            AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits();
+
+        TInt maxVariety = charMapDialogVariety.LastVariety();
+
+        AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation();
+        TInt maxVarietyOffset = 0;
+        TInt varietyOffset = maxVariety + 1;
+        if(Layout_Meta_Data::IsLandscapeOrientation())
+            {
+            varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections;
+            }
+
+        if(location == AknLayoutUtils::EAknCbaLocationRight)
+            {
+            maxVarietyOffset = varietyOffset;
+            }
+        else if(location == AknLayoutUtils::EAknCbaLocationLeft)
+            {
+            maxVarietyOffset = varietyOffset + varietyOffset;
+            }
+
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(mainPaneRect,
+            AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVarietyOffset));
+
+        TAknLayoutRect gridWithScrollLayRect;
+        gridWithScrollLayRect.LayoutRect(popupGridLayRect.Rect(),
+            AknLayoutScalable_Avkon::listscroll_popup_graphic_pane());
+
+
+        TAknLayoutRect gridLayRect;
+        if (iExtension->iHasCategoryButtonUi)
+            {
+            gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic_popup_pane(2));
+            }
+        else
+            {
+            gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(),
+                AknLayoutScalable_Avkon::grid_graphic_popup_pane(0));
+            }
+
+        TRect gridRect = Extension()->iMenuSct ? Rect(): gridLayRect.Rect();
+
+        TAknLayoutRect firstCellLayRect;
+        firstCellLayRect.LayoutRect(gridRect,
+            AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,0,0));
+
+        TRect firstCellRect;
+        if ( Extension()->iMenuSct )
+            {
+            firstCellRect = TRect( TPoint(0, 0),
+                 TSize( firstCellLayRect.Rect().Width(), Rect().Height() ) );
+            }
+        else
+            {
+            firstCellRect = firstCellLayRect.Rect();
+            }
+
+        TAknLayoutRect rightCellLayRect;
+        rightCellLayRect.LayoutRect(gridRect,
+            AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,1,0));
+
+        TInt firstVisibleIndex = iFirstVisibleRow * iMaxColumns;
+        // Max columns.
+        iMaxColumns = gridRect.Width() / firstCellRect.Width();
+        iFirstVisibleRow = firstVisibleIndex / iMaxColumns;
+
+        // Max visible rows.
+        iExtension->iMaxVisibleRows = gridRect.Height() / firstCellRect.Height();
+
+        // Cell width.
+        iGridItemWidth =
+            rightCellLayRect.Rect().iTl.iX - firstCellLayRect.Rect().iTl.iX;
+        if (iGridItemWidth < 0)
+            {
+            iGridItemWidth = -iGridItemWidth;
+            }
+
+        // Cell height.
+        if ( Extension()->iMenuSct )
+            {
+            iGridItemHeight = firstCellRect.Height();
+            }
+        else
+            {
+            TAknLayoutRect downCellLayRect;
+            downCellLayRect.LayoutRect(gridRect,
+                AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,0,1));
+            iGridItemHeight =
+                downCellLayRect.Rect().iTl.iY - firstCellLayRect.Rect().iTl.iY;
+            }
+        }
+    else
+        {
+        TAknLayoutRect popupGridLayRect;
+        popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(),
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window(0));
+
+        TRect popupGridRect = popupGridLayRect.Rect();
+
+        TInt gridVariety;
+        if (!IsJapaneseSctUi())
+            {
+            if(!Layout_Meta_Data::IsLandscapeOrientation())
+                {
+                gridVariety = (TableCount() > 1) ? 0 : 1;
+                }
+            else
+                {
+                gridVariety = (TableCount() > 1) ? 2 : 3;
+                }
+            }
+        else
+            {
+            gridVariety = !Layout_Meta_Data::IsLandscapeOrientation() ? 4 : 5;
+            }
+
+        TAknLayoutRect gridLayRect;
+        gridLayRect.LayoutRect(popupGridRect,
+            AknLayoutScalable_Avkon::grid_graphic2_pane(gridVariety));
+
+        TRect gridRect = gridLayRect.Rect();
+
+        TAknLayoutRect firstCellLayRect;
+        firstCellLayRect.LayoutRect(popupGridRect,
+            AknLayoutScalable_Avkon::aid_size_cell_graphic2(gridVariety,0,0));
+
+        TRect firstCellRect = firstCellLayRect.Rect();
+        TInt firstVisibleIndex = iFirstVisibleRow * iMaxColumns;
+
+        // Max columns.
+        iMaxColumns = gridRect.Width() / firstCellRect.Width();
+        iFirstVisibleRow = firstVisibleIndex / iMaxColumns;
+
+        // Max visible rows.
+        iExtension->iMaxVisibleRows = gridRect.Height() / firstCellRect.Height();
+
+        // Cell width.
+        iGridItemWidth = firstCellRect.Width();
+
+        // Cell height.
+        iGridItemHeight = firstCellRect.Height();
+        }
+    }
+
+HBufC* CAknCharMap::CharsFromCase(TInt aCharCase) const
+    {
+   __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidValue));
+
+    HBufC* chars = NULL;
+    switch (aCharCase)
+        {
+        case EAknSCTLowerCase:
+            chars = iCharsBufferLower;
+            break;
+        case EAknSCTUpperCase:
+            chars = iCharsBufferUpper;
+            break;
+        case EAknSCTNumeric:
+            chars = iCharsBufferNumeric;
+            break;
+        case EAknSCTFullCase:
+            chars = iCharsBufferFull;
+            break;
+        case EAknSCTHalfCase:
+            chars = iCharsBufferHalf;
+            break;
+        case EAknSCTQwerty:
+             chars = iExtension->iCharsQwerty;
+            break;
+        default:
+            break;
+        }
+    return chars;
+    }
+
+TInt CAknCharMap::PageCountFromChars(TDesC& aChars) const
+    {
+    TInt page(aChars.Length() / (iExtension->iMaxVisibleRows * iMaxColumns));
+    if ((page * (iExtension->iMaxVisibleRows * iMaxColumns)) != aChars.Length())
+        {
+        page++;
+        }
+    return page;
+    }
+
+TInt CAknCharMap::VisibleRows() const
+    {
+    TInt count((*iShowPagesRef)[iCaseIndex] - 1);
+    return count * iExtension->iMaxVisibleRows;
+    }
+
+void CAknCharMap::CreatePictoCharL()
+    {
+    if (!iExtension->iPictographsBuffer)
+        {
+        return;
+        }
+
+    delete iPictographsBuffer;
+    iPictographsBuffer = NULL;
+    delete iPictographsBuffer2;
+    iPictographsBuffer2 = NULL;
+    delete iPictoInterface;
+    iPictoInterface = NULL;
+
+    iPictoInterface = CAknPictographInterface::NewL(*this, *this);
+    if (iPictoInterface)
+        {
+        __ASSERT_ALWAYS(iFont, Panic(EAknPanicNullPointer));
+        iCurrentPictographHeight = EHeight16;
+        iPictoInterface->Interface()->SelectPictographHeightForFont(*iFont,iCurrentPictographHeight);
+        }
+
+    // set pictograph characters
+    if (iExtension->iPictographsBufferGrouping)
+        {
+        for (TInt index=0; index < 2; index++)
+            {
+            PictograhGrouping::TAknPictographGroupType type =
+                ( index == 0 )? PictograhGrouping::TAknPictographGroup1
+                                : PictograhGrouping::TAknPictographGroup2;
+            // get pictograph characters
+            HBufC* temp = PictograhGrouping::AllocStringLC(type);
+            HBufC* buf = HBufC::NewL(temp->Length());
+            TPtr ptr(buf->Des());
+            ptr.Append(*temp);
+            CleanupStack::PopAndDestroy(temp); // temp
+
+            if ( index == 0 )
+                {
+                iPictographsBuffer = buf;
+                }
+            else
+                {
+                iPictographsBuffer2 = buf;
+                }
+            }
+        }
+    else if ( iPictoInterface )
+        {
+        // get pictograph characters
+        HBufC* temp =
+            iPictoInterface->Interface()->SupportedPictographCodesL();
+        CleanupStack::PushL(temp);
+
+        iPictographsBuffer = HBufC::NewL(temp->Length());
+        TPtr ptr = iPictographsBuffer->Des();
+        ptr.Append(*temp);
+        CleanupStack::PopAndDestroy(temp); // temp
+
+        // picto2 is not used.
+        iPictographsBuffer2 = NULL;
+        }
+
+    // EFalse is set to iSetRecentPic variable when setting special
+    // characters from resouce.
+    iSetRecentPic = EFalse;
+    }
+
+//--------------------------------------------------------------------------
+// void CAknCharMap::HandlePointerEventL()
+// The function works in two different ways. First (1), if the pointer is set
+// down or dragged the "focus" shall either move to it or follow the pointer.
+// Second (2) when the pointer is lifted the char below the pointer is set in
+// to the array in which all the special characters are placed by the normal
+// (rocker) method.
+//--------------------------------------------------------------------------
+EXPORT_C void CAknCharMap::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    if ( AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition))
+        {
+        if (iExtension->iFocusHandler->FocusedControl() != this)// Tapping will move focus to grid.
+            {
+            iExtension->iFocusHandler->LeaveControl();
+            iExtension->iFocusHandler = iExtension;
+            }
+
+        TInt newGridX; // For the whole
+        TInt newGridY; // For the whole grid.
+        TInt yInPixels = aPointerEvent.iPosition.iY - iGridTopLeft.iY;
+        newGridY = yInPixels / iGridItemHeight;
+
+        newGridX = -1;
+
+        if ( iIsMirrored )
+            {
+            TInt topRight = iGridTopLeft.iX - ( iMaxColumns - 1 ) * iGridItemWidth;
+            TInt topLeft = iGridTopLeft.iX + iGridItemWidth;
+            if ( ( aPointerEvent.iPosition.iX > topRight ) &&
+                ( aPointerEvent.iPosition.iX < topLeft ) )
+                {
+                newGridX = ( topLeft - aPointerEvent.iPosition.iX ) / iGridItemWidth;
+                }
+            }
+        else if ((aPointerEvent.iPosition.iX - iGridTopLeft.iX) > 0)
+            {
+            newGridX = (aPointerEvent.iPosition.iX - iGridTopLeft.iX) / iGridItemWidth;
+            }
+
+        // The pointer has been set down or dragged into the area of the grid. (it might be in
+        // the "white space" at the end of the grid)
+        if ((yInPixels >= 0 && yInPixels < iGridItemHeight * iExtension->iMaxVisibleRows) &&
+            // When the pointer is in rows except the recent character row
+            ((((newGridY + iFirstVisibleRow) != 0) && newGridX < iMaxColumns && newGridX >= 0) ||
+            // When the pointer is in the recent character row
+            ( (newGridY + iFirstVisibleRow == 0) && (newGridX< LengthOfRecentChar()))) )
+            {
+            // For any action to be taken, the pointer event must either be a Button1Down or a drag event
+            // which has originated from a Button1Down in to the grid.
+            if (iExtension->iFlags&EAknCharMapHasBeenScrolledByDrag ||
+                aPointerEvent.iType == TPointerEvent::EButton1Down  ||
+                iExtension->iFlags&EAknCharMapButton1DownInGrid)
+                {
+                if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+                    {
+                    iExtension->iSelectAllowed = ETrue; // enable selection.
+                    }
+                iExtension->iFlags |= EAknCharMapButton1DownInGrid;
+                TUint globalY = newGridY + iFirstVisibleRow;
+                if (iChars->Length() > globalY * iMaxColumns + newGridX)
+                    {
+                    if (aPointerEvent.iType == TPointerEvent::EButton1Down ||
+                        aPointerEvent.iType == TPointerEvent::EDrag)
+                        {
+                        if (iCursorPos.iX+(iCursorPos.iY+iFirstVisibleRow)*iMaxColumns < iChars->Length())
+                            {
+                            iOldCursorPos = iCursorPos;
+                            }
+                        else
+                            {
+                            iOldCursorPos.iX = 0;
+                            iOldCursorPos.iY = 0;
+                            }
+
+                        iCursorPos.iY = newGridY;
+                        iCursorPos.iX = newGridX;
+
+                        if( iExtension->iSingleClickEnabled && 
+                            iExtension->iHighlightVisible &&
+                            aPointerEvent.iType == TPointerEvent::EDrag )
+                            {
+                            TInt focusPos = iCursorPos.iX + ( iFirstVisibleRow + 
+                                    iCursorPos.iY ) * iMaxColumns;
+                            TInt oldFocusPos = iOldCursorPos.iX + (
+                                    iFirstVisibleRow + 
+                                    iOldCursorPos.iY ) * iMaxColumns;
+                            if ( focusPos != oldFocusPos )
+                                {
+                                iExtension->iHighlightVisible = EFalse;
+                                iExtension->iSelectAllowed = EFalse;
+                                }
+                            }
+                        
+                        if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+                            {
+                            iExtension->iFlags |= EAknCharMapPressedDown;
+                            }
+                        else if ( iOldCursorPos != iCursorPos )
+                            {
+                            iExtension->iFlags &= (~EAknCharMapPressedDown);
+                            }
+                                
+                        // down event on an item, play feedback
+                        MTouchFeedback* feedback = MTouchFeedback::Instance();
+                        if ( feedback &&
+                             aPointerEvent.iType == TPointerEvent::EButton1Down )
+                            {
+                            feedback->InstantFeedback( this, ETouchFeedbackList );
+                            }
+                        if ( aPointerEvent.iType == TPointerEvent::EDrag &&
+                             iCursorPos != iOldCursorPos )
+                            {
+                            // Disable selection.
+                            iExtension->iSelectAllowed = EFalse;
+
+                            if ( iExtension->iKineticScrolling )
+                                {
+                                // Don't allow changing the item by dragging.
+                                iCursorPos = iOldCursorPos;
+                                }
+                            }
+
+                        if( aPointerEvent.iType == TPointerEvent::EButton1Down )
+                            {
+                            if( iExtension->iSingleClickEnabled )
+                                {
+                                iExtension->iHighlightVisible = ETrue;
+                                }
+                        
+                            HandleFocusStatusChanged();
+                            }
+                        
+                        DrawCursor();
+                        }
+                    else if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+                        {
+                        // Observe that selection has been changed, so char map dialog can get
+                        // selected char, add it to text and close.
+                        if (iExtension->iObserver &&
+                            iExtension->iFlags & EAknCharMapPressedDown)
+                            {
+                            iStatusChanged =
+                                iExtension->iSelectAllowed ?
+                                    EAknCharSelectedSpecialCharacter : EAknCharNoSelection;
+                            // up event hit the same item that was selected by down event,
+                            // play feedback
+                            MTouchFeedback* feedback = MTouchFeedback::Instance();
+                            if ( feedback )
+                                {
+                                feedback->InstantFeedback( this, 
+                                                           ETouchFeedbackList,
+                                                           ETouchFeedbackVibra,
+                                                           TPointerEvent() );
+                                }
+
+                            iExtension->iObserver->HandleControlEventL(
+                                this, MCoeControlObserver::EEventStateChanged);
+                            }
+                        }
+                    }
+                // The user tapped on a cell which does not have item. Remove highlight
+                else if ( iExtension->iSingleClickEnabled ) 
+                    {
+                    iExtension->iHighlightVisible = EFalse;
+                    DrawCursor();
+                    }
+                }
+            }
+        else if ( iExtension->iSingleClickEnabled )
+            {
+            iExtension->iHighlightVisible = EFalse;
+            DrawCursor();
+            }
+			
+        CCoeControl::HandlePointerEventL(aPointerEvent);
+
+        // if Stylus is lifted we clear all flags.
+        if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+            {
+            iExtension->iFlags &= (~EAknCharMapButton1DownInGrid);
+            iExtension->iFlags &= (~EAknCharMapHasBeenScrolledByDrag);
+            iExtension->iFlags &= (~EAknCharMapPressedDown);
+            if ( !iSBFrame )
+                {
+                return;
+                }
+            CEikScrollBar* vScrollBar = iSBFrame->VerticalScrollBar();
+            if(vScrollBar)
+                {
+                vScrollBar->HandlePointerEventL(aPointerEvent);
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::SetObserver
+// Sets the observer.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CAknCharMap::SetObserver( MCoeControlObserver* aObserver  )
+    {
+    if (iExtension)
+        {
+        iExtension->iObserver = aObserver;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::HandleScrollEventL
+// Handles the different scroll events so that the map reacts accordingly.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::HandleScrollEventL(
+    CEikScrollBar* aScrollBar,
+    TEikScrollEvent aEventType)
+    {
+    TBool update = EFalse;
+
+    switch (aEventType)
+        {
+        case EEikScrollUp:
+        case EEikScrollPageUp:
+            {
+            // nothing done if we are already on the first page.
+            if (iFirstVisibleRow != 0)
+                {
+                iFirstVisibleRow -= iExtension->iMaxVisibleRows;
+                update = ETrue;
+                }
+            if(iFirstVisibleRow == 0 &&
+            ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+              (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) )
+                {
+                iCursorPos = TPoint(0, 1);
+                }
+            else
+                {
+                iCursorPos = TPoint(0, 0);
+                }
+
+            UpdateHeadingPane( ETrue );
+            UpdateScrollIndicatorL();
+            }
+        break;
+        case EEikScrollDown:
+        case EEikScrollPageDown:
+            {
+            // nothing done if we are already on the last page.
+            if (iFirstVisibleRow != (PageCount() -1 ) * iExtension->iMaxVisibleRows)
+                {
+                iFirstVisibleRow += iExtension->iMaxVisibleRows;
+                update = ETrue;
+                }
+            iCursorPos = TPoint(0, 0);
+            UpdateHeadingPane( ETrue );
+            UpdateScrollIndicatorL();
+            }
+        break;
+        case EEikScrollThumbDragVert:
+            {
+            TInt thumbPosition;
+            TInt halfPage = iExtension->iMaxVisibleRows/2;
+            // Ask which type of scrollbar is shown
+            CAknAppUi* appUi = iAvkonAppUi;
+            TBool isDoubleSpan =
+                CEikScrollBarFrame::EDoubleSpan == iSBFrame->TypeOfVScrollBar();
+            if (isDoubleSpan)
+                {
+                thumbPosition =
+                    static_cast <const TAknDoubleSpanScrollBarModel*>
+                        (aScrollBar->Model())->FocusPosition();
+                }
+            else
+                {
+                thumbPosition = aScrollBar->Model()->iThumbPosition;
+                }
+
+            // If the slider is in the range of less then a half page from a possible correct thumb position.
+            // thus 0 <= iFirstVisibleRow - thumbPosition < halfPage. Or in the other direction:
+            // 0 <= thumbPosition - iFirstVisibleRow < halfPage
+            if (!((0 <= iFirstVisibleRow - thumbPosition &&
+                        iFirstVisibleRow - thumbPosition < halfPage )||
+                  (0 <= thumbPosition - iFirstVisibleRow &&
+                        thumbPosition - iFirstVisibleRow < halfPage)))
+                {
+                TReal toRound = thumbPosition/(TReal)iExtension->iMaxVisibleRows;
+                if (toRound * 2 > (TInt)toRound * 2 + 1)
+                    {
+                    toRound++;
+                    }
+                iFirstVisibleRow = (TInt)toRound * iExtension->iMaxVisibleRows;
+                if(iFirstVisibleRow == 0 &&
+                ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || 
+                  (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) )
+                    {
+                    iCursorPos = TPoint(0, 1);
+                    }
+                else
+                    {
+                    iCursorPos = TPoint(0, 0);
+                    }
+                UpdateHeadingPane( EFalse );
+                update = ETrue;
+                }
+            }
+        break;
+        case EEikScrollThumbReleaseVert:
+            {
+            UpdateScrollIndicatorL();
+            }
+        break;
+        case EEikScrollLeft: // flow through
+        case EEikScrollRight: // flow through
+        case EEikScrollPageLeft: // flow through
+        case EEikScrollPageRight: // flow through
+        case EEikScrollThumbDragHoriz: // flow through
+        case EEikScrollThumbReleaseHoriz: // flow through
+            // do nothing
+            break;
+        default:
+            // do nothing
+            break;
+        }
+     // If we have move up to the first page we check the first low is empty or not and
+     // set iCursorPos respective
+    if (iFirstVisibleRow == 0 and iCursorPos.iY == 0)
+        {
+         if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[iCursorPos.iX])) || 
+              (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[iCursorPos.iX]==KHistoryEmptyChar && !Extension()->iMenuSct) )
+            {
+            iCursorPos =  TPoint(iCursorPos.iX, 1);
+            }
+        }
+// If we have moved down to the last page we check that the cursor is in a place where it can be
+// drawn.
+    if (iFirstVisibleRow == (iRows/iExtension->iMaxVisibleRows) * iExtension->iMaxVisibleRows)
+        {
+        // the old cursor is set to a "safe" position where it at least can be.
+        iOldCursorPos.iX = 0;
+        iOldCursorPos.iY = 0;
+        // if the last page has only one line which isn't filled complitely.
+        if (iChars->Length()%iMaxColumns - 1 < iCursorPos.iX && iRows%iExtension->iMaxVisibleRows == 1)
+            {
+            iCursorPos.iX = iChars->Length()%iMaxColumns - 1;
+            }
+        // If the cursor is in a position where it would go unto a spot with out
+        // a character when scrolled.
+        if (iCursorPos.iY + iFirstVisibleRow >= iRows)
+            {
+            if (iChars->Length()%iMaxColumns > iCursorPos.iX)
+                {
+                iCursorPos.iY = iRows - 1 - iFirstVisibleRow;
+                }
+            else
+                {
+                iCursorPos.iY = iRows - 2 - iFirstVisibleRow;
+                }
+            }
+        // If the cursor is actually on the last row, but is still in the
+        // area where there is now chars. (the rest of the last row)
+        if (iChars->Length() <= (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns + iCursorPos.iX && 
+            iCursorPos.iY + iFirstVisibleRow + 1 == iRows)
+            {
+            iCursorPos.iY--;
+            }
+        // if the corrections did not help and the cursor is in the area
+        // where there is a valid row, but no chars anymore
+        }
+
+    // to avoid flicker we draw only if there really was something new to draw.
+    if (update)
+        {
+        if (iExtension->iObserver)
+            {
+            iExtension->iObserver->HandleControlEventL(this, MCoeControlObserver::EEventRequestFocus);
+            }
+        
+        HandleFocusStatusChanged();
+        DrawDeferred();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::AppendRecentCharL()
+// Append the recent data to SCT/Picto data
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::AppendRecentCharL()
+    {
+    __ASSERT_ALWAYS( iCharMapHistory, Panic(EAknPanicInvalidValue));
+    __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidValue));
+    
+    if(iSetRecentSct) return;
+
+    for (TInt index=0; index < 8; index++ )
+        {
+        
+        CAknCharMapHistory::THistoryType historyType = CAknCharMapHistory::EHistoryTypeNull;
+        HBufC** charsBuf = NULL;
+
+        switch (index)
+            {
+            case 0:
+                historyType = CAknCharMapHistory::EHistoryTypeFull;
+                charsBuf = &iCharsBufferFull;
+                break;
+            case 1:
+                historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                charsBuf = &iCharsBufferHalf;
+                break;
+            case 2:
+                historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                charsBuf = &iCharsBufferLower;
+                break;
+            case 3:
+                historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                charsBuf = &iCharsBufferUpper;
+                break;
+            case 4:
+                historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                charsBuf = &iCharsBufferNumeric;
+                break;
+            case 5:
+                historyType = CAknCharMapHistory::EHistoryTypePicto;
+                charsBuf = &iPictographsBuffer;
+                break;
+            case 6:
+                historyType = CAknCharMapHistory::EHistoryTypePicto2;
+                charsBuf = &iPictographsBuffer2;
+                break;
+            case 7:
+                historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                charsBuf = &iExtension->iCharsQwerty;
+                break;
+            default:
+                break;
+            }
+        
+        TPtrC textHistory = iCharMapHistory->RecentString(historyType, CAknCharMapHistory::EHistoryFilterTextOnly);
+        
+        *charsBuf = InsertSwitchCharAndHistoryToCharsBufL(*charsBuf, 
+                                                          TEmotionUtils::EmotionSwitchToSmileyChar(), 
+                                                          textHistory);
+        }
+    
+    // Emotion history
+    TPtrC emotionHistory = iCharMapHistory->RecentString(CAknCharMapHistory::EHistoryTypeFull, CAknCharMapHistory::EHistoryFilterEmotionOnly);
+    iExtension->iCharsSmiley = InsertSwitchCharAndHistoryToCharsBufL(iExtension->iCharsSmiley, 
+                                                                     TEmotionUtils::EmotionSwitchToSctChar(), 
+                                                                     emotionHistory);
+
+    // ETrue are set to each variable when setting the recent used characters.
+    iSetRecentSct = ETrue;
+    iSetRecentPic = ETrue;
+    }
+
+HBufC* CAknCharMap::InsertSwitchCharAndHistoryToCharsBufL(HBufC* aCharsBuf, TChar aSwitchChar, const TDesC& aHistory)
+    {
+    if (aCharsBuf)
+        {
+        // Check whether recent charcters are included in base charcters.
+        TBuf<CAknCharMapHistory::KHistoryBufferSize+5> insertBuffer;
+        for (TInt index=0; index<aHistory.Length(); index++)
+            {
+            TChar txt = aHistory[index];
+            if(aCharsBuf->Locate(txt)!=KErrNotFound || TEmotionUtils::IsEmotionChar(txt) || txt==KHistoryEmptyChar)
+                {
+                insertBuffer.Append(txt);
+                }
+            }
+
+        while(insertBuffer.Length() < iMaxColumns)  // empty history stuff
+            {
+            insertBuffer.Append(KHistoryEmptyChar);
+            }
+        
+        insertBuffer.SetLength(iMaxColumns);        // max length is one line
+        
+        // Emotion switch char
+        if(Extension()->NeedEmotionSwitchIcon())
+            {
+            insertBuffer.Append(aSwitchChar);
+            }
+
+        // insert to des buffer
+        TInt charsLength = insertBuffer.Length() + aCharsBuf->Length(); // history + Emotion swich char + text
+        aCharsBuf = aCharsBuf->ReAllocL(charsLength);
+        aCharsBuf->Des().Insert(0, insertBuffer);                       // history
+        }
+
+    return aCharsBuf;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::IsRecentChar()
+// Check whether the character(of index) is recent data, or not
+// The default value of first argument is 0.
+// -----------------------------------------------------------------------------
+//
+TBool CAknCharMap::IsRecentChar(TInt aIndex /*=0*/) const
+    {
+    TBool rtn = EFalse;
+    if (iCharMapHistory)
+        {
+        switch (iChaMapTableCase)
+            {
+            case EAknCharMapTableSpecialChar:
+                switch (iSpecialCharCase)
+                    {
+                    case EAknSCTHalfCase:
+                    case EAknSCTLowerCase:
+                    case EAknSCTUpperCase:
+                    case EAknSCTNumeric:
+                    case EAknSCTQwerty:
+                    case EAknSCTFullCase:
+                        if (aIndex<iMaxColumns && iSetRecentSct)
+                            {
+                            rtn = ETrue;
+                            }
+                        break;
+                    default:
+                        break;
+                    }
+                break;
+            case EAknCharMapTablePicto:
+            case EAknCharMapTablePicto2:
+                if (aIndex<iMaxColumns && iSetRecentSct)
+                    {
+                    rtn = ETrue;
+                    }
+                break;
+            default:
+                break;
+            }
+        }
+    return rtn;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMapHistory::SaveRecentDataL()
+// Save the recent data
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::SaveRecentDataL(TChar aChar)
+    {
+    __ASSERT_ALWAYS( iCharMapHistory, Panic(EAknPanicInvalidValue));
+
+    CAknCharMapHistory::THistoryType historyType = CAknCharMapHistory::EHistoryTypeNull;
+
+    switch (iChaMapTableCase)
+        {
+        case EAknCharMapTableSpecialChar:
+            switch (iSpecialCharCase)
+                {
+                case EAknSCTHalfCase:
+                case EAknSCTLowerCase:
+                case EAknSCTUpperCase:
+                case EAknSCTNumeric:
+                case EAknSCTQwerty:
+                    historyType = CAknCharMapHistory::EHistoryTypeHalf;
+                    break;
+                case EAknSCTFullCase:
+                    historyType = CAknCharMapHistory::EHistoryTypeFull;
+                    break;
+                default:
+                    break;
+                }
+            break;
+            
+        case EAknCharMapTablePicto:
+        case EAknCharMapTablePicto2:
+            historyType = (iCaseIndex==0) ? CAknCharMapHistory::EHistoryTypePicto : CAknCharMapHistory::EHistoryTypePicto2;
+            break;
+            
+        default:
+            break;
+        }
+    
+    if (historyType > CAknCharMapHistory::EHistoryTypeNull)
+        {
+        iCharMapHistory->InsertChar(historyType, aChar);
+        }
+
+    // Save recent data
+    iCharMapHistory->SaveL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::ConstructMenuSctRowL()
+// Constructs the SCT for editing menu.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CAknCharMap::ConstructMenuSctRowL()
+    {
+    Extension()->iMenuSct = ETrue;
+    TResourceReader reader;
+
+    TInt resourceId = R_AVKON_MENU_SCT_ROW_DEFAULT_CONTENTS;
+    if (FeatureManager::FeatureSupported(KFeatureIdChinese))
+        {
+        resourceId = R_AVKON_MENU_SCT_ROW_DEFAULT_CONTENTS_CHINESE;
+        }
+
+    CCoeEnv::Static()->CreateResourceReaderLC( reader, resourceId );
+    ConstructFromResourceL( reader );
+    CleanupStack::PopAndDestroy();
+    }
+
+
+EXPORT_C void CAknCharMap::ConstructMenuSctRowL(TInt aResourceId)
+    {
+    Extension()->iMenuSct = ETrue;
+    Extension()->iMenuSctHighlighted = ETrue;
+    TResourceReader reader;
+    CCoeEnv::Static()->CreateResourceReaderLC( reader,
+                                aResourceId );
+    ConstructFromResourceL( reader );
+    CleanupStack::PopAndDestroy();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::ConstructMenuSctRowFromDialogL()
+// Constructs the SCT for editing menu from the set resource.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CAknCharMap::ConstructMenuSctRowFromDialogL(TInt aResourceId)
+    {
+    Extension()->iMenuSct = ETrue;
+    Extension()->iMenuSctHighlighted = ETrue;
+
+    CEikDialog* dialog = new(ELeave) CEikDialog();
+    dialog->ReadResourceLC(aResourceId);
+    CAknCharMap* charmapControl = STATIC_CAST(CAknCharMap*, dialog->Control(EAknSCTQueryContentId));
+
+    // the code below emulates ConstructFromResourceL(), but gets value from charmapControl
+    CopyCharactersL(*charmapControl);     // replaces ReadCharSetFromResourceL()
+    CleanupStack::PopAndDestroy(dialog);
+    TBuf<32> fileName(KResFileName);
+    TInt langcode= iAvkonEnv->SettingCache().InputLanguage();
+    if (langcode < 10)
+        {
+        fileName.Append('0');
+        }
+    fileName.AppendNum(langcode);
+    TResourceReader reader;
+    RFs& fs = iEikonEnv->FsSession();
+    if ( BaflUtils::FileExists(fs, fileName) )
+        {
+        RResourceFile resourceFile;
+        resourceFile.OpenL( fs, fileName );
+        CleanupClosePushL( resourceFile ); // push
+        resourceFile.ConfirmSignatureL( 0 );
+        if ( resourceFile.OwnsResourceId(aResourceId) )
+            {
+            HBufC8* resource=
+                resourceFile.AllocReadLC(aResourceId); // push
+            reader.SetBuffer(resource);
+            TBuf<32> specialChars;
+            CAknCharMapDialog* langDialog =
+                new( ELeave ) CAknCharMapDialog(
+                    EAknSCTLowerCase, specialChars );
+            CleanupStack::PushL( langDialog ); // push
+            langDialog->CreateWindowL();
+            langDialog->ConstructFromResourceL(reader);
+            CAknCharMap* langMap = STATIC_CAST( CAknCharMap*,
+                langDialog->Control( EAknSCTQueryContentId ) );
+            CopyCharactersL( *langMap );
+            CleanupStack::PopAndDestroy(2); // langDialog, resource
+            }
+        CleanupStack::PopAndDestroy(); // resourcefile
+        }
+
+    if ( iExtension->iPictographsBuffer )
+        {
+        CreatePictoCharL();
+        }
+
+    if (!iCharMapHistory)
+        {
+        iCharMapHistory = CAknCharMapHistory::NewL();
+        iSetRecentSct = ETrue;
+        iSetRecentPic = ETrue;
+        }
+
+    if ( iExtension->iPictographsBuffer )
+        {
+        CreateOffscreenBackgroundL();
+        }
+
+    delete iExtension->iBgContext;
+    iExtension->iBgContext = NULL;
+
+    if ( DrawableWindow() && AknLayoutUtils::PenEnabled() )
+        {
+        EnableDragEvents();
+        SetGloballyCapturing( ETrue );
+        SetPointerCapture( ETrue );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::HighlightSctRow()
+// Highlight the row of recent used character according to argument.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CAknCharMap::HighlightSctRow(TBool aHighlight)
+    {
+    // If the row is empty, nothing to do
+    if (LengthOfRecentChar() == 0)
+        {
+        return;
+        }
+    
+    HandleFocusStatusChanged(aHighlight);
+    
+    CWindowGc& gc = SystemGc();
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        ActivateGc();
+        gc.UseFont(iFont);
+        }
+
+    TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    DrawCell( cursorPos, aHighlight );
+
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        gc.DiscardFont();
+        DeactivateGc();
+        }
+    // Menu SCT is being used.
+    if ( Extension()->iMenuSct )
+    	{
+    	Extension()->iMenuSctHighlighted = aHighlight;
+    	}
+    }
+// -----------------------------------------------------------------------------
+// CAknCharMap::SetMenuSctRect()
+// Sets the rect for menu SCT.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CAknCharMap::SetMenuSctRect( const TRect& aRect )
+    {
+    
+    if(Rect() == aRect) return;
+    
+    SetRect( aRect );
+
+    if ( !iIsMirrored )
+        {
+        iGridTopLeft = aRect.iTl;
+        iOffset.iX = aRect.iTl.iX + 1;
+        iOffset.iY = aRect.iTl.iY + 1;
+        }
+    else
+        {
+        iGridTopLeft.iX = aRect.iBr.iX;
+        iGridTopLeft.iY = aRect.iTl.iY;
+        iOffset.iX = aRect.iTl.iX + 1;
+        iOffset.iY = aRect.iTl.iY + 1;
+        }
+
+
+    DoLayout();
+    
+    if (iCharMapHistory)
+        {
+        CAknCharMapHistory::THistoryType charmap = CAknCharMapHistory::EHistoryTypeNull;
+        
+        switch (iSpecialCharCase)
+            {
+            case 0: // lower
+                charmap = CAknCharMapHistory::EHistoryTypeHalf;
+                break;
+            case 1: // upper
+                charmap = CAknCharMapHistory::EHistoryTypeHalf;
+                break;
+            case 2: // numeric
+                charmap = CAknCharMapHistory::EHistoryTypeHalf;
+                break;
+            case 3: // full
+                charmap = CAknCharMapHistory::EHistoryTypeFull;
+                break;
+            case 4: // half
+                charmap = CAknCharMapHistory::EHistoryTypeHalf;
+                break;
+            case 5: // qwerty
+                charmap = CAknCharMapHistory::EHistoryTypeHalf;
+                break;
+            case 6: // picto
+                charmap = CAknCharMapHistory::EHistoryTypePicto;
+                break;
+            case 7: // picto 2
+                charmap = CAknCharMapHistory::EHistoryTypePicto2;
+                break;
+            default:
+                break;
+            }
+        
+        CAknCharMapHistory::THistoryFilter historyFilter;
+        if(iExtension->IsEmotionEnabled())
+            {
+            historyFilter = CAknCharMapHistory::EHistoryFilterMixed;
+            }
+        else
+            {
+            historyFilter = CAknCharMapHistory::EHistoryFilterTextOnly;
+            }
+        
+        const TDesC& recentChars = iCharMapHistory->RecentString(charmap, historyFilter);
+        
+        // if iChars already contains HBufC, delete iChars and reset ichars
+        if (iExtension->iFlags & EAknCharMapCharsAllocated)
+            {
+            delete iChars;
+            iChars = NULL;
+            if (iChaMapTableCase != EAknCharMapTableSpecialChar)
+                {
+                if (iCaseIndex == 1)
+                    {
+                    iChars = iPictographsBuffer2;
+                    }
+                else
+                    {
+                    iChars = iPictographsBuffer;
+                    }
+                iShowCasesRef = &iPictographCases;
+                iShowPagesRef = &iPictographPages;
+                }
+            else
+                {
+                iShowCasesRef = &iSpecialCharCases;
+                iShowPagesRef = &iSpecialCharPages;
+                iChars = iCharsBufferLower;
+                if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase)
+                    iChars = iCharsBufferUpper;
+                else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric)
+                    iChars = iCharsBufferNumeric;
+                else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase)
+                    iChars = iCharsBufferFull;
+                else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase)
+                    iChars = iCharsBufferHalf;
+                else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty)
+                    iChars = iExtension->iCharsQwerty;
+
+                if(iChars == iCharsBufferLower)
+                    {
+                    iSpecialCharCase = EAknSCTLowerCase;
+                    }
+                }
+            // mark that iChars doesn't point to HBufC
+            iExtension->iFlags &= (~EAknCharMapCharsAllocated);
+            }
+        iRows = 1;
+        TPtrC realChars = iChars->Des(); // get only the SCT chars
+
+        // Check whether recent charcters are included in base charcters.
+        HBufC* newrecent = HBufC::New(recentChars.Length());
+        if( newrecent == NULL)
+            {
+            return;
+            }
+
+        TPtr ptrrecent(newrecent->Des());
+        ptrrecent.Copy(recentChars);
+        for (TInt index=0; index < ptrrecent.Length(); index++)
+            {
+            if (ptrrecent[index] != KHistoryEmptyChar)
+                {
+                if(TEmotionUtils::IsEmotionChar(ptrrecent[index]))
+                    {
+                    continue;
+                    }
+                else
+                    {
+                    TInt err = realChars.Locate(ptrrecent[index]);
+                    if (err == KErrNotFound)
+                        {
+                        ptrrecent.Delete(index,1);
+                        ptrrecent.Append(KHistoryEmptyChar);
+                        index--;
+                        }                       
+                    }
+                }
+            }
+        if (iExtension->iFlags & EAknCharMapCharsAllocated) // iChars already contains HBufC
+            {                                               // so delete old instance
+            delete iChars;
+            iChars = NULL;
+            }
+
+        iChars = newrecent;
+        iChars->Des().SetLength(iMaxColumns);
+        if (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)
+            {
+            iCursorPos = TPoint(0, 1);
+            }
+        if (iCursorPos.iX >= iMaxColumns)
+            {
+            iCursorPos = TPoint(0, 0);
+            }
+        iExtension->iFlags |= EAknCharMapCharsAllocated; // mark that iChars points to HBufC
+        }
+    
+    iExtension->LoadEmotionTumbnails(*iChars);
+
+    HandleFocusStatusChanged();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::CharacterCase()
+// Get current character case.
+// -----------------------------------------------------------------------------
+//
+TInt CAknCharMap::CharacterCase()
+    {
+    return iSpecialCharCase;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::DisableRecentCharsRow()
+// Hides the first row that shows recent characters.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::DisableRecentCharsRow()
+    {
+    if(!iSetRecentSct) return;
+    
+    iSetRecentSct = EFalse;
+    iSetRecentPic = EFalse;
+    
+    TInt insertedLength = iMaxColumns;
+    
+    // Emotion switch char
+    if(Extension()->NeedEmotionSwitchIcon())
+        {
+        insertedLength++;
+        }
+
+    for (TInt index=0; index < 8; index++ )
+        {
+        HBufC** base = NULL;
+        
+        switch (index)
+            {
+            case 0:
+                base = &iCharsBufferFull;
+                break;
+            case 1:
+                base = &iCharsBufferHalf;
+                break;
+            case 2:
+                base = &iCharsBufferLower;
+                break;
+            case 3:
+                base = &iCharsBufferUpper;
+                break;
+            case 4:
+                base = &iCharsBufferNumeric;
+                break;
+            case 5:
+                base = &iPictographsBuffer;
+                break;
+            case 6:
+                base = &iExtension->iCharsQwerty;
+                break;
+            case 7:
+                base = &iPictographsBuffer2;
+                break;
+            default:
+                break;
+            }
+        
+        if (*base)
+            {
+            // Remove recent characters from the beginning.
+            // Length of removed characters is iMaxColumns
+            (*base)->Des().Delete(0, insertedLength);
+            }
+        }
+    
+    // delete Emotion history
+    iExtension->iCharsSmiley->Des().Delete(0, insertedLength);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::Extension
+// Asserts that extension object has been created.
+// -----------------------------------------------------------------------------
+//
+CAknCharMapExtension* CAknCharMap::Extension() const
+    {
+    __ASSERT_ALWAYS( iExtension, Panic( EAknPanicNullPointer ) );
+    return iExtension;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::UpdateHeadingPane
+// Updates page number and title in Heading Pane.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::UpdateHeadingPane( TBool aUpdateTitle )
+    {
+    if (iExtension->iObserver &&
+        !AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct)
+        {
+        CAknCharMapDialog* dialog =
+            static_cast<CAknCharMapDialog*>(iExtension->iObserver );
+        CAknPopupHeadingPane* headingPane =
+            static_cast< CAknPopupHeadingPane* >
+                (dialog-> Control( EAknSCTQueryHeadingId ) );
+
+        if ( headingPane )
+            {
+            TRAP_IGNORE(
+                {
+                // Update heading pane's page number
+                headingPane->SetPageL( CurrentPage(), PageCount() );
+
+                // Update also title if requested
+                if ( aUpdateTitle)
+                    {
+                    const TDesC* title = (IsJapaneseSctUi())?
+                                         TitleWithSelectingSpecialChar()
+                                         :Title();
+                    if ( title )
+                        {
+                        //
+                        headingPane->SetTextL( *title );
+                        }
+                    }
+                } );
+            }
+        }
+    }
+
+
+
+
+void CAknCharMap::SetStatusChanged(const TInt aStatusChanged)
+    {
+    iStatusChanged = aStatusChanged;
+    if (iExtension->iObserver)
+        {
+        TRAP_IGNORE( iExtension->iObserver->HandleControlEventL(this, MCoeControlObserver::EEventStateChanged) );
+        }
+    }
+
+TInt CAknCharMap::StatusChanged()
+    {
+    return iStatusChanged;
+    }
+
+TInt CAknCharMap::CurrentCategory()
+    {
+    return iExtension->iCurrentCategory;
+    }
+
+TInt CAknCharMap::Category()
+    {
+    TInt category = EAknSCTCategoryButtonHalfCase;
+    if (iChaMapTableCase == EAknCharMapTableSpecialChar)
+        {
+        if (iSpecialCharCase == EAknSCTFullCase)
+            {
+            category = EAknSCTCategoryButtonFullCase;
+            }
+        }
+    else
+        {
+        if (iExtension->iPictographsBufferGrouping)
+            {
+            category = (iCaseIndex == 1) ?
+                EAknSCTCategoryButtonPicto2 : EAknSCTCategoryButtonPicto1;
+            }
+        else
+            {
+            category = EAknSCTCategoryButtonPicto;
+            }
+        }
+    return category;
+    }
+
+/**
+ * Change to new category
+ */
+TBool CAknCharMap::ChangeCategoryL(const TInt aCategory, TBool& aLayoutChanged)
+    {
+    TBool result(ETrue);
+
+    aLayoutChanged = EFalse;
+
+    TInt oldVisibleRows = iRows;
+    if (oldVisibleRows > iExtension->iMaxVisibleRows)
+        {
+        oldVisibleRows = iExtension->iMaxVisibleRows;
+        }
+
+    switch (aCategory)
+        {
+        case EAknSCTCategoryButtonHalfCase:
+            iChaMapTableCase = EAknCharMapTableSpecialChar;
+            SetCharacterCaseL(EAknSCTHalfCase);
+            break;
+        case EAknSCTCategoryButtonFullCase:
+            iChaMapTableCase = EAknCharMapTableSpecialChar;
+            SetCharacterCaseL(EAknSCTFullCase);
+            break;
+        case EAknSCTCategoryButtonPicto:
+            iChaMapTableCase = EAknCharMapTablePicto;
+            iCaseIndex = 0;
+            SetCharacterCaseL(iSpecialCharCase);
+            break;
+        case EAknSCTCategoryButtonPicto1:
+            iChaMapTableCase = EAknCharMapTablePicto;
+            iCaseIndex = 0;
+            SetCharacterCaseL(iSpecialCharCase);
+            break;
+        case EAknSCTCategoryButtonPicto2:
+            iChaMapTableCase = EAknCharMapTablePicto;
+            iCaseIndex = 1;
+            SetCharacterCaseL(iSpecialCharCase);
+            break;
+        default:
+            Panic(EAknPanicOutOfRange);
+            break;
+        }
+
+    TInt visibleRows = iRows;
+    if (visibleRows > iExtension->iMaxVisibleRows)
+        {
+        visibleRows = iExtension->iMaxVisibleRows;
+        }
+
+    // Return also information whether the layout changed or not.
+    aLayoutChanged = ( oldVisibleRows != visibleRows );
+
+    UpdateScrollIndicatorL();
+
+    UpdateInputFieldL();
+
+    RefreshNaviPageL();
+
+    if (aLayoutChanged)
+        {
+        // If the number of the visible row is changed,
+        // it is necessary to re-create the background.
+        CreateOffscreenBackgroundL();
+        }
+    return result;
+    }
+
+
+TBool CAknCharMap::IsSupportCategoryButtonUi() const
+    {
+    return (iExtension)? iExtension->iHasCategoryButtonUi : EFalse;
+    }
+
+TBool CAknCharMap::IsJapaneseSctUi() const
+    {
+    return (iExtension)? iExtension->iJapaneseSctUi : EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::TitleWithSelectingSpecialChar()
+// Return the title string with the selecting special characters
+// -----------------------------------------------------------------------------
+//
+
+const TDesC* CAknCharMap::TitleWithSelectingSpecialChar()
+    {
+    const TDesC* title = Title();
+    TRAPD(err, CreateTitleWithSelectingSpecialCharL(title));
+    if (err != KErrNone)
+        {
+        return title;
+        }
+    else
+        {
+        return Extension()->iTitleBuf;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::ChangeFocusSct()
+// Change the current focus either Grid or Category buttons
+// If aFocusOn is EFalse, from Grid to Category buttons,
+// If aFocusOn is ETrue, from Category buttons to Grid
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::ChangeFocusSct(TBool aFocusOn)
+    {
+    CWindowGc& gc = SystemGc();
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        ActivateGc();
+        gc.UseFont(iFont);
+        }
+
+    TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    DrawCell( cursorPos, aFocusOn );
+
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        gc.DiscardFont();
+        DeactivateGc();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknCharMap::CreateTitleWithSelectingSpecialCharL()
+// Create the string mixing title and the selecting special characters,
+// and Set it to Extension()->iTitleBuf.
+// -----------------------------------------------------------------------------
+//
+void CAknCharMap::CreateTitleWithSelectingSpecialCharL(const TDesC* aTitle)
+    {
+    const TDesC* title = aTitle;
+    if ( title )
+        {
+        if (!AknLayoutUtils::PenEnabled())
+            {
+            CAknCharMapDialog* dialog =
+                static_cast<CAknCharMapDialog*>(iExtension->iObserver);
+            CAknPopupHeadingPane* headingPane =
+                static_cast<CAknPopupHeadingPane*>(
+                    dialog->Control(EAknSCTQueryHeadingId));
+            if (Extension()->iTitleBuf)
+                {
+                delete Extension()->iTitleBuf;
+                Extension()->iTitleBuf =NULL;
+                }
+            Extension()->iTitleBuf =
+                HBufC::NewL(title->Length() + iFetcherCharsBuffer->Length());
+            TPtr titlePtr(Extension()->iTitleBuf->Des());
+            HBufC* tempBuf = iFetcherCharsBuffer->AllocLC();
+            TPtr tempPtr(tempBuf->Des());
+
+            CCoeControl* titleCtrl = (CCoeControl*)headingPane->Prompt();
+            TRect promptRect = titleCtrl->Rect();
+
+            TInt varietyIndex = (AknLayoutUtils::PenEnabled())? 3 : 1;
+            TAknTextComponentLayout textLayout =
+                AknLayoutScalable_Avkon::heading_pane_t1(varietyIndex);
+
+            TRect parentRect;
+            TAknLayoutRect popupRect;
+            if(!AknLayoutUtils::LayoutMetricsRect(
+                AknLayoutUtils::EPopupParent, parentRect))
+                {
+                parentRect = iAvkonAppUi->ClientRect();
+                }
+            popupRect.LayoutRect(parentRect,
+                AknLayoutScalable_Avkon::popup_window_general(1));
+
+            TAknLayoutRect headingRect;
+            TAknWindowComponentLayout headingPaneLayout =
+                AknLayoutScalable_Avkon::heading_pane(0);
+            headingRect.LayoutRect(TRect(TPoint(0,0),
+                popupRect.Rect().Size()), headingPaneLayout);
+            parentRect = headingRect.Rect();
+
+            TAknLayoutText textRect;
+            textRect.LayoutText(parentRect, textLayout);
+            TInt controlWidth = textRect.TextRect().Width();
+
+            const CFont* promptFont =
+                AknLayoutUtils::FontFromId( textLayout.Font() );
+
+            TInt titleWidth = promptFont->TextWidthInPixels(*title);
+            TInt textWidth = promptFont->TextWidthInPixels(tempPtr);
+            FOREVER
+                {
+                if (titleWidth >= controlWidth)
+                    {
+                    titlePtr.Append(*title);
+                    break;
+                    }
+                if (controlWidth >= (titleWidth + textWidth))
+                    {
+                    titlePtr.Append(*title);
+                    titlePtr.Append(tempPtr);
+                    break;
+                    }
+                if (tempPtr.Length() > 1)
+                    {
+                    tempPtr.Delete(0,1);
+                    tempPtr[0] = CEditableText::EEllipsis;
+                    textWidth = promptFont->TextWidthInPixels(tempPtr);
+                    }
+                else
+                    {
+                    titleWidth = controlWidth + 1;
+                    }
+                }
+            CleanupStack::PopAndDestroy(tempBuf);
+            }
+        }
+    }
+
+void CAknCharMap::RefreshNaviPageL()
+    {
+    if (iExtension->iPageNavi)
+        {
+        iExtension->iPageNavi->UpdatePageTitleL();
+        }
+    }
+
+TAknChaMapTableCase CAknCharMap::NextTableCase() const
+    {
+    return EAknCharMapTableSpecialChar; // Currently no other maps supported.
+    }
+
+MAknSctFocusHandler* CAknCharMap::FocusHandler()
+    {
+    return iExtension->iFocusHandler;
+    }
+
+CCoeControl* CAknCharMap::FocusedControl()
+    {
+    return this;
+    }
+
+TBool CAknCharMap::EnterControl(TInt aX, TInt aY)
+    {
+    if ((aY < 0) || (aY >= iExtension->iMaxVisibleRows))
+        {
+        return EFalse; // Out of grid.
+        }
+
+    if ((aX < 0) || (aX >= iMaxColumns))
+        {
+        return EFalse; // Out of grid.
+        }
+
+    TInt pos = 0;
+
+    CWindowGc& gc = SystemGc();
+    if(!CAknEnv::Static()->TransparencyEnabled())
+        {
+        ActivateGc();
+        gc.UseFont(iFont);
+        }
+
+    // clear cell
+    pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    DrawCell( pos, EFalse );
+
+    iCursorPos = TPoint(aX, aY); // new pos.
+
+    // highlight cell
+    pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    DrawCell( pos, ETrue );
+
+    UpdateHeadingPane( ETrue );
+
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        gc.DiscardFont();
+        DeactivateGc();
+        }
+
+    return ETrue;
+    }
+
+void CAknCharMap::MoveFocus(TInt aX, TInt aY)
+    {
+    TRAP_IGNORE(MoveCursorL(aX,aY));
+    }
+
+TBool CAknCharMap::LeaveControl()
+    {
+    HandleFocusStatusChanged(EFalse);
+    
+    CWindowGc& gc = SystemGc();
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        ActivateGc();
+        gc.UseFont(iFont);
+        }
+
+    TInt pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns;
+    DrawCell( pos, EFalse );
+
+    if( !CAknEnv::Static()->TransparencyEnabled() )
+        {
+        gc.DiscardFont();
+        DeactivateGc();
+        }
+
+    return ETrue;
+    }
+
+TInt CAknCharMap::TableCount() const
+    {
+    // Numbers of tables excluding pictographs.
+    // there will be sct table and Emotion table(if enabled)
+    return Extension()->IsEmotionEnabled() ? 2 : 1;
+    }
+
+void CAknCharMap::UpdateInputFieldL()
+    {
+    if (!iExtension)
+        {
+        return; // Not ready for updates.
+        }
+
+    TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+
+    // Update title field.
+    const TDesC* title = Title();
+    if (iExtension->iCategoryTitle && title)
+        {
+        iExtension->iCategoryTitle->SetTextL(*title);
+        Window().Invalidate(iExtension->iCategoryTitle->Rect());
+        iExtension->iCategoryTitle->SetBrushStyle(
+            CGraphicsContext::ENullBrush);
+        }
+
+    // Update entry field.
+    if (iExtension->iCategoryEntry &&
+        iFetcherCharsBuffer && iFetcherCharsBuffer->Length()>0)
+        {
+        if (Extension()->iEntryBuf)
+            {
+            delete Extension()->iEntryBuf;
+            Extension()->iEntryBuf =NULL;
+            }
+        Extension()->iEntryBuf =
+            HBufC::NewL(iFetcherCharsBuffer->Length());
+        TPtr entryPtr(Extension()->iEntryBuf->Des());
+
+        HBufC* tempBuf = iFetcherCharsBuffer->AllocLC();
+        TPtr tempPtr(tempBuf->Des());
+
+        TInt variety =
+            Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+        const CFont* entryFont = AknLayoutUtils::FontFromId(
+            AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety).Font());
+        TInt entryWidth = entryFont->TextWidthInPixels(tempPtr);
+
+        TInt controlWidth = Extension()->iCategoryEntry->Size().iWidth;
+
+        FOREVER
+            {
+            if (entryWidth < controlWidth)
+                {
+                entryPtr.Append(tempPtr);
+                break;
+                }
+            if (tempPtr.Length() > 1)
+                {
+                tempPtr.Delete(0,1);
+                tempPtr[0] = CEditableText::EEllipsis;
+                entryWidth = entryFont->TextWidthInPixels(tempPtr);
+                }
+            else
+                {
+                entryWidth = controlWidth + 1;
+                }
+            }
+
+        Extension()->iCategoryEntry->SetTextL(tempPtr);
+        Window().Invalidate(iExtension->iCategoryEntry->Rect());
+        Extension()->iCategoryEntry->SetBrushStyle(
+            CGraphicsContext::ENullBrush);
+
+        CleanupStack::PopAndDestroy(tempBuf);
+        }
+    }
+
+TInt CAknCharMap::RowMin(TInt aRow) const
+    {
+    TInt index = KErrNotFound;
+    if ((aRow >= 0) && (aRow < iExtension->iMaxVisibleRows))
+        {
+        TInt start = (iFirstVisibleRow + aRow) * iMaxColumns;
+        for (TInt i = 0; i < iMaxColumns; i++)
+            {
+            TInt pos = start + i;
+            if ((pos >= 0) && (pos < iChars->Length()))
+                {
+                if ((*iChars)[pos] != KHistoryEmptyChar)
+                    {
+                    index = i; // the first valid cell in the row.
+                    break;
+                    }
+                }
+            }
+        }
+    return index;
+    }
+
+TInt CAknCharMap::RowMax(TInt aRow) const
+    {
+    TInt index = KErrNotFound;
+    if ((aRow >= 0) && (aRow < iExtension->iMaxVisibleRows))
+        {
+        TInt start = (iFirstVisibleRow + aRow) * iMaxColumns;
+        for (TInt i = iMaxColumns - 1; i >= 0; i--)
+            {
+            TInt pos = start + i;
+            if ((pos >= 0) && (pos < iChars->Length()))
+                {
+                if ((*iChars)[pos] != KHistoryEmptyChar)
+                    {
+                    index = i; // the last valid cell in the row.
+                    break;
+                    }
+                }
+            }
+        }
+    return index;
+    }
+
+TInt CAknCharMap::ColMin(TInt aCol) const
+    {
+    TInt index = KErrNotFound;
+    if ((aCol >= 0) && (aCol < iMaxColumns))
+        {
+        TInt start = iFirstVisibleRow * iMaxColumns + aCol;
+        for (TInt i = 0; i < iExtension->iMaxVisibleRows; i++)
+            {
+            TInt pos = start + iMaxColumns * i;
+            if ((pos >= 0) && (pos < iChars->Length()))
+                {
+                if ((*iChars)[pos] != KHistoryEmptyChar)
+                    {
+                    index = i; // the first valid cell in the column.
+                    break;
+                    }
+                }
+            }
+        }
+    return index;
+    }
+
+TInt CAknCharMap::ColMax(TInt aCol) const
+    {
+    TInt index = KErrNotFound;
+    if ((aCol >= 0) && (aCol < iMaxColumns))
+        {
+        TInt start = iFirstVisibleRow * iMaxColumns + aCol;
+        for (TInt i = iExtension->iMaxVisibleRows - 1; i >= 0; i--)
+            {
+            TInt pos = start + iMaxColumns * i;
+            if ((pos >= 0) && (pos < iChars->Length()))
+                {
+                if ((*iChars)[pos] != KHistoryEmptyChar)
+                    {
+                    index = i; // the last valid cell in the column.
+                    break;
+                    }
+                }
+            }
+        }
+    return index;
+    }
+
+TInt CAknCharMap::MaxCols() const
+    {
+    return iMaxColumns;
+    }
+
+TBool CAknCharMap::TakeFocus()
+    {
+    TInt success = EFalse;
+    if (iExtension->iFocusHandler->FocusedControl() != this)
+        {
+        iExtension->iFocusHandler->LeaveControl();
+        iExtension->iFocusHandler = iExtension;
+        success = ETrue;
+        }
+    return success;
+    }
+
+void CAknCharMap::ShowFocus()
+    {
+    ChangeFocusSct(ETrue);
+    }
+
+TPoint CAknCharMap::CursorPos()
+    {
+    return iCursorPos;
+    }
+
+
+// for emotion added
+
+void CAknCharMap::HandleFocusStatusChanged(TBool aIsFocused)
+    {
+    TInt focusPos = iCursorPos.iX + (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns;
+    if(focusPos>=0 && focusPos<iChars->Length())
+        {
+        aIsFocused &= (iExtension->iFocusHandler->FocusedControl()==this);
+        iExtension->HandleFocusStatusChanged((*iChars)[focusPos], aIsFocused);
+        }
+    }
+
+TBool CAknCharMap::EmotionsAreAllReadyToDraw(TInt aIndex, TInt aCount) const
+    {
+    for(TInt i(0); i<aCount; i++)
+        {
+        if(aIndex < iChars->Length())
+            {
+            TChar name = (*iChars)[aIndex++];
+            CSmileyIcon* icon = iExtension->EmotionIcon(name);
+            if(icon && !icon->ReadyToDraw())
+                {
+                return EFalse;
+                }
+            }
+        else
+            {
+            break;
+            }
+        }
+    
+    return ETrue;
+    }
+
+void CAknCharMap::GetFocusSctName(TChar& aChar, TDes& aName) const
+    {
+    TInt pos = iMaxColumns * (iFirstVisibleRow + iCursorPos.iY) + iCursorPos.iX;
+    
+    aChar = (*iChars)[pos];
+    
+    aName.Zero();
+    
+    if(TEmotionUtils::IsEmotionChar(aChar))
+        {
+        CSmileyIcon* icon = iExtension->EmotionIcon(aChar);
+        if ( icon )
+            {
+            aName.Append(icon->Name());
+            }
+        }
+    else
+        {
+        aName.Append(aChar);
+        }
+    }
+
+TBool CAknCharMap::HaveBufferToAppendFocusSct() const
+    {
+    TChar sctChar;
+    TBuf<10> sctName;
+    GetFocusSctName(sctChar, sctName);
+    
+    return ( iFetcherCharsBuffer->Length() + sctName.Length() < iFetcherCharsBuffer->MaxLength() );
+    }
+
+TBool CAknCharMap::AppendFocusSctToDestinationBufferL()
+    {
+    TBool appended = EFalse;
+    
+    TChar sctChar;
+    TBuf<10> sctName;
+    GetFocusSctName(sctChar, sctName);
+
+    if(Extension()->NeedEmotionSwitchIcon() && 
+       (sctChar==TEmotionUtils::EmotionSwitchToSctChar() || sctChar==TEmotionUtils::EmotionSwitchToSmileyChar()))
+        {
+        SwitchSctAndEmotionL();
+        }
+    else if(iFetcherCharsBuffer->Length() + sctName.Length() < iFetcherCharsBuffer->MaxLength())
+        {
+        iFetcherCharsBuffer->Append(sctName);
+
+        if (iCharMapHistory)
+            {
+            SaveRecentDataL(sctChar);
+            }
+        
+        appended = ETrue;
+        }
+    else
+        {
+        return EFalse; // return here
+        }
+        
+    if (!Extension()->iMenuSct)
+        {
+        UpdateHeadingPane( ETrue );
+        }
+    
+    if (iExtension->iCategoryEntry)
+        {
+        iExtension->iCategoryEntry->SetTextL(*iFetcherCharsBuffer);
+        UpdateInputFieldL();
+        }
+
+    return appended;
+
+    }
+
+TBool CAknCharMap::SwitchSctAndEmotionL()
+    {
+    if(Extension()->IsEmotionEnabled())
+        {
+        Extension()->iIsShowingEmotion = !Extension()->IsShowingEmotion();
+        
+        SetCharacterCaseL(iSpecialCharCase);
+        
+        CAknSctTableNavi* tableNavi = Extension()->iTableNavi;
+        if(tableNavi)
+            {
+            tableNavi->UpdateNextTableButtonL();
+            }
+
+        DrawNow();
+        
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+
+//  End of File