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












#include "AknFepCaseManager.h"
#include "AknFepPanic.h"
#include "aknfeppeninputenums.h"

#include <aknfep.rsg>
#include <aknedsts.h>
#include <barsread.h>
#include <jplangutil.h>
#include <AknPictographInterface.h>
#include <AknPictographDrawerInterface.h>
#include <featmgr.h>
#include <PUAcodes.hrh>

const TText KSpaceCharacter=' ';
const TText KInvertedExclamationMarkCharacter = 0x00A1;
const TText KInvertedQuestionMarkCharacter = 0x00BF;

/* Teleca change begin, 18.08.2009 ssal */
const TInt KSBase = 0xac00; // base address for hangul syllables
const TInt KCBase = 0x3131; // base address for hangul compatibility jamo

const TInt KLCount = 19; // count of L-jamos
const TInt KVCount = 21; // count of V-jamos
const TInt KTCount = 28; // count of T-jamos
const TInt KNCount = KVCount * KTCount; // count of V&T-jamo combinations
const TInt KSCount = KLCount * KNCount; // total count of hangul syllables

// Conversion table for hangul compatibility jamo
const TUint16 conversionTableFromCompatibilityJamoToJamo[] = {
0x1100,
0x1101,
0x11AA,
0x1102,
0x11AC,
0x11AD,
0x1103,
0x1104,
0x1105,
0x11B0,
0x11B1,
0x11B2,
0x11B3,
0x11B4,
0x11B5,
0x11B6,
0x1106,
0x1107,
0x1108,
0x11B9,
0x1109,
0x110A,
0x110B,
0x110C,
0x110D,
0x110E,
0x110F,
0x1110,
0x1111,
0x1112,
0x1161,
0x1162,
0x1163,
0x1164,
0x1165,
0x1166,
0x1167,
0x1168,
0x1169,
0x116A,
0x116B,
0x116C,
0x116D,
0x116E,
0x116F,
0x1170,
0x1171,
0x1172,
0x1173,
0x1174,
0x1175,
};

#define KCCount (sizeof(conversionTableFromCompatibilityJamoToJamo) / sizeof(TUint16))
/* Teleca change end, 18.08.2009 ssal */

// 0x2029 is the paragraph seperator. When the user inputs a
// new line character, 0x2029 is inserted.
const TText KParagraphSeperator = 0x2029;
// 0x000A is line feed character 
const TText KLineFeed = 0x000A;

//for chinese unicode ox4E00 to 0x9FA5
const TText KChineseLowerUnicode = 0x4E00;
const TText KChineseUpperUnicode = 0x9FA5;
CAknFepCaseManager* CAknFepCaseManager::NewL(CAknFepManager& aFep)
    {
    CAknFepCaseManager* self = new (ELeave) CAknFepCaseManager(aFep);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(); //self
    return self;
    }


CAknFepCaseManager::~CAknFepCaseManager()
    {
    delete iPictoInterface;
    }




void CAknFepCaseManager::ConfigureCaseStateFromEditorState()
    {
    CAknEdwinState* editorState = iFep.EditorState();
    if (!editorState)
        {
        return;
        }
        
 	iCurrentCase = editorState->CurrentCase();   
    iPreviousCase = editorState->CaseState().PreviousCase();    
        
    SetFixedCase(editorState->Flags() & EAknEditorFlagFixedCase);

    iPreviousCase = iCurrentCase;

  	if (CurrentEditorIsFixedCase())
    	{    
    	SetCurrentCase(editorState->DefaultCase()); 
    	iPreviousCase = iCurrentCase; 
    	__ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
                     AknFepPanic(EAknFepPanicNonPermittedEditorMode));		   	
    	} 
    	
    //determine it based on position 
    UpdateCase(ENullNaviEvent);

    // if still there is no current case set - use the default
    if (!iCurrentCase)
        {
        SetCurrentCase(editorState->DefaultCase());
        if (!IsCasePermitted(iCurrentCase))
            {
            SetCurrentCase(editorState->CurrentCase());
            }
        
        iPreviousCase = iCurrentCase;
        __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
                       AknFepPanic(EAknFepPanicNonPermittedEditorMode));
        }

    // if the current is not allowed stay where we are
    else if (!IsCasePermitted(iCurrentCase))
        {
        if (!iPreviousCase)
            {
            SetCurrentCase(editorState->DefaultCase());
            iPreviousCase = iCurrentCase;
            __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
                           AknFepPanic(EAknFepPanicNonPermittedEditorMode));
            }
        else
            {
            if (IsCasePermitted(iPreviousCase))
                {
                SetCurrentCase(iPreviousCase);
                }
            else
                {
                SetCurrentCase(editorState->DefaultCase());
                iPreviousCase = iCurrentCase;
                __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
                               AknFepPanic(EAknFepPanicNonPermittedEditorMode));
                }    
            }
        }
    }


