fep/aknfep/src/AknFepCaseManager.cpp
changeset 40 2cb9bae34d17
parent 31 f1bdd6b078d1
child 49 37f5d84451bd
equal deleted inserted replaced
31:f1bdd6b078d1 40:2cb9bae34d17
     1 /*
       
     2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0""
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:           
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 
       
    26 
       
    27 
       
    28 
       
    29 #include "AknFepCaseManager.h"
       
    30 #include "AknFepPanic.h"
       
    31 #include "aknfeppeninputenums.h"
       
    32 
       
    33 #include <aknfep.rsg>
       
    34 #include <aknedsts.h>
       
    35 #include <barsread.h>
       
    36 #include <jplangutil.h>
       
    37 #include <AknPictographInterface.h>
       
    38 #include <AknPictographDrawerInterface.h>
       
    39 #include <featmgr.h>
       
    40 #include <PUAcodes.hrh>
       
    41 
       
    42 const TText KSpaceCharacter=' ';
       
    43 const TText KInvertedExclamationMarkCharacter = 0x00A1;
       
    44 const TText KInvertedQuestionMarkCharacter = 0x00BF;
       
    45 
       
    46 /* Teleca change begin, 18.08.2009 ssal */
       
    47 const TInt KSBase = 0xac00; // base address for hangul syllables
       
    48 const TInt KCBase = 0x3131; // base address for hangul compatibility jamo
       
    49 
       
    50 const TInt KLCount = 19; // count of L-jamos
       
    51 const TInt KVCount = 21; // count of V-jamos
       
    52 const TInt KTCount = 28; // count of T-jamos
       
    53 const TInt KNCount = KVCount * KTCount; // count of V&T-jamo combinations
       
    54 const TInt KSCount = KLCount * KNCount; // total count of hangul syllables
       
    55 
       
    56 // Conversion table for hangul compatibility jamo
       
    57 const TUint16 conversionTableFromCompatibilityJamoToJamo[] = {
       
    58 0x1100,
       
    59 0x1101,
       
    60 0x11AA,
       
    61 0x1102,
       
    62 0x11AC,
       
    63 0x11AD,
       
    64 0x1103,
       
    65 0x1104,
       
    66 0x1105,
       
    67 0x11B0,
       
    68 0x11B1,
       
    69 0x11B2,
       
    70 0x11B3,
       
    71 0x11B4,
       
    72 0x11B5,
       
    73 0x11B6,
       
    74 0x1106,
       
    75 0x1107,
       
    76 0x1108,
       
    77 0x11B9,
       
    78 0x1109,
       
    79 0x110A,
       
    80 0x110B,
       
    81 0x110C,
       
    82 0x110D,
       
    83 0x110E,
       
    84 0x110F,
       
    85 0x1110,
       
    86 0x1111,
       
    87 0x1112,
       
    88 0x1161,
       
    89 0x1162,
       
    90 0x1163,
       
    91 0x1164,
       
    92 0x1165,
       
    93 0x1166,
       
    94 0x1167,
       
    95 0x1168,
       
    96 0x1169,
       
    97 0x116A,
       
    98 0x116B,
       
    99 0x116C,
       
   100 0x116D,
       
   101 0x116E,
       
   102 0x116F,
       
   103 0x1170,
       
   104 0x1171,
       
   105 0x1172,
       
   106 0x1173,
       
   107 0x1174,
       
   108 0x1175,
       
   109 };
       
   110 
       
   111 #define KCCount (sizeof(conversionTableFromCompatibilityJamoToJamo) / sizeof(TUint16))
       
   112 /* Teleca change end, 18.08.2009 ssal */
       
   113 
       
   114 // 0x2029 is the paragraph seperator. When the user inputs a
       
   115 // new line character, 0x2029 is inserted.
       
   116 const TText KParagraphSeperator = 0x2029;
       
   117 // 0x000A is line feed character 
       
   118 const TText KLineFeed = 0x000A;
       
   119 
       
   120 //for chinese unicode ox4E00 to 0x9FA5
       
   121 const TText KChineseLowerUnicode = 0x4E00;
       
   122 const TText KChineseUpperUnicode = 0x9FA5;
       
   123 CAknFepCaseManager* CAknFepCaseManager::NewL(CAknFepManager& aFep)
       
   124     {
       
   125     CAknFepCaseManager* self = new (ELeave) CAknFepCaseManager(aFep);
       
   126     CleanupStack::PushL(self);
       
   127     self->ConstructL();
       
   128     CleanupStack::Pop(); //self
       
   129     return self;
       
   130     }
       
   131 
       
   132 
       
   133 CAknFepCaseManager::~CAknFepCaseManager()
       
   134     {
       
   135     delete iPictoInterface;
       
   136     }
       
   137 
       
   138 
       
   139 
       
   140 
       
   141 void CAknFepCaseManager::ConfigureCaseStateFromEditorState()
       
   142     {
       
   143     CAknEdwinState* editorState = iFep.EditorState();
       
   144     if (!editorState)
       
   145         {
       
   146         return;
       
   147         }
       
   148         
       
   149  	iCurrentCase = editorState->CurrentCase();   
       
   150     iPreviousCase = editorState->CaseState().PreviousCase();    
       
   151         
       
   152     SetFixedCase(editorState->Flags() & EAknEditorFlagFixedCase);
       
   153 
       
   154     iPreviousCase = iCurrentCase;
       
   155 
       
   156   	if (CurrentEditorIsFixedCase())
       
   157     	{    
       
   158     	SetCurrentCase(editorState->DefaultCase()); 
       
   159     	iPreviousCase = iCurrentCase; 
       
   160     	__ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
       
   161                      AknFepPanic(EAknFepPanicNonPermittedEditorMode));		   	
       
   162     	} 
       
   163     	
       
   164     //determine it based on position 
       
   165     UpdateCase(ENullNaviEvent);
       
   166 
       
   167     // if still there is no current case set - use the default
       
   168     if (!iCurrentCase)
       
   169         {
       
   170         SetCurrentCase(editorState->DefaultCase());
       
   171         if (!IsCasePermitted(iCurrentCase))
       
   172             {
       
   173             SetCurrentCase(editorState->CurrentCase());
       
   174             }
       
   175         
       
   176         iPreviousCase = iCurrentCase;
       
   177         __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
       
   178                        AknFepPanic(EAknFepPanicNonPermittedEditorMode));
       
   179         }
       
   180 
       
   181     // if the current is not allowed stay where we are
       
   182     else if (!IsCasePermitted(iCurrentCase))
       
   183         {
       
   184         if (!iPreviousCase)
       
   185             {
       
   186             SetCurrentCase(editorState->DefaultCase());
       
   187             iPreviousCase = iCurrentCase;
       
   188             __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
       
   189                            AknFepPanic(EAknFepPanicNonPermittedEditorMode));
       
   190             }
       
   191         else
       
   192             {
       
   193             if (IsCasePermitted(iPreviousCase))
       
   194                 {
       
   195                 SetCurrentCase(iPreviousCase);
       
   196                 }
       
   197             else
       
   198                 {
       
   199                 SetCurrentCase(editorState->DefaultCase());
       
   200                 iPreviousCase = iCurrentCase;
       
   201                 __ASSERT_DEBUG(IsCasePermitted(iCurrentCase), 
       
   202                                AknFepPanic(EAknFepPanicNonPermittedEditorMode));
       
   203                 }    
       
   204             }
       
   205         }
       
   206     }
       
   207 
       
   208 
       
   209 void CAknFepCaseManager::UpdateCase(TWesternNaviEvent aNaviEvent)
       
   210     {
       
   211     TBool applyCaseNeeded = ETrue;
       
   212     if ( iFep.IsFlagSet(CAknFepManager::EFlagSupressAutoUpdate) )
       
   213         {
       
   214         return;
       
   215         }
       
   216     CAknEdwinState* editorState = iFep.EditorState();
       
   217     if (!CurrentEditorIsFixedCase() && editorState 
       
   218       && editorState->PermittedCases() & EAknEditorTextCase)
       
   219         {
       
   220         // lets figure out where the cursor will be when the case needs to be checked
       
   221         TInt cursorPos = FindCursorPositionAtCaseCheck(aNaviEvent);
       
   222         
       
   223         if (!(cursorPos == 0 
       
   224            && iFep.IsFlagSet(CAknFepManager::EFlagSupressAutoUpdateAtEditorStart) ))
       
   225             {
       
   226             TInt defaultCase = editorState->DefaultCase();
       
   227             if ( cursorPos == 0 && 
       
   228                (defaultCase == EAknEditorLowerCase || defaultCase == EAknEditorUpperCase ))
       
   229                 {
       
   230                 SetCurrentCase(defaultCase);
       
   231                 }
       
   232             // UPPER CASE : If in upper case & inside sentence, stay in upper.
       
   233             else if (!(iCurrentCase == EAknEditorUpperCase && 
       
   234                        CapsLockRequired(cursorPos, iCurrentCase) && 
       
   235                        aNaviEvent != EBackspaceEvent))
       
   236                 {
       
   237                 const TBool textCaseRequired = TextCaseRequired(cursorPos);
       
   238                 // UPPER CASE : If upper case & inside sentence & backspace event, stay in upper.
       
   239                 if (!(iCurrentCase == EAknEditorUpperCase && aNaviEvent == EBackspaceEvent &&
       
   240                     !textCaseRequired && cursorPos != 0))
       
   241                     {
       
   242                     // TEXT CASE : set if at start of editor or following a full stop / text case character
       
   243                     if (cursorPos == 0 || textCaseRequired)
       
   244                         {
       
   245                         TInt inputMode = iFep.InputMode();
       
   246                         if (iFep.IsChineseInputLanguage() && 
       
   247                         	inputMode != ELatin &&
       
   248                         	iCurrentCase != EAknEditorLowerCase)
       
   249                         {
       
   250                         SetCurrentCase(iCurrentCase);
       
   251                         }
       
   252 #ifdef RD_HINDI_PHONETIC_INPUT	
       
   253                         
       
   254 	                    else if(iFep.IsIndicPhoneticInputLanguage())
       
   255 	                    	{
       
   256 	                    	if(CurrentCase() != EAknEditorUpperCase)
       
   257 	                    	    SetCurrentCase(EAknEditorLowerCase);	
       
   258 	                    	}
       
   259 #endif
       
   260                         else
       
   261                         {
       
   262                         /* Teleca change begin, 27.08.2008 ssal 
       
   263                         	original code:
       
   264                         SetCurrentCase(EAknEditorTextCase);	*/
       
   265                         
       
   266                         if(iFep.IsKoreanInputLanguage() && inputMode == EHangul )
       
   267                         	{
       
   268                         	SetCurrentCase(EAknEditorLowerCase);	
       
   269                         	}
       
   270                         else
       
   271                         	{
       
   272                             SetCurrentCase(EAknEditorTextCase);
       
   273                             }
       
   274                         /* Teleca change end, 27.08.2008 ssal */
       
   275                         }
       
   276                         applyCaseNeeded = EFalse;
       
   277                         }
       
   278                     else // OTHERWISE LOWER
       
   279                         {
       
   280                         SetCurrentCase(EAknEditorLowerCase);
       
   281                         applyCaseNeeded = EFalse;
       
   282                         }
       
   283                     }
       
   284                 }
       
   285             }
       
   286         else
       
   287             {
       
   288             iFep.ClearFlag(CAknFepManager::EFlagSupressAutoUpdateAtEditorStart);
       
   289             }
       
   290         }
       
   291     if (applyCaseNeeded)
       
   292         {
       
   293         ApplyCase();
       
   294         }
       
   295     }
       
   296 
       
   297 
       
   298 void CAknFepCaseManager::ManualCaseUpdate()
       
   299     {
       
   300     if (!CurrentEditorIsFixedCase())
       
   301         {
       
   302         if (IsCasePermitted(iCurrentCase)) 
       
   303             {
       
   304             DoManualCaseUpdate();
       
   305             iFep.ClearFlag(CAknFepManager::EFlagSupressAutoUpdate);
       
   306             }
       
   307         }
       
   308     }
       
   309 
       
   310 
       
   311 void CAknFepCaseManager::RevertCaseChange()
       
   312     {
       
   313     if (!CurrentEditorIsFixedCase())
       
   314         {
       
   315         if (IsCasePermitted(iPreviousCase)) 
       
   316             {
       
   317             SetCurrentCase(iPreviousCase); 
       
   318             }
       
   319         }
       
   320     }
       
   321 
       
   322 
       
   323 void CAknFepCaseManager::SetCurrentCase(TInt aCase, TBool aOverrideNumericTest)
       
   324     {
       
   325     if ( ( iFep.InputMode() == ENumber || iFep.InputMode() == ENativeNumber ) && 
       
   326         !aOverrideNumericTest)
       
   327         {
       
   328         if ( iFep.EditorState() && 
       
   329             (iFep.EditorState()->NumericKeymap() == EAknEditorConverterNumberModeKeymap) )
       
   330             {
       
   331             // Converter number mode keymap for '*' key requires upper case 'E'.
       
   332             iCurrentCase = EAknEditorUpperCase;
       
   333             }
       
   334         else
       
   335             {
       
   336             // Number mode keymappings for '*' -key uses lower case letters (pw).
       
   337             iCurrentCase = EAknEditorLowerCase;
       
   338             }
       
   339         }
       
   340     else
       
   341         {
       
   342         if ( aCase == ECaseInverseText )
       
   343             {
       
   344             iCurrentCase = ECaseUpper;
       
   345             iInverseCase = ETrue;
       
   346             }
       
   347         else
       
   348             {
       
   349             iCurrentCase = aCase;
       
   350             iInverseCase = EFalse;
       
   351             }
       
   352         }
       
   353     ApplyCase();
       
   354     }
       
   355 
       
   356 
       
   357 TInt CAknFepCaseManager::CurrentCase() const
       
   358     {
       
   359     return iCurrentCase;
       
   360     }
       
   361 
       
   362 TBool CAknFepCaseManager::IsAbleChangeCase() const
       
   363     {
       
   364     TBool isable = ETrue;
       
   365     
       
   366     CAknEdwinState* editorState = iFep.EditorState();
       
   367     if (editorState)
       
   368     	{
       
   369 	    const TInt permittedCases = editorState->PermittedCases();
       
   370 	    
       
   371 	    if (permittedCases == EAknEditorUpperCase ||
       
   372 	        permittedCases == EAknEditorLowerCase )
       
   373 	        {
       
   374 	        isable = EFalse;
       
   375 	        }
       
   376 	    else if ((editorState->Flags() & EAknEditorFlagForceTransparentFepModes)
       
   377 	          && iFep.IsChineseInputLanguage())
       
   378 	        {
       
   379 	        isable = EFalse;
       
   380 	        }
       
   381 	    else if ( editorState->Flags() & EAknEditorFlagFixedCase )
       
   382 	        {
       
   383 	        isable = EFalse;
       
   384 	        }
       
   385 	    else if (!iFep.InputLanguageSupportsCaseChanges())
       
   386 	        {
       
   387 	        isable = EFalse;
       
   388 	        }
       
   389     	}
       
   390     else
       
   391     	{
       
   392     	isable = EFalse;
       
   393     	}
       
   394     return isable;
       
   395     }
       
   396 
       
   397 CAknFepCaseManager::CAknFepCaseManager(CAknFepManager& aFep) :
       
   398     iFep(aFep)
       
   399     {
       
   400     }
       
   401 
       
   402 
       
   403 void CAknFepCaseManager::ConstructL()
       
   404     {
       
   405     // Set text case character set from resource
       
   406     TResourceReader reader;
       
   407     CCoeEnv::Static()->CreateResourceReaderLC(reader, R_AKNFEP_TEXT_CASE_CHARACTER_SET);
       
   408     iTextCaseCharacters=reader.ReadTPtrC();
       
   409 
       
   410     // Create PictographInterface
       
   411     CCoeControl* control = NULL;
       
   412     MAknPictographAnimatorCallBack* callback = NULL;
       
   413     iPictoInterface = CAknPictographInterface::NewL(*control,*callback);
       
   414 
       
   415     CleanupStack::PopAndDestroy(); // reader*/
       
   416     }
       
   417 
       
   418 
       
   419 TInt CAknFepCaseManager::FindCursorPositionAtCaseCheck(TWesternNaviEvent aNaviEvent)
       
   420     {
       
   421     TCursorSelection curCursSel;
       
   422     iFep.FepAwareTextEditor()->GetCursorSelectionForFep(curCursSel);
       
   423     
       
   424     TInt docLength = iFep.FepAwareTextEditor()->DocumentLengthForFep();
       
   425     TInt returnedPosition = -1;
       
   426 
       
   427     TCursorSelection uncommittedText = iFep.UncommittedText();
       
   428 
       
   429     switch (aNaviEvent)
       
   430         {
       
   431         case ENullNaviEvent:
       
   432             if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
       
   433                 {
       
   434                 returnedPosition = uncommittedText.HigherPos();
       
   435                 }
       
   436             else
       
   437                 {
       
   438                 // In case of non-predictive mode, following condition
       
   439                 // check text is selceted mode or not?
       
   440                 // In selected mode, character always being inserted
       
   441                 // anchor position
       
   442                 if( curCursSel.Length() >0 )
       
   443                     {
       
   444                     returnedPosition = curCursSel.LowerPos();
       
   445                     }
       
   446                 else
       
   447                     {
       
   448                     returnedPosition = curCursSel.HigherPos();
       
   449                     }
       
   450                 }
       
   451             break;
       
   452         case ERightNaviEvent:
       
   453             if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
       
   454                 {
       
   455                 returnedPosition = uncommittedText.HigherPos();
       
   456                 }
       
   457             else
       
   458                 {
       
   459                 if (curCursSel.Length())
       
   460                     {
       
   461                     returnedPosition = curCursSel.HigherPos();
       
   462                     }
       
   463                 else
       
   464                     {
       
   465                     if (curCursSel.iCursorPos == docLength)
       
   466                         {
       
   467                         returnedPosition = 0;
       
   468                         }
       
   469                     else
       
   470                         {
       
   471                         returnedPosition = curCursSel.HigherPos() + 1;
       
   472                         }
       
   473                     }
       
   474                 }
       
   475             break;
       
   476         case ELeftNaviEvent:
       
   477             if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
       
   478                 {
       
   479                 returnedPosition = uncommittedText.LowerPos();
       
   480                 }
       
   481             else
       
   482                 {
       
   483                 if (curCursSel.Length())
       
   484                     {
       
   485                     returnedPosition = curCursSel.LowerPos();
       
   486                     }
       
   487                 else
       
   488                     {
       
   489                     if (curCursSel.iCursorPos == 0)
       
   490                         {
       
   491                         returnedPosition = docLength;
       
   492                         }
       
   493                     else
       
   494                         {
       
   495                         returnedPosition = curCursSel.LowerPos() - 1;
       
   496                         }
       
   497                     }
       
   498                 }
       
   499             break;
       
   500         case EBackspaceEvent:
       
   501             if (iFep.IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
       
   502                 {
       
   503                 returnedPosition = uncommittedText.HigherPos();
       
   504                 }
       
   505             else
       
   506                 {
       
   507                 if (curCursSel.Length())
       
   508                     {
       
   509                     returnedPosition = curCursSel.LowerPos();
       
   510                     }
       
   511                 else
       
   512                     {
       
   513                     returnedPosition = curCursSel.LowerPos() - 1;
       
   514                     }
       
   515                 }
       
   516             break;
       
   517         default:
       
   518             break;
       
   519         }
       
   520 
       
   521     if (returnedPosition < 0)
       
   522         {
       
   523         returnedPosition = 0;
       
   524         }
       
   525     else if (returnedPosition > docLength)
       
   526         {
       
   527         returnedPosition = docLength;
       
   528         }
       
   529     return returnedPosition;
       
   530     }
       
   531 
       
   532 
       
   533 TBool CAknFepCaseManager::TextCaseRequired(TInt aCursorPos)
       
   534     {
       
   535     TBool textCaseRequired = EFalse;
       
   536     TInt charPosToCheck = aCursorPos - 1;   
       
   537     TChar ch = KSpaceCharacter;
       
   538     TBuf<CAknFepManager::ESingleCharacter> editorText;
       
   539     TInt nonEnterSpaceCharCount = 0;
       
   540     
       
   541     if (charPosToCheck >= 0) 
       
   542         {
       
   543         // Get the character just before the cursor.
       
   544         iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
       
   545             charPosToCheck, CAknFepManager::ESingleCharacter);
       
   546         ch = editorText[0];        
       
   547         if ( ch == KInvertedQuestionMarkCharacter || ch == KInvertedExclamationMarkCharacter )
       
   548             {
       
   549             // Text case is required imediatelly after 'spanich' question and exclamation mark that begins a sentence.
       
   550             textCaseRequired = ETrue;        
       
   551             }
       
   552         // for chinese uncode limit
       
   553         if ( ch >= KChineseLowerUnicode && ch<= KChineseUpperUnicode)
       
   554         	{
       
   555         	textCaseRequired = ETrue; 
       
   556         	}
       
   557         
       
   558         if( ( TUint )ch == KParagraphSeperator || ( TUint )ch == KLineFeed )
       
   559             {
       
   560             // When we have enter key, we need to decide the case after: 
       
   561             // we reach some non space characters (OR)
       
   562             // we reach the beginning of the editor
       
   563             while (charPosToCheck > 0 && !textCaseRequired)
       
   564                 {
       
   565                 charPosToCheck--;
       
   566                 iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
       
   567                     charPosToCheck, CAknFepManager::ESingleCharacter);
       
   568                 ch = editorText[0];
       
   569                 
       
   570                 // IsSpace returns true for ParagraphSeperator.
       
   571                 if (!(ch.IsSpace() || ch == EKeyEnter) && nonEnterSpaceCharCount <= 1)
       
   572                     {
       
   573                     if (IsTextCaseCharacter(ch))
       
   574                         {
       
   575         	            textCaseRequired = ETrue;
       
   576                         }
       
   577                     break;
       
   578                     }
       
   579                 else 
       
   580                 	{
       
   581                 	if(!( ( TUint )ch == KParagraphSeperator || ( TUint )ch == EKeyEnter || ( TUint )ch == KLineFeed ) )
       
   582                 		{
       
   583                 		// Incrementing the count if we have
       
   584                 		// IsSpace() returns True AND
       
   585                 		// the character is not a ParagraphSeparator or Enter or Line Feed
       
   586                 		nonEnterSpaceCharCount++;
       
   587 	                	}
       
   588                 	if (charPosToCheck <= 0 && !nonEnterSpaceCharCount)
       
   589                     	{
       
   590                     	//Reached the beginning of the Editor. Text case should be ON
       
   591                     	textCaseRequired = ETrue;
       
   592                     	}                    	
       
   593                 	}    	
       
   594                 }
       
   595             charPosToCheck = aCursorPos - 1;
       
   596             
       
   597            	if (charPosToCheck <= 0 && !nonEnterSpaceCharCount)
       
   598            	    {
       
   599            	    // If Enter is pressed as the first character. Text case is ON
       
   600                 textCaseRequired = ETrue;
       
   601                 }                    	
       
   602             
       
   603         	}
       
   604 
       
   605         /* Teleca change begin, 27.08.2008 ssal */	
       
   606         if (IsKoreanCharacter(ch))
       
   607         	{
       
   608         	textCaseRequired = ETrue;       
       
   609         	}
       
   610         /* Teleca change end, 27.08.2008 ssal */
       
   611         }
       
   612 
       
   613 
       
   614     if (charPosToCheck > 0 && !textCaseRequired) 
       
   615         {
       
   616         if (iFep.IsFeatureSupportedJapanese())
       
   617             {
       
   618             // The character case is changed to text case when the left side
       
   619             // character is Japanese character.
       
   620             if (IsJapaneseCharacter(ch))
       
   621                 {
       
   622                 textCaseRequired = ETrue;
       
   623                 }
       
   624             else if (ch.IsSpace() || ch == EKeyEnter ||
       
   625                      ch == (TUint)KPuaCodeSpaceSymbol)
       
   626                 {
       
   627                 while (charPosToCheck > 0)
       
   628                     {
       
   629                     charPosToCheck--;
       
   630                     // Get the character before the previous character.
       
   631                     iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
       
   632                         charPosToCheck, CAknFepManager::ESingleCharacter);
       
   633                     ch = editorText[0];
       
   634                     if (!(ch.IsSpace() || ch == EKeyEnter || ch == (TUint)KPuaCodeSpaceSymbol))
       
   635                         {
       
   636                         if (IsTextCaseCharacter(ch))
       
   637                             {
       
   638                             // One space between the cursor and the punctuation character => text case needed
       
   639                             textCaseRequired = ETrue;
       
   640                             }
       
   641                         break;
       
   642                         }
       
   643                     else if (charPosToCheck <= 0)
       
   644                         {
       
   645                         // reached the start of the editor => text case needed
       
   646                         textCaseRequired = ETrue;
       
   647                         }
       
   648                     }
       
   649                 }
       
   650             }
       
   651         else
       
   652             {
       
   653             if ( charPosToCheck > 0 && !textCaseRequired && !nonEnterSpaceCharCount) 
       
   654 			    {        
       
   655 			    if ( ch.IsSpace() || ch == EKeyEnter || 
       
   656 			    	ch == ( TUint )KPuaCodeSpaceSymbol )
       
   657 			        {
       
   658 			        while ( charPosToCheck > 0 )
       
   659 			            {
       
   660 			            charPosToCheck--;
       
   661 			            
       
   662 			            // Get the character before the previous character.
       
   663 			            iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
       
   664 			                charPosToCheck, CAknFepManager::ESingleCharacter);
       
   665 			                
       
   666 			            ch = editorText[0];
       
   667 			            
       
   668 			            // This condition is added to keep Text case ON when space is
       
   669 			            // entered after a "New line" character.
       
   670 			            if( ( TUint )ch == KParagraphSeperator )
       
   671 			            	{			            	
       
   672 			            	textCaseRequired = ETrue;
       
   673 			            	break;
       
   674 			            	}
       
   675 			            	
       
   676 			            if ( !( ch == EKeyEnter || 
       
   677 			            		ch == ( TUint )KPuaCodeSpaceSymbol ) )
       
   678 			                {
       
   679 			                if ( IsTextCaseCharacter( ch ) )
       
   680 			                    {			                    
       
   681 			                    textCaseRequired = ETrue;
       
   682 			                    }
       
   683 			                break;
       
   684 			                }
       
   685 			            else if ( charPosToCheck <= 0 )
       
   686 			                {
       
   687 			                // reached the start of the editor => text case needed
       
   688 			                textCaseRequired = ETrue;
       
   689 			                }
       
   690 			            }
       
   691                     }
       
   692                 }
       
   693             }
       
   694         }
       
   695     else if (charPosToCheck < 0)
       
   696         {
       
   697         // reached the start of the editor => text case needed
       
   698         textCaseRequired = ETrue;
       
   699         }
       
   700     else    // if (charPosToCheck == 0)
       
   701         {
       
   702         if (!textCaseRequired && iFep.IsFeatureSupportedJapanese())
       
   703             {
       
   704             if (IsJapaneseCharacter(ch)
       
   705              || ch.IsSpace()
       
   706              || ch == EKeyEnter
       
   707              || ch == (TUint)KPuaCodeSpaceSymbol)
       
   708                 {
       
   709                 // reached the start of the editor => text case needed
       
   710                 textCaseRequired = ETrue;
       
   711                 }
       
   712             }
       
   713         }
       
   714 
       
   715     return textCaseRequired;
       
   716     }
       
   717 
       
   718 
       
   719 TBool CAknFepCaseManager::CapsLockRequired(TInt aCursorPos, TInt aCurCase)
       
   720     {
       
   721     TBool capsLocked = iForceUpperCase;
       
   722     TInt charPosToCheck = aCursorPos - 1;   
       
   723     TChar ch = KSpaceCharacter;
       
   724     TBuf<CAknFepManager::ESingleCharacter> editorText;
       
   725     
       
   726     // is the previous character alphabetical?
       
   727     if (charPosToCheck >= 0) 
       
   728         {
       
   729         iFep.FepAwareTextEditor()->GetEditorContentForFep(editorText,
       
   730             charPosToCheck, CAknFepManager::ESingleCharacter);
       
   731         if( editorText.Length()>0 )
       
   732             {
       
   733             ch = editorText[0];
       
   734             }
       
   735             
       
   736         if (IsAlpha(ch) ||
       
   737             ((aCurCase == EAknEditorUpperCase || aCurCase == ECaseInverseText) && 
       
   738              !TextCaseRequired(aCursorPos)))
       
   739             {
       
   740             // Caps lock (upper case mode) is kept up if we are currently in upper case mode
       
   741             // and previous character is alpha character or for example full stop. 
       
   742             // If the cursor and full stop is separated with space, text case is restored. 
       
   743             capsLocked = ETrue;
       
   744             }
       
   745         }
       
   746     
       
   747     return capsLocked;
       
   748     }
       
   749 
       
   750 
       
   751 void CAknFepCaseManager::DoManualCaseUpdate()
       
   752     {
       
   753     TBool applyCaseNeeded = ETrue;
       
   754     iPreviousCase = iCurrentCase;
       
   755     TCursorSelection currentSelection;
       
   756     iFep.FepAwareTextEditor()->GetCursorSelectionForFep(currentSelection);
       
   757 
       
   758     switch (iCurrentCase)
       
   759         {
       
   760         case EAknEditorLowerCase:
       
   761             if (CapsLockRequired(currentSelection.iCursorPos, iCurrentCase) 
       
   762              && IsCasePermitted(EAknEditorUpperCase))
       
   763                 {
       
   764                 SetCurrentCase(EAknEditorUpperCase);
       
   765                 }
       
   766             else if (!IsCasePermitted(EAknEditorTextCase) 
       
   767 #ifdef RD_HINDI_PHONETIC_INPUT	
       
   768             
       
   769             || iFep.IsIndicPhoneticInputLanguage()
       
   770 #endif            
       
   771             )
       
   772                 {
       
   773                 if( IsCasePermitted(EAknEditorUpperCase) )
       
   774                     SetCurrentCase(EAknEditorUpperCase);
       
   775                 }
       
   776             else
       
   777                 {
       
   778                 SetCurrentCase(EAknEditorTextCase);
       
   779                 }
       
   780             applyCaseNeeded = EFalse;
       
   781             break;
       
   782         case EAknEditorTextCase:
       
   783              if (iForceUpperCase && IsCasePermitted(EAknEditorUpperCase))
       
   784                 {
       
   785                 SetCurrentCase(EAknEditorUpperCase);
       
   786                 applyCaseNeeded = EFalse;     
       
   787                 break;          
       
   788                 }
       
   789         case EAknEditorUpperCase:
       
   790             SetCurrentCase(EAknEditorLowerCase);
       
   791             applyCaseNeeded = EFalse;
       
   792             break;
       
   793         default:
       
   794             break;
       
   795         }
       
   796 
       
   797     if (!(IsCasePermitted(iCurrentCase)))
       
   798         {
       
   799         DoManualCaseUpdate();
       
   800         }
       
   801     else
       
   802         {
       
   803         if (applyCaseNeeded)
       
   804             {
       
   805             ApplyCase();
       
   806             }
       
   807         }
       
   808     }
       
   809 
       
   810 
       
   811 void CAknFepCaseManager::ApplyCase()
       
   812     {
       
   813     // update engine...
       
   814     switch (iCurrentCase)
       
   815         {
       
   816         case EAknEditorUpperCase: // fall through
       
   817         case EAknEditorTextCase:
       
   818             iFep.SetCase(EUpperCase);
       
   819             break;
       
   820         case EAknEditorLowerCase: // fall through
       
   821         default:
       
   822             iFep.SetCase(ELowerCase);
       
   823             break;
       
   824         }
       
   825     if(iFep.EditorState())
       
   826         {
       
   827         iFep.EditorState()->SetCurrentCase(iCurrentCase);
       
   828         }
       
   829     iFep.UpdateIndicators();
       
   830 
       
   831 #ifdef RD_SCALABLE_UI_V2    
       
   832     iFep.UpdateTouchCaseMode();
       
   833 #endif
       
   834     }
       
   835 
       
   836 
       
   837 void CAknFepCaseManager::SetFixedCase(TBool aFixedCase)
       
   838     {
       
   839     iFixedCase = aFixedCase;
       
   840     }
       
   841 
       
   842 
       
   843 TBool CAknFepCaseManager::CurrentEditorIsFixedCase() const
       
   844     {
       
   845     return iFixedCase;
       
   846     }
       
   847 
       
   848 
       
   849 TBool CAknFepCaseManager::IsCasePermitted(TInt aCase) const
       
   850     {
       
   851     // if current is permitted or current is lower and text is permitted
       
   852     CAknEdwinState* editorState = iFep.EditorState();
       
   853     return ( editorState && ( !editorState->PermittedCases() || 
       
   854            (aCase & editorState->PermittedCases() || 
       
   855            (aCase == EAknEditorLowerCase && 
       
   856            (EAknEditorTextCase & editorState->PermittedCases())))) );
       
   857     }
       
   858 
       
   859 TBool CAknFepCaseManager::IsTextCaseCharacter(TChar aChar) const
       
   860     {
       
   861     TBool ret = EFalse;
       
   862     if (iTextCaseCharacters.Locate(aChar)!=KErrNotFound)
       
   863         {
       
   864         ret = ETrue;
       
   865         }
       
   866     else if (JPLangUtil::IsKanji((TText)aChar)
       
   867           || JPLangUtil::IsHiragana((TText)aChar)
       
   868           || JPLangUtil::IsKatakana((TText) aChar))
       
   869         {
       
   870         ret = ETrue;
       
   871         }
       
   872     return ret;
       
   873     }
       
   874 
       
   875 TBool CAknFepCaseManager::IsAlpha(TChar aChar) const
       
   876     {
       
   877     TBool ret = EFalse;
       
   878     TBool isPicto = EFalse;
       
   879     
       
   880     if (iPictoInterface && iPictoInterface->Interface())
       
   881         {
       
   882         isPicto = iPictoInterface->Interface()->IsPictograph((TText)aChar);
       
   883         }
       
   884     
       
   885     if (!( JPLangUtil::IsHiragana((TText)aChar)
       
   886         || JPLangUtil::IsKanji((TText)aChar)
       
   887         || JPLangUtil::IsKatakana((TText)aChar)
       
   888         /* Teleca change begin, 18.08.2009 ssal */
       
   889         || IsKoreanCharacter(aChar)
       
   890         /* Teleca change end, 18.08.2009 ssal */
       
   891         || isPicto ))
       
   892         {
       
   893         TChar ch = aChar;
       
   894         if (iFep.IsFeatureSupportedJapanese() && 
       
   895             JPLangUtil::IsFullWidth((TText) ch))
       
   896             {
       
   897             TBuf<CAknFepManager::ESingleCharacter> fullChar;
       
   898             TBuf<CAknFepManager::ESingleCharacter> halfChar;
       
   899             fullChar.Append(ch);
       
   900             if (JPLangUtil::ConvertFullToHalfWidth(fullChar, halfChar))
       
   901                 {
       
   902                 ch = halfChar[0];
       
   903                 ret = ch.IsAlpha();
       
   904                 }
       
   905             }
       
   906         else
       
   907             {
       
   908             ret = ch.IsAlpha();
       
   909             }
       
   910         }
       
   911     return ret;
       
   912     }
       
   913 
       
   914 TInt CAknFepCaseManager::PluginPermittedCases()
       
   915     {
       
   916 	TInt allowedCases = ECaseInvalide;    
       
   917     if ( !(iFep.EditorState()) )
       
   918         {
       
   919         return allowedCases;
       
   920         }
       
   921     
       
   922     TInt editorCases = iFep.EditorState()->PermittedCases();
       
   923     
       
   924     if( editorCases == 0 )
       
   925         {
       
   926         allowedCases = ECaseUpper | ECaseLower | ECaseText | ECaseInverseText;    
       
   927         }
       
   928     else
       
   929         {
       
   930         allowedCases = editorCases;
       
   931         
       
   932         if( (editorCases & EAknEditorUpperCase) && 
       
   933             (editorCases & EAknEditorTextCase) )
       
   934             {
       
   935             allowedCases |= ECaseInverseText;
       
   936             }
       
   937         }
       
   938     
       
   939     return allowedCases;
       
   940     }
       
   941 
       
   942 
       
   943 // -----------------------------------------------------------------------------
       
   944 // CAknFepCaseManager::CapsLockRequired
       
   945 // 
       
   946 // 
       
   947 // -----------------------------------------------------------------------------
       
   948 //
       
   949 TBool CAknFepCaseManager::CapsLockRequired(TInt aCurrentCase)
       
   950     {
       
   951   	TCursorSelection currentSelection;
       
   952   	
       
   953   	if (iFep.FepAwareTextEditor())
       
   954   		{  		  	
       
   955     	iFep.FepAwareTextEditor()->GetCursorSelectionForFep(currentSelection);    
       
   956     	return CapsLockRequired(currentSelection.iCursorPos, aCurrentCase);
       
   957   		}
       
   958   		
       
   959 	return EFalse;  		
       
   960     }
       
   961 
       
   962 // -----------------------------------------------------------------------------
       
   963 // CAknFepCaseManager::IsJapaneseCharacter
       
   964 // Determines whether a character is one of Japanese characters
       
   965 // -----------------------------------------------------------------------------
       
   966 //
       
   967 TBool CAknFepCaseManager::IsJapaneseCharacter(TChar aChar) const
       
   968     {
       
   969     TBool ret = EFalse;
       
   970     // The character case is changed to text case when the left side
       
   971     // character is Japanese character (Hiragana, Katakana, Kanji,
       
   972     // Full-width Symbol).
       
   973     if (JPLangUtil::IsKanji((TText)aChar)
       
   974      || JPLangUtil::IsHiragana((TText)aChar)
       
   975      || JPLangUtil::IsKatakana((TText)aChar))
       
   976         {
       
   977         // Hiragana, Katakana, Kanji
       
   978         ret = ETrue;
       
   979         }
       
   980     else if (JPLangUtil::IsFullWidth((TText)aChar)
       
   981      && aChar != KPuaCodeSpaceSymbol
       
   982      && aChar != KPuaCodeLineFeedSymbol)
       
   983         {
       
   984         if (iFep.InputMode() == ELatin
       
   985           && iFep.CharacterWidth() == EFullWidthChar)
       
   986             {
       
   987             TBuf<CAknFepManager::ESingleCharacter> fullChar;
       
   988             TBuf<CAknFepManager::ESingleCharacter> halfChar;
       
   989             fullChar.Append(aChar);
       
   990             if (JPLangUtil::ConvertFullToHalfWidth(fullChar, halfChar))
       
   991                 {
       
   992                 TChar ch2 = halfChar[0];
       
   993                 if (!ch2.IsAlpha())
       
   994                     {
       
   995                     // Full width Symbol or Number
       
   996                     ret = ETrue;
       
   997                     }
       
   998                 }
       
   999             else
       
  1000                 {
       
  1001                 // The character which isn't converted to half is
       
  1002                 // special Japanese Symbols.
       
  1003                 ret = ETrue;
       
  1004                 }
       
  1005             }
       
  1006         else
       
  1007             {
       
  1008             ret = ETrue;
       
  1009             }
       
  1010         }
       
  1011     return ret;
       
  1012     }
       
  1013 
       
  1014 /* Teleca change begin, 18.08.2009 ssal */
       
  1015 // -----------------------------------------------------------------------------
       
  1016 // CAknFepCaseManager::IsKoreanCharacter
       
  1017 // Determines whether a character is one of Korean characters
       
  1018 // -----------------------------------------------------------------------------
       
  1019 //
       
  1020 TBool CAknFepCaseManager::IsKoreanCharacter(TChar aChar) const
       
  1021     {  
       
  1022     if ( IsHangulSyllable( aChar) || IsHangulCompatibilityJamo( aChar ) )
       
  1023     	{
       
  1024     	return ETrue;
       
  1025     	}
       
  1026     return EFalse;
       
  1027     }
       
  1028 
       
  1029 // ---------------------------------------------------------------------------
       
  1030 // Checks that is given character hangul syllable or not.
       
  1031 // ---------------------------------------------------------------------------
       
  1032 //
       
  1033 TBool CAknFepCaseManager::IsHangulSyllable( TChar aChar ) const
       
  1034     {
       
  1035     // Character is 'hangul syllable' 
       
  1036     // if it's numeric value is between KSBase and KSBase + KSCount.
       
  1037     TInt index = static_cast<TInt> ( aChar ) - KSBase;
       
  1038     if ( index < 0 || index >= KSCount )
       
  1039         {
       
  1040         return EFalse;
       
  1041         }
       
  1042     return ETrue;
       
  1043     }
       
  1044 
       
  1045 // ---------------------------------------------------------------------------
       
  1046 // Checks that is given character hangul syllable or not.
       
  1047 // ---------------------------------------------------------------------------
       
  1048 //
       
  1049 TBool CAknFepCaseManager::IsHangulCompatibilityJamo( TChar aChar ) const
       
  1050     {
       
  1051     // Character is 'hangul compatibility jamo' 
       
  1052     // if it's numeric value is between KCBase and KCBase + KCCount.
       
  1053     TInt index = static_cast<TInt> ( aChar ) - KCBase;
       
  1054     if ( index < 0 || index >= KCCount )
       
  1055         {
       
  1056         return EFalse;
       
  1057         }
       
  1058     return ETrue;
       
  1059     }
       
  1060 
       
  1061 /* Teleca change end, 18.08.2009 ssal */    
       
  1062 // End of file