textinput/peninputvkbcn/ctrlsrc/AknFepVkbPinyinAnalyser.cpp
changeset 0 eb1f2e154e89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textinput/peninputvkbcn/ctrlsrc/AknFepVkbPinyinAnalyser.cpp	Tue Feb 02 01:02:04 2010 +0200
@@ -0,0 +1,451 @@
+/*
+* Copyright (c) 2002-2005 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:  Implementation of the vkb data manager
+*
+*/
+
+
+// system includes
+
+
+// user includes
+#include "AknFepVkbPinyinAnalyser.h"
+#include "AknFepVkbPinyinAnalyserDb.h"
+
+class TSpellBand
+{
+public:
+    int iStart;
+    int iCount;
+}; 
+
+
+class TSpellAnalysis : public TPriQueLink  
+{
+public:
+    RArray<TInt> iSeparators;
+    TSpellAnalysis()
+    {
+        iPriority = -0x10000;
+    }
+    ~TSpellAnalysis()
+        {
+        iSeparators.Close();
+        }
+        
+    TSpellAnalysis(const TSpellAnalysis& aSource)
+    {
+        iPriority = aSource.iPriority;
+        for( TInt i = 0; i < aSource.iSeparators.Count(); ++i )
+        {
+            iSeparators.Append(aSource.iSeparators[i]);
+        }
+    }
+    void Calculate()
+    {
+        iPriority = (iSeparators.Count() + 1) << 16;
+        TInt multi = 12;
+        for( TInt i = 0; i < iSeparators.Count(); ++i )
+        {
+            iPriority += ( 6 - iSeparators[i]) << multi; 
+            if( multi >= 3 )
+            {
+                multi -= 3;
+            }            
+        }
+        iPriority = -iPriority;
+    }
+    TInt GetStartPos()
+    {
+        if( iSeparators.Count() == 0)
+        {
+            return 0;
+        }
+        else
+        {
+            return iSeparators[ iSeparators.Count() - 1 ];
+        }
+    }
+    void AddSeparator(TInt aPos)
+    {
+        iSeparators.Append(aPos);
+        Calculate();
+    }
+};
+
+// -----------------------------------------------------------------------------
+// CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser()
+    {
+    iAnalysisFlag = EFalse;
+    }
+       
+// -----------------------------------------------------------------------------
+// CAknFepVkbPinyinAnalyser::NewL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CAknFepVkbPinyinAnalyser* CAknFepVkbPinyinAnalyser::NewL( CPinyinAnalyserDbFeed* aDb )
+    {
+    CAknFepVkbPinyinAnalyser* self = new ( ELeave ) CAknFepVkbPinyinAnalyser();
+    CleanupStack::PushL(self);
+    self->ConstructL( aDb ); 
+    CleanupStack::Pop();
+    return self;
+    }  
+      
+// -----------------------------------------------------------------------------
+// CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser()
+    {
+    delete []iParagraph;
+    delete []iSpellLibrary;
+    delete iLastResult;
+    delete iDb;
+    }
+
+
+void CAknFepVkbPinyinAnalyser::ConstructL( CPinyinAnalyserDbFeed* aDb )
+    {
+    ASSERT( aDb != NULL );
+    iDb = aDb;
+
+    TInt length = iDb->GetSpellCount();
+    
+    iSpellLibrary = new(ELeave) TPtrC[length];
+    for(TInt i = 0; i < length; ++i )
+        {
+        iSpellLibrary[i].Set( aDb->GetSpellByIndex( i ) );
+        }
+        
+    TInt current = 0;
+    TInt pinyinElementCount = iDb->GetSpellElementCount();
+    iParagraph = new(ELeave) TSpellBand[pinyinElementCount];
+    iParagraph[current].iStart = 0;
+    for(TInt i = 0; i < length; ++i )
+        {
+        if( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) )
+            {
+            iParagraph[current].iCount = i - iParagraph[current].iStart;
+            current++;
+            iParagraph[current].iStart = i;
+            while( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) )
+                {
+                iParagraph[current].iCount = 0;
+                current ++;
+                iParagraph[current].iStart = i;
+                }
+            }
+        }
+        
+    iParagraph[current].iCount = length - iParagraph[current].iStart;
+    
+    }
+ 
+    
+HBufC* CAknFepVkbPinyinAnalyser::LastAnalysisResult()
+    {
+    return iLastResult;
+    }
+
+TBool CAknFepVkbPinyinAnalyser::AnalyzeL(const TDesC& aInputString)
+    {
+    delete iLastResult;
+    iLastResult = NULL;
+    
+    iLastResult = HBufC::NewL(aInputString.Length() * 2);
+    
+    if( aInputString.Length() < 1 )
+    {
+        return ETrue;
+    }
+    
+    if( aInputString.Length() == 1 )
+        {
+        iLastResult->Des().Append( aInputString[0] );
+        if ( iDb->IsFirstElement( aInputString[0] )  )
+            {
+            return ETrue;
+            }
+        else 
+            {
+            return EFalse;
+            }
+        }
+    
+    int first = 0;
+    int second = 1;
+    int previous = 0;
+    iAnalysisFlag = ETrue;
+    //rough spilit
+    for(; second < aInputString.Length(); first++, second++ )
+        {
+        if( !iDb->IsNormalElement(aInputString[first]) )
+            {
+            //go to detail analysis
+            if( first > previous)
+                {
+                TPtrC toanalysis = aInputString.Mid(previous, first - previous);
+                DetailAnalyse(toanalysis);
+                }
+                
+            iLastResult->Des().Append(aInputString[first]);
+            previous = first + 1;
+            }
+        else if(!iDb->IsNormalElement(aInputString[second]) )
+            {
+            //go to detail analysis
+            if( second > previous)
+                {
+                TPtrC toanalysis = aInputString.Mid(previous, second - previous);
+                DetailAnalyse(toanalysis);
+                }
+                
+            iLastResult->Des().Append(aInputString[second]);
+            previous = second + 1;
+            first ++;
+            second ++;
+            }                    
+        else if( iDb->GetSpellElementType( aInputString[first]) == ESpellVowel || 
+                 iDb->GetSpellElementType( aInputString[second]) == ESpellVowel)
+            {
+            continue;
+            }
+        else if( iDb->GetSpellElementType( aInputString[first]) == ESpellConsonant || 
+                 iDb->GetSpellElementType( aInputString[second]) == ESpellConsonant  )
+            {
+            //go to detail analysis
+            TPtrC toanalysis = aInputString.Mid(previous, second - previous);
+            DetailAnalyse(toanalysis);
+            iLastResult->Des().Append(KProgramSeparator);
+            previous = second;
+            }
+        else 
+            {
+            if( (aInputString[second] == L'h' && ( aInputString[first] == L'z' || 
+                 aInputString[first] == L'c' || aInputString[first] == L's')) || //ch, sh, zh
+                (aInputString[second] == L'g' && aInputString[first] == L'n') || //ng
+                (aInputString[second] == L'n' && aInputString[first] == L'h') //hn 
+               )
+                {
+                }
+            else 
+                {
+                //go to detail analysis
+                TPtrC toanalysis = aInputString.Mid(previous, second - previous);
+                DetailAnalyse(toanalysis);
+                iLastResult->Des().Append(KProgramSeparator);
+                previous = second;
+                }
+            }
+        }
+        
+        if( aInputString.Length() <= previous || second > aInputString.Length()  )
+            {
+            return iAnalysisFlag;
+            }
+   
+        TPtrC toanalysis = aInputString.Mid(previous, second - previous);
+        DetailAnalyse(toanalysis);
+        return iAnalysisFlag;
+    }
+    
+TSpellAnalysis* CreateTSpellAnalysisL()
+    {
+    return new(ELeave) TSpellAnalysis();
+    }
+TBool CAknFepVkbPinyinAnalyser::DetailAnalyse(const TDesC& aInputString)
+{
+    TPriQue<TSpellAnalysis> open;
+    TSpellAnalysis* p = NULL;
+    TRAP_IGNORE( p = CreateTSpellAnalysisL());
+    
+    open.Add(*p);
+
+    int sameLength;
+    int startPos;
+    TBool findRes;
+    TSpellAnalysis* pNext = NULL;
+    
+    while( !open.IsEmpty() )
+    {
+        pNext = open.First();
+        pNext->Deque();
+        
+        startPos = pNext->GetStartPos();
+        findRes = FindSpell(aInputString.Mid(startPos), sameLength);
+        
+        if( findRes || sameLength + startPos == aInputString.Length())
+        {
+            //got it!
+            int start = 0;
+            for( TInt j = 0; j < pNext->iSeparators.Count(); ++j )
+                {
+                iLastResult->Des().Append(aInputString.Mid(start, pNext->iSeparators[j] - start));
+                start = pNext->iSeparators[j];
+                iLastResult->Des().Append(KProgramSeparator);
+                }
+                
+            iLastResult->Des().Append(aInputString.Mid(start, aInputString.Length() - start));
+            break;
+        }
+        else if( sameLength == 0 )
+        {
+            delete pNext;
+            pNext = NULL;
+        }
+        else
+        {
+            int partLength = sameLength - 1;
+            while( partLength > 0 )
+            {
+                int templen;
+                if( FindSpell(aInputString.Mid(startPos, partLength), templen) )
+                {
+                    TSpellAnalysis* q = new TSpellAnalysis(*pNext);
+                    q->AddSeparator(startPos + partLength);
+                    open.Add(*q);
+                }
+                partLength --;
+            }
+            pNext->AddSeparator(startPos + sameLength);
+            open.Add(*pNext);
+        }
+    }
+    if( pNext )
+    {
+        delete pNext;
+        pNext = NULL;
+        while( !open.IsEmpty() )
+        {
+            TSpellAnalysis* p = open.First();
+            p->Deque();
+            delete p;
+        }
+        return true;
+    }
+    else
+    {
+    //not found
+    /*
+        FindSpell(aInputString, sameLength);
+        int offset = 0;
+        TBool rtn = sameLength > 0;
+        while( sameLength > 0 )
+        {
+            iLastResult->Des().Append(aInputString.Mid(offset, sameLength));
+            iLastResult->Des().Append(KProgramSeparator);
+            offset += sameLength;
+            FindSpell(aInputString.Mid(offset), sameLength);
+        }
+      */
+        //FindSpell(aInputString, sameLength);
+        int offset = 0;
+
+        while( offset < aInputString.Length() )
+        {
+        FindSpell(aInputString.Mid(offset), sameLength);
+        
+        if( sameLength )
+            {
+            iLastResult->Des().Append(aInputString.Mid(offset, sameLength));
+            iLastResult->Des().Append(KProgramSeparator);
+            offset += sameLength;
+            }
+        else
+            {
+            iLastResult->Des().Append(aInputString.Mid(offset, 1));
+            
+            iLastResult->Des().Append(KProgramSeparator);
+            
+            offset += 1;
+            }
+        }
+        if( iLastResult->Des()[ iLastResult->Length() - 1 ] == KProgramSeparator )
+            {
+            iLastResult->Des().SetLength( iLastResult->Length() - 1 );
+            }
+        iAnalysisFlag = EFalse;
+        return EFalse;
+    }
+}
+
+TBool CAknFepVkbPinyinAnalyser::FindSpell(const TDesC& aSpell, TInt& aSameLength)
+{
+    int index = aSpell[0] - iDb->GetSpellElementByIndex( 0 );   
+
+    int start = iParagraph[index].iStart;
+    int end = iParagraph[index].iCount + iParagraph[index].iStart - 1;
+    int mid = ( start + end ) >> 1;
+    int result = 0;
+    aSameLength = 0;
+    while( mid > start && mid < end )
+    {
+        result = Compare(iSpellLibrary[mid], aSpell, aSameLength);
+        if( result == 0 )
+        {
+            return true;
+        }
+        else if( result < 0 )
+        {
+            start = mid;
+            mid = (start + end ) >> 1;
+        }
+        else
+        {
+            end = mid;
+            mid = (start + end) >> 1;
+        }
+    }
+    int newLength;
+    if( result > 0 )
+    {
+        result = Compare(iSpellLibrary[start], aSpell, newLength);
+    }
+    else
+    {
+        result = Compare(iSpellLibrary[end], aSpell, newLength);
+    }
+    newLength > aSameLength ? aSameLength = newLength : aSameLength;
+
+    return result == 0;
+}
+
+TInt CAknFepVkbPinyinAnalyser::Compare(const TDesC& aFirst, const TDesC& aSecond, 
+                                       TInt& aSameLength)
+    {
+    aSameLength = 0;
+    
+    TInt length = aFirst.Length() > aSecond.Length() ? aSecond.Length() : aFirst.Length();
+    
+    for( TInt i = 0; i < length; ++i )
+        {
+        if( aFirst[i] != aSecond[i] )
+            {
+            return aFirst[i] - aSecond[i];
+            }
+            
+        aSameLength ++;
+        }
+        
+    return aFirst.Length() - aSecond.Length();
+    }
+
+// End of File