void CAknFepCaseManager::UpdateCase(TWesternNaviEvent aNaviEvent)
    {
    TBool applyCaseNeeded = ETrue;
    if ( iFep.IsFlagSet(CAknFepManager::EFlagSupressAutoUpdate) )
        {
        return;
        }
    CAknEdwinState* editorState = iFep.EditorState();
    if (!CurrentEditorIsFixedCase() && editorState 
      && editorState->PermittedCases() & EAknEditorTextCase)
        {
        // lets figure out where the cursor will be when the case needs to be checked
        TInt cursorPos = FindCursorPositionAtCaseCheck(aNaviEvent);
        
        if (!(cursorPos == 0 
           && iFep.IsFlagSet(CAknFepManager::EFlagSupressAutoUpdateAtEditorStart) ))
            {
            TInt defaultCase = editorState->DefaultCase();
            if ( cursorPos == 0 && 
               (defaultCase == EAknEditorLowerCase || defaultCase == EAknEditorUpperCase ))
                {
                SetCurrentCase(defaultCase);
                }
            // UPPER CASE : If in upper case & inside sentence, stay in upper.
            else if (!(iCurrentCase == EAknEditorUpperCase && 
                       CapsLockRequired(cursorPos, iCurrentCase) && 
                       aNaviEvent != EBackspaceEvent))
                {
                const TBool textCaseRequired = TextCaseRequired(cursorPos);
                // UPPER CASE : If upper case & inside sentence & backspace event, stay in upper.
                if (!(iCurrentCase == EAknEditorUpperCase && aNaviEvent == EBackspaceEvent &&
                    !textCaseRequired && cursorPos != 0))
                    {
                    // TEXT CASE : set if at start of editor or following a full stop / text case character
                    if (cursorPos == 0 || textCaseRequired)
                        {
                        TInt inputMode = iFep.InputMode();
                        if (iFep.IsChineseInputLanguage() && 
                        	inputMode != ELatin &&
                        	iCurrentCase != EAknEditorLowerCase)
                        {
                        SetCurrentCase(iCurrentCase);
                        }
#ifdef RD_HINDI_PHONETIC_INPUT	
                        
	                    else if(iFep.IsIndicPhoneticInputLanguage())
	                    	{
	                    	if(CurrentCase() != EAknEditorUpperCase)
	                    	    SetCurrentCase(EAknEditorLowerCase);	
	                    	}
#endif
                        else
                        {
                        /* Teleca change begin, 27.08.2008 ssal 
                        	original code:
                        SetCurrentCase(EAknEditorTextCase);	*/
                        
                        if(iFep.IsKoreanInputLanguage() && inputMode == EHangul )
                        	{
                        	SetCurrentCase(EAknEditorLowerCase);	
                        	}
                        else
                        	{
                            SetCurrentCase(EAknEditorTextCase);
                            }
                        /* Teleca change end, 27.08.2008 ssal */
                        }
                        applyCaseNeeded = EFalse;
                        }
                    else // OTHERWISE LOWER
                        {
                        SetCurrentCase(EAknEditorLowerCase);
                        applyCaseNeeded = EFalse;
                        }
                    }
                }
            }
        else
            {
            iFep.ClearFlag(CAknFepManager::EFlagSupressAutoUpdateAtEditorStart);
            }
        }
    if (applyCaseNeeded)
        {
        ApplyCase();
        }
    }


void CAknFepCaseManager::ManualCaseUpdate()
    {
    if (!CurrentEditorIsFixedCase())
        {
        if (IsCasePermitted(iCurrentCase)) 
            {
            DoManualCaseUpdate();
            iFep.ClearFlag(CAknFepManager::EFlagSupressAutoUpdate);
            }
        }
    }


void CAknFepCaseManager::RevertCaseChange()
    {
    if (!CurrentEditorIsFixedCase())
        {
        if (IsCasePermitted(iPreviousCase)) 
            {
            SetCurrentCase(iPreviousCase); 
            }
        }
    }


