textinput/peninputvkbcn/ctrlsrc/AknFepVkbPinyinAnalyser.cpp
changeset 0 eb1f2e154e89
equal deleted inserted replaced
-1:000000000000 0:eb1f2e154e89
       
     1 /*
       
     2 * Copyright (c) 2002-2005 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:  Implementation of the vkb data manager
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // system includes
       
    20 
       
    21 
       
    22 // user includes
       
    23 #include "AknFepVkbPinyinAnalyser.h"
       
    24 #include "AknFepVkbPinyinAnalyserDb.h"
       
    25 
       
    26 class TSpellBand
       
    27 {
       
    28 public:
       
    29     int iStart;
       
    30     int iCount;
       
    31 }; 
       
    32 
       
    33 
       
    34 class TSpellAnalysis : public TPriQueLink  
       
    35 {
       
    36 public:
       
    37     RArray<TInt> iSeparators;
       
    38     TSpellAnalysis()
       
    39     {
       
    40         iPriority = -0x10000;
       
    41     }
       
    42     ~TSpellAnalysis()
       
    43         {
       
    44         iSeparators.Close();
       
    45         }
       
    46         
       
    47     TSpellAnalysis(const TSpellAnalysis& aSource)
       
    48     {
       
    49         iPriority = aSource.iPriority;
       
    50         for( TInt i = 0; i < aSource.iSeparators.Count(); ++i )
       
    51         {
       
    52             iSeparators.Append(aSource.iSeparators[i]);
       
    53         }
       
    54     }
       
    55     void Calculate()
       
    56     {
       
    57         iPriority = (iSeparators.Count() + 1) << 16;
       
    58         TInt multi = 12;
       
    59         for( TInt i = 0; i < iSeparators.Count(); ++i )
       
    60         {
       
    61             iPriority += ( 6 - iSeparators[i]) << multi; 
       
    62             if( multi >= 3 )
       
    63             {
       
    64                 multi -= 3;
       
    65             }            
       
    66         }
       
    67         iPriority = -iPriority;
       
    68     }
       
    69     TInt GetStartPos()
       
    70     {
       
    71         if( iSeparators.Count() == 0)
       
    72         {
       
    73             return 0;
       
    74         }
       
    75         else
       
    76         {
       
    77             return iSeparators[ iSeparators.Count() - 1 ];
       
    78         }
       
    79     }
       
    80     void AddSeparator(TInt aPos)
       
    81     {
       
    82         iSeparators.Append(aPos);
       
    83         Calculate();
       
    84     }
       
    85 };
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser
       
    89 // (other items were commented in a header).
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser()
       
    93     {
       
    94     iAnalysisFlag = EFalse;
       
    95     }
       
    96        
       
    97 // -----------------------------------------------------------------------------
       
    98 // CAknFepVkbPinyinAnalyser::NewL
       
    99 // (other items were commented in a header).
       
   100 // -----------------------------------------------------------------------------
       
   101 //
       
   102 CAknFepVkbPinyinAnalyser* CAknFepVkbPinyinAnalyser::NewL( CPinyinAnalyserDbFeed* aDb )
       
   103     {
       
   104     CAknFepVkbPinyinAnalyser* self = new ( ELeave ) CAknFepVkbPinyinAnalyser();
       
   105     CleanupStack::PushL(self);
       
   106     self->ConstructL( aDb ); 
       
   107     CleanupStack::Pop();
       
   108     return self;
       
   109     }  
       
   110       
       
   111 // -----------------------------------------------------------------------------
       
   112 // CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser
       
   113 // (other items were commented in a header).
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser()
       
   117     {
       
   118     delete []iParagraph;
       
   119     delete []iSpellLibrary;
       
   120     delete iLastResult;
       
   121     delete iDb;
       
   122     }
       
   123 
       
   124 
       
   125 void CAknFepVkbPinyinAnalyser::ConstructL( CPinyinAnalyserDbFeed* aDb )
       
   126     {
       
   127     ASSERT( aDb != NULL );
       
   128     iDb = aDb;
       
   129 
       
   130     TInt length = iDb->GetSpellCount();
       
   131     
       
   132     iSpellLibrary = new(ELeave) TPtrC[length];
       
   133     for(TInt i = 0; i < length; ++i )
       
   134         {
       
   135         iSpellLibrary[i].Set( aDb->GetSpellByIndex( i ) );
       
   136         }
       
   137         
       
   138     TInt current = 0;
       
   139     TInt pinyinElementCount = iDb->GetSpellElementCount();
       
   140     iParagraph = new(ELeave) TSpellBand[pinyinElementCount];
       
   141     iParagraph[current].iStart = 0;
       
   142     for(TInt i = 0; i < length; ++i )
       
   143         {
       
   144         if( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) )
       
   145             {
       
   146             iParagraph[current].iCount = i - iParagraph[current].iStart;
       
   147             current++;
       
   148             iParagraph[current].iStart = i;
       
   149             while( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) )
       
   150                 {
       
   151                 iParagraph[current].iCount = 0;
       
   152                 current ++;
       
   153                 iParagraph[current].iStart = i;
       
   154                 }
       
   155             }
       
   156         }
       
   157         
       
   158     iParagraph[current].iCount = length - iParagraph[current].iStart;
       
   159     
       
   160     }
       
   161  
       
   162     
       
   163 HBufC* CAknFepVkbPinyinAnalyser::LastAnalysisResult()
       
   164     {
       
   165     return iLastResult;
       
   166     }
       
   167 
       
   168 TBool CAknFepVkbPinyinAnalyser::AnalyzeL(const TDesC& aInputString)
       
   169     {
       
   170     delete iLastResult;
       
   171     iLastResult = NULL;
       
   172     
       
   173     iLastResult = HBufC::NewL(aInputString.Length() * 2);
       
   174     
       
   175     if( aInputString.Length() < 1 )
       
   176     {
       
   177         return ETrue;
       
   178     }
       
   179     
       
   180     if( aInputString.Length() == 1 )
       
   181         {
       
   182         iLastResult->Des().Append( aInputString[0] );
       
   183         if ( iDb->IsFirstElement( aInputString[0] )  )
       
   184             {
       
   185             return ETrue;
       
   186             }
       
   187         else 
       
   188             {
       
   189             return EFalse;
       
   190             }
       
   191         }
       
   192     
       
   193     int first = 0;
       
   194     int second = 1;
       
   195     int previous = 0;
       
   196     iAnalysisFlag = ETrue;
       
   197     //rough spilit
       
   198     for(; second < aInputString.Length(); first++, second++ )
       
   199         {
       
   200         if( !iDb->IsNormalElement(aInputString[first]) )
       
   201             {
       
   202             //go to detail analysis
       
   203             if( first > previous)
       
   204                 {
       
   205                 TPtrC toanalysis = aInputString.Mid(previous, first - previous);
       
   206                 DetailAnalyse(toanalysis);
       
   207                 }
       
   208                 
       
   209             iLastResult->Des().Append(aInputString[first]);
       
   210             previous = first + 1;
       
   211             }
       
   212         else if(!iDb->IsNormalElement(aInputString[second]) )
       
   213             {
       
   214             //go to detail analysis
       
   215             if( second > previous)
       
   216                 {
       
   217                 TPtrC toanalysis = aInputString.Mid(previous, second - previous);
       
   218                 DetailAnalyse(toanalysis);
       
   219                 }
       
   220                 
       
   221             iLastResult->Des().Append(aInputString[second]);
       
   222             previous = second + 1;
       
   223             first ++;
       
   224             second ++;
       
   225             }                    
       
   226         else if( iDb->GetSpellElementType( aInputString[first]) == ESpellVowel || 
       
   227                  iDb->GetSpellElementType( aInputString[second]) == ESpellVowel)
       
   228             {
       
   229             continue;
       
   230             }
       
   231         else if( iDb->GetSpellElementType( aInputString[first]) == ESpellConsonant || 
       
   232                  iDb->GetSpellElementType( aInputString[second]) == ESpellConsonant  )
       
   233             {
       
   234             //go to detail analysis
       
   235             TPtrC toanalysis = aInputString.Mid(previous, second - previous);
       
   236             DetailAnalyse(toanalysis);
       
   237             iLastResult->Des().Append(KProgramSeparator);
       
   238             previous = second;
       
   239             }
       
   240         else 
       
   241             {
       
   242             if( (aInputString[second] == L'h' && ( aInputString[first] == L'z' || 
       
   243                  aInputString[first] == L'c' || aInputString[first] == L's')) || //ch, sh, zh
       
   244                 (aInputString[second] == L'g' && aInputString[first] == L'n') || //ng
       
   245                 (aInputString[second] == L'n' && aInputString[first] == L'h') //hn 
       
   246                )
       
   247                 {
       
   248                 }
       
   249             else 
       
   250                 {
       
   251                 //go to detail analysis
       
   252                 TPtrC toanalysis = aInputString.Mid(previous, second - previous);
       
   253                 DetailAnalyse(toanalysis);
       
   254                 iLastResult->Des().Append(KProgramSeparator);
       
   255                 previous = second;
       
   256                 }
       
   257             }
       
   258         }
       
   259         
       
   260         if( aInputString.Length() <= previous || second > aInputString.Length()  )
       
   261             {
       
   262             return iAnalysisFlag;
       
   263             }
       
   264    
       
   265         TPtrC toanalysis = aInputString.Mid(previous, second - previous);
       
   266         DetailAnalyse(toanalysis);
       
   267         return iAnalysisFlag;
       
   268     }
       
   269     
       
   270 TSpellAnalysis* CreateTSpellAnalysisL()
       
   271     {
       
   272     return new(ELeave) TSpellAnalysis();
       
   273     }
       
   274 TBool CAknFepVkbPinyinAnalyser::DetailAnalyse(const TDesC& aInputString)
       
   275 {
       
   276     TPriQue<TSpellAnalysis> open;
       
   277     TSpellAnalysis* p = NULL;
       
   278     TRAP_IGNORE( p = CreateTSpellAnalysisL());
       
   279     
       
   280     open.Add(*p);
       
   281 
       
   282     int sameLength;
       
   283     int startPos;
       
   284     TBool findRes;
       
   285     TSpellAnalysis* pNext = NULL;
       
   286     
       
   287     while( !open.IsEmpty() )
       
   288     {
       
   289         pNext = open.First();
       
   290         pNext->Deque();
       
   291         
       
   292         startPos = pNext->GetStartPos();
       
   293         findRes = FindSpell(aInputString.Mid(startPos), sameLength);
       
   294         
       
   295         if( findRes || sameLength + startPos == aInputString.Length())
       
   296         {
       
   297             //got it!
       
   298             int start = 0;
       
   299             for( TInt j = 0; j < pNext->iSeparators.Count(); ++j )
       
   300                 {
       
   301                 iLastResult->Des().Append(aInputString.Mid(start, pNext->iSeparators[j] - start));
       
   302                 start = pNext->iSeparators[j];
       
   303                 iLastResult->Des().Append(KProgramSeparator);
       
   304                 }
       
   305                 
       
   306             iLastResult->Des().Append(aInputString.Mid(start, aInputString.Length() - start));
       
   307             break;
       
   308         }
       
   309         else if( sameLength == 0 )
       
   310         {
       
   311             delete pNext;
       
   312             pNext = NULL;
       
   313         }
       
   314         else
       
   315         {
       
   316             int partLength = sameLength - 1;
       
   317             while( partLength > 0 )
       
   318             {
       
   319                 int templen;
       
   320                 if( FindSpell(aInputString.Mid(startPos, partLength), templen) )
       
   321                 {
       
   322                     TSpellAnalysis* q = new TSpellAnalysis(*pNext);
       
   323                     q->AddSeparator(startPos + partLength);
       
   324                     open.Add(*q);
       
   325                 }
       
   326                 partLength --;
       
   327             }
       
   328             pNext->AddSeparator(startPos + sameLength);
       
   329             open.Add(*pNext);
       
   330         }
       
   331     }
       
   332     if( pNext )
       
   333     {
       
   334         delete pNext;
       
   335         pNext = NULL;
       
   336         while( !open.IsEmpty() )
       
   337         {
       
   338             TSpellAnalysis* p = open.First();
       
   339             p->Deque();
       
   340             delete p;
       
   341         }
       
   342         return true;
       
   343     }
       
   344     else
       
   345     {
       
   346     //not found
       
   347     /*
       
   348         FindSpell(aInputString, sameLength);
       
   349         int offset = 0;
       
   350         TBool rtn = sameLength > 0;
       
   351         while( sameLength > 0 )
       
   352         {
       
   353             iLastResult->Des().Append(aInputString.Mid(offset, sameLength));
       
   354             iLastResult->Des().Append(KProgramSeparator);
       
   355             offset += sameLength;
       
   356             FindSpell(aInputString.Mid(offset), sameLength);
       
   357         }
       
   358       */
       
   359         //FindSpell(aInputString, sameLength);
       
   360         int offset = 0;
       
   361 
       
   362         while( offset < aInputString.Length() )
       
   363         {
       
   364         FindSpell(aInputString.Mid(offset), sameLength);
       
   365         
       
   366         if( sameLength )
       
   367             {
       
   368             iLastResult->Des().Append(aInputString.Mid(offset, sameLength));
       
   369             iLastResult->Des().Append(KProgramSeparator);
       
   370             offset += sameLength;
       
   371             }
       
   372         else
       
   373             {
       
   374             iLastResult->Des().Append(aInputString.Mid(offset, 1));
       
   375             
       
   376             iLastResult->Des().Append(KProgramSeparator);
       
   377             
       
   378             offset += 1;
       
   379             }
       
   380         }
       
   381         if( iLastResult->Des()[ iLastResult->Length() - 1 ] == KProgramSeparator )
       
   382             {
       
   383             iLastResult->Des().SetLength( iLastResult->Length() - 1 );
       
   384             }
       
   385         iAnalysisFlag = EFalse;
       
   386         return EFalse;
       
   387     }
       
   388 }
       
   389 
       
   390 TBool CAknFepVkbPinyinAnalyser::FindSpell(const TDesC& aSpell, TInt& aSameLength)
       
   391 {
       
   392     int index = aSpell[0] - iDb->GetSpellElementByIndex( 0 );   
       
   393 
       
   394     int start = iParagraph[index].iStart;
       
   395     int end = iParagraph[index].iCount + iParagraph[index].iStart - 1;
       
   396     int mid = ( start + end ) >> 1;
       
   397     int result = 0;
       
   398     aSameLength = 0;
       
   399     while( mid > start && mid < end )
       
   400     {
       
   401         result = Compare(iSpellLibrary[mid], aSpell, aSameLength);
       
   402         if( result == 0 )
       
   403         {
       
   404             return true;
       
   405         }
       
   406         else if( result < 0 )
       
   407         {
       
   408             start = mid;
       
   409             mid = (start + end ) >> 1;
       
   410         }
       
   411         else
       
   412         {
       
   413             end = mid;
       
   414             mid = (start + end) >> 1;
       
   415         }
       
   416     }
       
   417     int newLength;
       
   418     if( result > 0 )
       
   419     {
       
   420         result = Compare(iSpellLibrary[start], aSpell, newLength);
       
   421     }
       
   422     else
       
   423     {
       
   424         result = Compare(iSpellLibrary[end], aSpell, newLength);
       
   425     }
       
   426     newLength > aSameLength ? aSameLength = newLength : aSameLength;
       
   427 
       
   428     return result == 0;
       
   429 }
       
   430 
       
   431 TInt CAknFepVkbPinyinAnalyser::Compare(const TDesC& aFirst, const TDesC& aSecond, 
       
   432                                        TInt& aSameLength)
       
   433     {
       
   434     aSameLength = 0;
       
   435     
       
   436     TInt length = aFirst.Length() > aSecond.Length() ? aSecond.Length() : aFirst.Length();
       
   437     
       
   438     for( TInt i = 0; i < length; ++i )
       
   439         {
       
   440         if( aFirst[i] != aSecond[i] )
       
   441             {
       
   442             return aFirst[i] - aSecond[i];
       
   443             }
       
   444             
       
   445         aSameLength ++;
       
   446         }
       
   447         
       
   448     return aFirst.Length() - aSecond.Length();
       
   449     }
       
   450 
       
   451 // End of File