fep/aknfep/src/AknFepCaseManager.cpp
changeset 0 eb1f2e154e89
child 19 5e18d8c489d6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fep/aknfep/src/AknFepCaseManager.cpp	Tue Feb 02 01:02:04 2010 +0200
@@ -0,0 +1,1062 @@
+/*
+* 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