void CAknFepCaseManager::SetCurrentCase(TInt aCase, TBool aOverrideNumericTest)
    {
    if ( ( iFep.InputMode() == ENumber || iFep.InputMode() == ENativeNumber ) && 
        !aOverrideNumericTest)
        {
        if ( iFep.EditorState() && 
            (iFep.EditorState()->NumericKeymap() == EAknEditorConverterNumberModeKeymap) )
            {
            // Converter number mode keymap for '*' key requires upper case 'E'.
            iCurrentCase = EAknEditorUpperCase;
            }
        else
            {
            // Number mode keymappings for '*' -key uses lower case letters (pw).
            iCurrentCase = EAknEditorLowerCase;
            }
        }
    else
        {
        if ( aCase == ECaseInverseText )
            {
            iCurrentCase = ECaseUpper;
            iInverseCase = ETrue;
            }
        else
            {
            iCurrentCase = aCase;
            iInverseCase = EFalse;
            }
        }
    ApplyCase();
    }


TInt CAknFepCaseManager::CurrentCase() const
    {
    return iCurrentCase;
    }

TBool CAknFepCaseManager::IsAbleChangeCase() const
    {
    TBool isable = ETrue;
    
    CAknEdwinState* editorState = iFep.EditorState();
    if (editorState)
    	{
	    const TInt permittedCases = editorState->PermittedCases();
	    
	    if (permittedCases == EAknEditorUpperCase ||
	        permittedCases == EAknEditorLowerCase )
	        {
	        isable = EFalse;
	        }
	    else if ((editorState->Flags() & EAknEditorFlagForceTransparentFepModes)
	          && iFep.IsChineseInputLanguage())
	        {
	        isable = EFalse;
	        }
	    else if ( editorState->Flags() & EAknEditorFlagFixedCase )
	        {
	        isable = EFalse;
	        }
	    else if (!iFep.InputLanguageSupportsCaseChanges())
	        {
	        isable = EFalse;
	        }
    	}
    else
    	{
    	isable = EFalse;
    	}
    return isable;
    }

CAknFepCaseManager::CAknFepCaseManager(CAknFepManager& aFep) :
    iFep(aFep)
    {
    }


void CAknFepCaseManager::ConstructL()
    {
    // Set text case character set from resource
    TResourceReader reader;
    CCoeEnv::Static()->CreateResourceReaderLC(reader, R_AKNFEP_TEXT_CASE_CHARACTER_SET);
    iTextCaseCharacters=reader.ReadTPtrC();

    // Create PictographInterface
    CCoeControl* control = NULL;
    MAknPictographAnimatorCallBack* callback = NULL;
    iPictoInterface = CAknPictographInterface::NewL(*control,*callback);

    CleanupStack::PopAndDestroy(); // reader*/
    }


TInt CAknFepCaseManager::FindCursorPositionAtCaseCheck(TWesternNaviEvent aNaviEvent)
    {
    TCursorSelection curCursSel;
    iFep.FepAwareTextEditor()->GetCursorSelectionForFep(curCursSel);
    
    TInt docLength = iFep.FepAwareTextEditor()->DocumentLengthForFep();
    TInt returnedPosition = -1;

    TCursorSelection uncommittedText = iFep.UncommittedText();

    switch (aNaviEvent)
        {
        case ENullNaviEvent:
            if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
                {
                returnedPosition = uncommittedText.HigherPos();
                }
            else
                {
                // In case of non-predictive mode, following condition
                // check text is selceted mode or not?
                // In selected mode, character always being inserted
                // anchor position
                if( curCursSel.Length() >0 )
                    {
                    returnedPosition = curCursSel.LowerPos();
                    }
                else
                    {
                    returnedPosition = curCursSel.HigherPos();
                    }
                }
            break;
        case ERightNaviEvent:
            if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
                {
                returnedPosition = uncommittedText.HigherPos();
                }
            else
                {
                if (curCursSel.Length())
                    {
                    returnedPosition = curCursSel.HigherPos();
                    }
                else
                    {
                    if (curCursSel.iCursorPos == docLength)
                        {
                        returnedPosition = 0;
                        }
                    else
                        {
                        returnedPosition = curCursSel.HigherPos() + 1;
                        }
                    }
                }
            break;
        case ELeftNaviEvent:
            if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
                {
                returnedPosition = uncommittedText.LowerPos();
                }
            else
                {
                if (curCursSel.Length())
                    {
                    returnedPosition = curCursSel.LowerPos();
                    }
                else
                    {
                    if (curCursSel.iCursorPos == 0)
                        {
                        returnedPosition = docLength;
                        }
                    else
                        {
                        returnedPosition = curCursSel.LowerPos() - 1;
                        }
                    }
                }
            break;
        case EBackspaceEvent:
            if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
                {
                returnedPosition = uncommittedText.HigherPos();
                }
            else
                {
                if (curCursSel.Length())
                    {
                    returnedPosition = curCursSel.LowerPos();
                    }
                else
                    {
                    returnedPosition = curCursSel.LowerPos() - 1;
                    }
                }
            break;
        default:
            break;
        }

    if (returnedPosition < 0)
        {
        returnedPosition = 0;
        }
    else if (returnedPosition > docLength)
        {
        returnedPosition = docLength;
        }
    return returnedPosition;
    }


TBool CAknFepCaseManager::TextCaseRequired(TInt aCursorPos)
    {
    TBool textCaseRequired = EFalse;
    TInt charPosToCheck = aCursorPos - 1;   
    TChar ch = KSpaceCharacter;
    TBuf<CAknFepManager::ESingleCharacter> editorText;
    TInt nonEnterSpaceCharCount = 0;
    
    if (charPosToCheck >= 0) 
        {
        // Get the character just before the cursor.
        iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
            charPosToCheck, CAknFepManager::ESingleCharacter);
        ch = editorText[0];        
        if ( ch == KInvertedQuestionMarkCharacter || ch == KInvertedExclamationMarkCharacter )
            {
            // Text case is required imediatelly after 'spanich' question and exclamation mark that begins a sentence.
            textCaseRequired = ETrue;        
            }
        // for chinese uncode limit
        if ( ch >= KChineseLowerUnicode && ch<= KChineseUpperUnicode)
        	{
        	textCaseRequired = ETrue; 
        	}
        
        if( ( TUint )ch == KParagraphSeperator || ( TUint )ch == KLineFeed )
            {
            // When we have enter key, we need to decide the case after: 
            // we reach some non space characters (OR)
            // we reach the beginning of the editor
            while (charPosToCheck > 0 && !textCaseRequired)
                {
                charPosToCheck--;
                iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
                    charPosToCheck, CAknFepManager::ESingleCharacter);
                ch = editorText[0];
                
                // IsSpace returns true for ParagraphSeperator.
                if (!(ch.IsSpace() || ch == EKeyEnter) && nonEnterSpaceCharCount <= 1)
                    {
                    if (IsTextCaseCharacter(ch))
                        {
        	            textCaseRequired = ETrue;
                        }
                    break;
                    }
                else 
                	{
                	if(!( ( TUint )ch == KParagraphSeperator || ( TUint )ch == EKeyEnter || ( TUint )ch == KLineFeed ) )
                		{
                		// Incrementing the count if we have
                		// IsSpace() returns True AND
                		// the character is not a ParagraphSeparator or Enter or Line Feed
                		nonEnterSpaceCharCount++;
	                	}
                	if (charPosToCheck <= 0 && !nonEnterSpaceCharCount)
                    	{
                    	//Reached the beginning of the Editor. Text case should be ON
                    	textCaseRequired = ETrue;
                    	}                    	
                	}    	
                }
            charPosToCheck = aCursorPos - 1;
            
           	if (charPosToCheck <= 0 && !nonEnterSpaceCharCount)
           	    {
           	    // If Enter is pressed as the first character. Text case is ON
                textCaseRequired = ETrue;
                }                    	
            
        	}

        /* Teleca change begin, 27.08.2008 ssal */	
        if (IsKoreanCharacter(ch))
        	{
        	textCaseRequired = ETrue;       
        	}
        /* Teleca change end, 27.08.2008 ssal */
        }


    if (charPosToCheck > 0 && !textCaseRequired) 
        {
        if (iFep.IsFeatureSupportedJapanese())
            {
            // The character case is changed to text case when the left side
            // character is Japanese character.
            if (IsJapaneseCharacter(ch))
                {
                textCaseRequired = ETrue;
                }
            else if (ch.IsSpace() || ch == EKeyEnter ||
                     ch == (TUint)KPuaCodeSpaceSymbol)
                {
                while (charPosToCheck > 0)
                    {
                    charPosToCheck--;
                    // Get the character before the previous character.
                    iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
                        charPosToCheck, CAknFepManager::ESingleCharacter);
                    ch = editorText[0];
                    if (!(ch.IsSpace() || ch == EKeyEnter || ch == (TUint)KPuaCodeSpaceSymbol))
                        {
                        if (IsTextCaseCharacter(ch))
                            {
                            // One space between the cursor and the punctuation character => text case needed
                            textCaseRequired = ETrue;
                            }
                        break;
                        }
                    else if (charPosToCheck <= 0)
                        {
                        // reached the start of the editor => text case needed
                        textCaseRequired = ETrue;
                        }
                    }
                }
            }
        else
            {
            if ( charPosToCheck > 0 && !textCaseRequired && !nonEnterSpaceCharCount) 
			    {        
			    if ( ch.IsSpace() || ch == EKeyEnter || 
			    	ch == ( TUint )KPuaCodeSpaceSymbol )
			        {
			        while ( charPosToCheck > 0 )
			            {
			            charPosToCheck--;
			            
			            // Get the character before the previous character.
			            iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
			                charPosToCheck, CAknFepManager::ESingleCharacter);
			                
			            ch = editorText[0];
			            
			            // This condition is added to keep Text case ON when space is
			            // entered after a "New line" character.
			            if( ( TUint )ch == KParagraphSeperator )
			            	{			            	
			            	textCaseRequired = ETrue;
			            	break;
			            	}
			            	
			            if ( !( ch == EKeyEnter || 
			            		ch == ( TUint )KPuaCodeSpaceSymbol ) )
			                {
			                if ( IsTextCaseCharacter( ch ) )
			                    {			                    
			                    textCaseRequired = ETrue;
			                    }
			                break;
			                }
			            else if ( charPosToCheck <= 0 )
			                {
			                // reached the start of the editor => text case needed
			                textCaseRequired = ETrue;
			                }
			            }
                    }
                }
            }
        }
    else if (charPosToCheck < 0)
        {
        // reached the start of the editor => text case needed
        textCaseRequired = ETrue;
        }
    else    // if (charPosToCheck == 0)
        {
        if (!textCaseRequired && iFep.IsFeatureSupportedJapanese())
            {
            if (IsJapaneseCharacter(ch)
             || ch.IsSpace()
             || ch == EKeyEnter
             || ch == (TUint)KPuaCodeSpaceSymbol)
                {
                // reached the start of the editor => text case needed
                textCaseRequired = ETrue;
                }
            }
        }

    return textCaseRequired;
    }


TBool CAknFepCaseManager::CapsLockRequired(TInt aCursorPos, TInt aCurCase)
    {
    TBool capsLocked = iForceUpperCase;
    TInt charPosToCheck = aCursorPos - 1;   
    TChar ch = KSpaceCharacter;
    TBuf<CAknFepManager::ESingleCharacter> editorText;
    
    // is the previous character alphabetical?
    if (charPosToCheck >= 0) 
        {
        iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
            charPosToCheck, CAknFepManager::ESingleCharacter);
        if( editorText.Length()>0 )
            {
            ch = editorText[0];
            }
            
        if (IsAlpha(ch) ||
            ((aCurCase == EAknEditorUpperCase || aCurCase == ECaseInverseText) && 
             !TextCaseRequired(aCursorPos)))
            {
            // Caps lock (upper case mode) is kept up if we are currently in upper case mode
            // and previous character is alpha character or for example full stop. 
            // If the cursor and full stop is separated with space, text case is restored. 
            capsLocked = ETrue;
            }
        }
    
    return capsLocked;
    }


void CAknFepCaseManager::DoManualCaseUpdate()
    {
    TBool applyCaseNeeded = ETrue;
    iPreviousCase = iCurrentCase;
    TCursorSelection currentSelection;
    iFep.FepAwareTextEditor()->GetCursorSelectionForFep(currentSelection);

    switch (iCurrentCase)
        {
        case EAknEditorLowerCase:
            if (CapsLockRequired(currentSelection.iCursorPos, iCurrentCase) 
             && IsCasePermitted(EAknEditorUpperCase))
                {
                SetCurrentCase(EAknEditorUpperCase);
                }
            else if (!IsCasePermitted(EAknEditorTextCase) 
#ifdef RD_HINDI_PHONETIC_INPUT	
            
            || iFep.IsIndicPhoneticInputLanguage()
#endif            
            )
                {
                if( IsCasePermitted(EAknEditorUpperCase) )
                    SetCurrentCase(EAknEditorUpperCase);
                }
            else
                {
                SetCurrentCase(EAknEditorTextCase);
                }
            applyCaseNeeded = EFalse;
            break;
        case EAknEditorTextCase:
             if (iForceUpperCase && IsCasePermitted(EAknEditorUpperCase))
                {
                SetCurrentCase(EAknEditorUpperCase);
                applyCaseNeeded = EFalse;     
                break;          
                }
        case EAknEditorUpperCase:
            SetCurrentCase(EAknEditorLowerCase);
            applyCaseNeeded = EFalse;
            break;
        default:
            break;
        }

    if (!(IsCasePermitted(iCurrentCase)))
        {
        DoManualCaseUpdate();
        }
    else
        {
        if (applyCaseNeeded)
            {
            ApplyCase();
            }
        }
    }


void CAknFepCaseManager::ApplyCase()
    {
    // update engine...
    switch (iCurrentCase)
        {
        case EAknEditorUpperCase: // fall through
        case EAknEditorTextCase:
            iFep.SetCase(EUpperCase);
            break;
        case EAknEditorLowerCase: // fall through
        default:
            iFep.SetCase(ELowerCase);
            break;
        }
    if(iFep.EditorState())
        {
        iFep.EditorState()->SetCurrentCase(iCurrentCase);
        }
    iFep.UpdateIndicators();

#ifdef RD_SCALABLE_UI_V2    
    iFep.UpdateTouchCaseMode();
#endif
    }


void CAknFepCaseManager::SetFixedCase(TBool aFixedCase)
    {
    iFixedCase = aFixedCase;
    }


TBool CAknFepCaseManager::CurrentEditorIsFixedCase() const
    {
    return iFixedCase;
    }


TBool CAknFepCaseManager::IsCasePermitted(TInt aCase) const
    {
    // if current is permitted or current is lower and text is permitted
    CAknEdwinState* editorState = iFep.EditorState();
    return ( editorState && ( !editorState->PermittedCases() || 
           (aCase & editorState->PermittedCases() || 
           (aCase == EAknEditorLowerCase && 
           (EAknEditorTextCase & editorState->PermittedCases())))) );
    }

TBool CAknFepCaseManager::IsTextCaseCharacter(TChar aChar) const
    {
    TBool ret = EFalse;
    if (iTextCaseCharacters.Locate(aChar)!=KErrNotFound)
        {
        ret = ETrue;
        }
    else if (JPLangUtil::IsKanji((TText)aChar)
          || JPLangUtil::IsHiragana((TText)aChar)
          || JPLangUtil::IsKatakana((TText) aChar))
        {
        ret = ETrue;
        }
    return ret;
    }

TBool CAknFepCaseManager::IsAlpha(TChar aChar) const
    {
    TBool ret = EFalse;
    TBool isPicto = EFalse;
    
    if (iPictoInterface && iPictoInterface->Interface())
        {
        isPicto = iPictoInterface->Interface()->IsPictograph((TText)aChar);
        }
    
    if (!( JPLangUtil::IsHiragana((TText)aChar)
        || JPLangUtil::IsKanji((TText)aChar)
        || JPLangUtil::IsKatakana((TText)aChar)
        /* Teleca change begin, 18.08.2009 ssal */
        || IsKoreanCharacter(aChar)
        /* Teleca change end, 18.08.2009 ssal */
        || isPicto ))
        {
        TChar ch = aChar;
        if (iFep.IsFeatureSupportedJapanese() && 
            JPLangUtil::IsFullWidth((TText) ch))
            {
            TBuf<CAknFepManager::ESingleCharacter> fullChar;
            TBuf<CAknFepManager::ESingleCharacter> halfChar;
            fullChar.Append(ch);
            if (JPLangUtil::ConvertFullToHalfWidth(fullChar, halfChar))
                {
                ch = halfChar[0];
                ret = ch.IsAlpha();
                }
            }
        else
            {
            ret = ch.IsAlpha();
            }
        }
    return ret;
    }

TInt CAknFepCaseManager::PluginPermittedCases()
    {
	TInt allowedCases = ECaseInvalide;    
    if ( !(iFep.EditorState()) )
        {
        return allowedCases;
        }
    
    TInt editorCases = iFep.EditorState()->PermittedCases();
    
    if( editorCases == 0 )
        {
        allowedCases = ECaseUpper | ECaseLower | ECaseText | ECaseInverseText;    
        }
    else
        {
        allowedCases = editorCases;
        
        if( (editorCases & EAknEditorUpperCase) && 
            (editorCases & EAknEditorTextCase) )
            {
            allowedCases |= ECaseInverseText;
            }
        }
    
    return allowedCases;
    }


// -----------------------------------------------------------------------------
// CAknFepCaseManager::CapsLockRequired
// 
// 
// -----------------------------------------------------------------------------
//
TBool CAknFepCaseManager::CapsLockRequired(TInt aCurrentCase)
    {
  	TCursorSelection currentSelection;
  	
  	if (iFep.FepAwareTextEditor())
  		{  		  	
    	iFep.FepAwareTextEditor()->GetCursorSelectionForFep(currentSelection);    
    	return CapsLockRequired(currentSelection.iCursorPos, aCurrentCase);
  		}
  		
	return EFalse;  		
    }

// -----------------------------------------------------------------------------
// CAknFepCaseManager::IsJapaneseCharacter
// Determines whether a character is one of Japanese characters
// -----------------------------------------------------------------------------
//
TBool CAknFepCaseManager::IsJapaneseCharacter(TChar aChar) const
    {
    TBool ret = EFalse;
    // The character case is changed to text case when the left side
    // character is Japanese character (Hiragana, Katakana, Kanji,
    // Full-width Symbol).
    if (JPLangUtil::IsKanji((TText)aChar)
     || JPLangUtil::IsHiragana((TText)aChar)
     || JPLangUtil::IsKatakana((TText)aChar))
        {
        // Hiragana, Katakana, Kanji
        ret = ETrue;
        }
    else if (JPLangUtil::IsFullWidth((TText)aChar)
     && aChar != KPuaCodeSpaceSymbol
     && aChar != KPuaCodeLineFeedSymbol)
        {
        if (iFep.InputMode() == ELatin
          && iFep.CharacterWidth() == EFullWidthChar)
            {
            TBuf<CAknFepManager::ESingleCharacter> fullChar;
            TBuf<CAknFepManager::ESingleCharacter> halfChar;
            fullChar.Append(aChar);
            if (JPLangUtil::ConvertFullToHalfWidth(fullChar, halfChar))
                {
                TChar ch2 = halfChar[0];
                if (!ch2.IsAlpha())
                    {
                    // Full width Symbol or Number
                    ret = ETrue;
                    }
                }
            else
                {
                // The character which isn't converted to half is
                // special Japanese Symbols.
                ret = ETrue;
                }
            }
        else
            {
            ret = ETrue;
            }
        }
    return ret;
    }

/* Teleca change begin, 18.08.2009 ssal */
// -----------------------------------------------------------------------------
// CAknFepCaseManager::IsKoreanCharacter
// Determines whether a character is one of Korean characters
// -----------------------------------------------------------------------------
//
TBool CAknFepCaseManager::IsKoreanCharacter(TChar aChar) const
    {  
    if ( IsHangulSyllable( aChar) || IsHangulCompatibilityJamo( aChar ) )
    	{
    	return ETrue;
    	}
    return EFalse;
    }

// ---------------------------------------------------------------------------
// Checks that is given character hangul syllable or not.
// ---------------------------------------------------------------------------
//
TBool CAknFepCaseManager::IsHangulSyllable( TChar aChar ) const
    {
    // Character is 'hangul syllable' 
    // if it's numeric value is between KSBase and KSBase + KSCount.
    TInt index = static_cast<TInt> ( aChar ) - KSBase;
    if ( index < 0 || index >= KSCount )
        {
        return EFalse;
        }
    return ETrue;
    }

// ---------------------------------------------------------------------------
// Checks that is given character hangul syllable or not.
// ---------------------------------------------------------------------------
//
TBool CAknFepCaseManager::IsHangulCompatibilityJamo( TChar aChar ) const
    {
    // Character is 'hangul compatibility jamo' 
    // if it's numeric value is between KCBase and KCBase + KCCount.
    TInt index = static_cast<TInt> ( aChar ) - KCBase;
    if ( index < 0 || index >= KCCount )
        {
        return EFalse;
        }
    return ETrue;
    }

/* Teleca change end, 18.08.2009 ssal */    
// End of file
