diff -r 000000000000 -r eb1f2e154e89 textinput/peninputhwrfscn/src/peninputhwrengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textinput/peninputhwrfscn/src/peninputhwrengine.cpp Tue Feb 02 01:02:04 2010 +0200 @@ -0,0 +1,909 @@ +/* +* 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 HWR engine +* +*/ + + +//FEP INCLUDES +#include +#include +#include + +//USER INCLUDES +#include "peninputhwrengine.h" +#include "peninputhwrfscndatastore.h" + +// CONSTANT DEFINITION HEADER +#include "peninputhwrfscnstoreconstants.h" + +// --------------------------------------------------------------------------- +// SplitString() +// --------------------------------------------------------------------------- +// +static TInt SplitString( const TPtrC &aPtr, + TUint16 aSeperator, + RPointerArray& aStringArray ) + { + // phrase input mode + TInt start = 0; + TInt length = 0; + + for ( TInt i = 0; i < aPtr.Length(); i++ ) + { + if ( aPtr[i] == aSeperator ) + { + TPtrC segment( aPtr.Ptr() + start, length ); + TRAP_IGNORE( aStringArray.AppendL( segment.AllocL() ) ); + start += ( length + 1 ); + length = 0; + } + else + { + length++; + } + } + + if ( length ) + { + TPtrC segm( aPtr.Ptr() + start, length ); + TRAP_IGNORE( aStringArray.AppendL( segm.AllocL() ) ); + } + + return aStringArray.Count(); + } + +// --------------------------------------------------------------------------- +// Symbian constructor +// --------------------------------------------------------------------------- +// +CAknFepHwrEngine* CAknFepHwrEngine::NewL( CPtiEngine* aPtiEngine, + CPeninputHwrfscnDataStore* aOwner ) + { + CAknFepHwrEngine* self = new ( ELeave ) CAknFepHwrEngine(); + + CleanupStack::PushL( self ); + self->ConstructL( aPtiEngine, aOwner ); + CleanupStack::Pop( self );//self + + return self; + } + +// --------------------------------------------------------------------------- +// C++ constructor +// --------------------------------------------------------------------------- +// +CAknFepHwrEngine::CAknFepHwrEngine() + { + iNeedSetNumberMode = EFalse; + iNeedSetCase = EFalse; + iNeedSetRange = EFalse; + iRecognizer = NULL; + iOwnPtiEngine = EFalse; + } + +// --------------------------------------------------------------------------- +// destructor +// --------------------------------------------------------------------------- +// +CAknFepHwrEngine::~CAknFepHwrEngine() + { + if( iOwnPtiEngine ) + { + delete iPtiEngine; + } + delete iCustomKeymap; + + delete iIdle; + + iNeedPermittedRanges.Close(); + } + +// --------------------------------------------------------------------------- +// Second phase constructor +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::ConstructL( CPtiEngine* aPtiEngine, + CPeninputHwrfscnDataStore* aOwner ) + { + if( !aPtiEngine ) + { + iPtiEngine = CPtiEngine::NewL( ETrue ); + iOwnPtiEngine = ETrue; + } + else + { + iPtiEngine = aPtiEngine; + } + + iIdle = CIdle::NewL( CActive::EPriorityIdle ); + iOwner = aOwner; + } + +// --------------------------------------------------------------------------- +// Convert stroke end mark +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::ConvertStrokeEndMark( RArray& aTraceData, + TPoint aPnt1, TPoint aPnt2 ) + { + TInt count = aTraceData.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + if ( aTraceData[i] == aPnt1 ) + { + aTraceData.Remove( i ); + aTraceData.Insert( aPnt2, i ); + } + } + } + +// --------------------------------------------------------------------------- +// Do recoginize by engine +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::DoRecognizeL( const RArray& aTraceData, + RPointerArray& aCandidates ) + { + if ( !iRecognizer ) + { + DoIdleConstructL(); + } + + TPoint ctrlStrokeEndMark = iOwner->StrokeEndMarkFromControl(); + + if ( ctrlStrokeEndMark != iRecognizer->StrokeEndMark() ) + { + ConvertStrokeEndMark( CONST_CAST( RArray&, aTraceData ), + iOwner->StrokeEndMarkFromControl(), + iRecognizer->StrokeEndMark() ); + iOwner->SetStrokeEndMark(); // make control's stroke end mark info same to engine + } + + aCandidates.ResetAndDestroy(); + + //Do recognition for number only + if ( iOwner->IsNumberOnly() ) + { + DoRecognizeOfNumberOnly( aTraceData,aCandidates ); + return; + } + + TInt primaryCount = iRecognizer->Recognize( aTraceData, aCandidates ); + + // filter recognized candidate, set start position for all ranges + TPtrC ptr( KSeparator ); + + // remove uncessary aux candidate, including range separator + for ( TInt i=0; iCompare( KGestureBackspace ) == 0 ) + { + // convert backspace returned by engine, to make sure it display correctly. + *aCandidates[i] = KDisplayBackspace; + break; + } + } + + //reorder the secondary range + ReorderSecondaryRange( aCandidates ); + + // remove uncessary primary candidate + TInt totallyCount = aCandidates.Count(); + TInt removePos = iTotalCandidateNum; + + for ( TInt i = removePos; i < totallyCount; i++ ) + { + delete aCandidates[removePos]; + aCandidates.Remove( removePos ); + } + + // not allowing '-' to be the first char in chinese range + // not allowing '/' to be the first char in English and Number range + TPtrC dashPtr( KDash ); + TPtrC solidusPtr( KSolidus ); + if ( ( iPremaryRange == ERangeNative ) && + ( aCandidates[0]->Compare( dashPtr ) == 0 ) ) + { + *aCandidates[0] = *aCandidates[1]; + *aCandidates[1] = dashPtr; + } + else if ( ( ( iPremaryRange == ERangeEnglish ) || + ( iPremaryRange == ERangeNumber ) ) + && ( aCandidates[0]->Compare( solidusPtr ) == 0 ) ) + { + *aCandidates[0] = *aCandidates[1]; + *aCandidates[1] = solidusPtr; + } + } + +// --------------------------------------------------------------------------- +// Do recognition when the range is only number +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::DoRecognizeOfNumberOnly( const RArray& aTraceData, + RPointerArray& aCandidates ) + { + if ( iNumberMode == EAknEditorPlainNumberModeKeymap ) + { + TBuf buf; + buf.Append( KNumberString() ); + buf.Append( KGestureBackspace ); + iRecognizer->RecognizeWithCharSet( aTraceData, aCandidates, buf ); + } + else + { + iRecognizer->Recognize( aTraceData, aCandidates ); + } + + //find special char and do special handling + TInt count = aCandidates.Count(); + for ( TInt i = count - 1; i >= 0; i-- ) + { + //the space and enter are not allowed to be appeared in candidates + if( ( *aCandidates[i] )[0] == KGestureSpace()[0] || + ( *aCandidates[i] )[0] == KGestureEnter()[0] ) + { + delete aCandidates[i]; + aCandidates.Remove( i ); + } + else if( aCandidates[i]->Compare( KGestureBackspace ) == 0 ) + { + *aCandidates[i] = KDisplayBackspace; + } + } + + if ( iCustomKeymap ) + { + count = aCandidates.Count(); + for( TInt i = count - 1; i >= 0; i-- ) + { + if( iCustomKeymap->Find( *aCandidates[i] ) == KErrNotFound ) + { + delete aCandidates[i]; + aCandidates.Remove( i ); + } + } + } + + // remove uncessary primary candidate + count = aCandidates.Count() - iTotalCandidateNum; + for ( TInt i = 0; i < count; i++ ) + { + delete aCandidates[iTotalCandidateNum]; + aCandidates.Remove( iTotalCandidateNum ); + } + } + +// --------------------------------------------------------------------------- +// Reorder secondary range in candidate list +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::ReorderSecondaryRange( RPointerArray& aCandidates ) + { + if( iRangeCount <= 1 ) + { + return; + } + + RPointerArray secondary; + TInt auxCandidateNum = GetAuxCandidateNum(); + + HBufC* secCandidate = NULL; + TInt candiateCount = aCandidates.Count(); + + TInt primaryCountFromEng = 0; + + // Get all secondary candidates + for( TInt i = 0; i < candiateCount; i++ )// "i" is the index of separater + { + if( aCandidates[i]->CompareC( KSeparator ) == 0 ) + { + if(primaryCountFromEng == 0) + { + // Save the primary candidates count from ptiengine + primaryCountFromEng = i; + } + TInt auxCountFromEng = 0; + while(i < candiateCount - 1 && aCandidates[++i]->CompareC( KSeparator ) != 0) + { + // calculate the secondary range candidate count + auxCountFromEng++; + + // Copy all the secondary candidate to an array + secCandidate = aCandidates[i]->Alloc(); + secondary.Append( secCandidate ); + } + + for(TInt j = 0; j < auxCandidateNum - auxCountFromEng ; j++ ) + { + // supply empty secondary candidate when engine not return + // enough cell + secondary.Append( KNullDesC().Alloc() ); + } + i--; // go back to the separator index + } + } + + + // caculate the primary candidate count + TInt primaryCount = 0; + TInt rowCount = 0; + + if( iPremaryRange == ERangeNumber ) + { + primaryCount = KCandidateCountNumMode - iRangeCount + 1; + rowCount = 1; + } + else + { + primaryCount = KCandidateCountPerRow - iRangeCount + 1; + rowCount = KCandidateRowCount; + } + + // supply empty primary candidate when engine not return + // enough cell + if(primaryCountFromEng < primaryCount * rowCount) + { + for(TInt y = 0; y < primaryCount * rowCount - primaryCountFromEng; y++) + { + aCandidates.Insert( KNullDesC().Alloc(), primaryCountFromEng ); + } + } + + // insert secondary candidates into the end of each row + for( ; rowCount > 0; rowCount-- ) + { + for( TInt m = 0; m < iRangeCount - 1; m++ ) + { + TInt secondaryIndex = rowCount - 1 + m * auxCandidateNum; + TInt insertPos = primaryCount * rowCount + m; + aCandidates.Insert( secondary[secondaryIndex], insertPos ); + } + } + secondary.Reset(); + secondary.Close(); + } + + +// --------------------------------------------------------------------------- +// Do predictive using trigger string +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::DoPredictiveL( const TDesC& aTriggerStr, + RPointerArray& aPredictives, + TBool aNextPage ) + { + // predictive only valid for Chinese + if ( ( iLanguage != ELangPrcChinese ) && + ( iLanguage != ELangTaiwanChinese ) && + ( iLanguage != ELangHongKongChinese ) ) + { + return; + } + + // activate correct pti language according to given language + if ( !aNextPage ) + { + iPtiEngine->SetCandidatePageLength( KPredictiveCountPerPage ); + + aPredictives.ResetAndDestroy(); + if( !iPtiEngine->SetPredictiveChineseChar( aTriggerStr ) ) + { + return; + } + } + else + { + if ( !iPtiEngine->NextCandidatePage() ) + { + return; + } + } + + TPtrC ptr = iPtiEngine->CandidatePage(); + + if ( ( iPtiEngine->InputMode() == EPtiEnginePinyinVkb ) || + ( iPtiEngine->InputMode() == EPtiEngineStrokeByPhrase ) || + ( iPtiEngine->InputMode() == EPtiEngineZhuyinVkb ) ) + { + SplitString( ptr, KSegment, aPredictives ); + } + else + { + TInt predictiveCandidateNum = ptr.Length(); + + for ( TInt i=0; i& aHomophonic ) + { + // homophonic only valid for PRC Chinese and Taiwan Chinese + if ( ( iLanguage == ELangPrcChinese ) || + ( iLanguage == ELangTaiwanChinese ) ) + { + iPtiEngine->SetCandidatePageLength( KMaxHomophonicCandidateCount ); + aHomophonic.ResetAndDestroy(); + + // get the spelling of the character + TBuf spelling; + TPtiSpelling spellingType = EPtiPinyin; + + if ( iPtiEngine->InputMode() == EPtiEnginePinyinVkb ) + { + spellingType = EPtiPinyin; + } + else if ( iPtiEngine->InputMode() == EPtiEngineZhuyinVkb ) + { + spellingType = EPtiZhuyin; + } + + TInt result = iPtiEngine->GetSpelling( aTriggerStr[0], + spelling, spellingType ); + if( KErrNone != result ) + { + return; + } + + // get homophonic or polyphonic candidates by spelling + GetHomophonicAndPolyphonic( spelling, aHomophonic ); + + // delete the repeated characters + TInt count = aHomophonic.Count(); + for ( TInt i = count - 1; i >= 0; i-- ) + { + if ( aTriggerStr == *( aHomophonic[i] ) ) + { + delete aHomophonic[i]; + aHomophonic.Remove( i ); + } + } + // remove the seleted character to the first cell + aHomophonic.Insert( aTriggerStr.AllocL(), 0 ); + } + } + +// --------------------------------------------------------------------------- +// Get homophonic or polyphonic candidates +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::GetHomophonicAndPolyphonic( TDes& aSpelling, + RPointerArray& aHomophonic ) + { + TInt index = KErrNotFound; + TBuf tmpSpelling; + + while( aSpelling != KNullDesC16 ) + { + tmpSpelling.Zero(); + // find the separator + index = aSpelling.Find( KPolyphonicSeparator ); + if( index != KErrNotFound ) + { + // get one spelling in the polyphonic string + tmpSpelling = aSpelling.Left( index ); + + // remove the left spelling and a separator + aSpelling = aSpelling.Right( aSpelling.Length() - index - 1 ); + } + else // only one spelling + { + tmpSpelling = aSpelling; + aSpelling = KNullDesC16; + } + + // get candidate for each spelling + RPointerArray candidates; + HBufC* formatString = iPtiEngine->GetCandidatesByInputString( + tmpSpelling, + candidates, + EFalse ); + + for( TInt i = 0; i < candidates.Count(); i++ ) + { + aHomophonic.Append( candidates[i] ); + } + delete formatString; + candidates.Reset(); + } + } + + +// --------------------------------------------------------------------------- +// Set primary and auxiliary ranges for hwr engine +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetRanges( const RArray& aPermittedRanges ) + { + ASSERT( aPermittedRanges.Count() > 0 ); + + if ( !iRecognizer ) + { + iNeedPermittedRanges.Reset(); + + for ( TInt i = 0; i < aPermittedRanges.Count(); i++ ) + { + iNeedPermittedRanges.Append( aPermittedRanges[i] ); + } + + iNeedSetRange = ETrue; + return; + } + else + { + iPremaryRange = aPermittedRanges[0]; + iRangeCount = aPermittedRanges.Count(); + + if( iPremaryRange == ERangeNumber ) + { + SetCandidatesMaxCount( KCandidateCountNumMode ); + SetAuxCandidateNum( KAuxCandidateCountNumMode ); + } + else + { + SetCandidatesMaxCount( KCandidateCount ); + SetAuxCandidateNum( KAuxCandidateCount ); + } + + TRecognitionRange range; + + SetRecognitionRange( aPermittedRanges[0], range ); + iRecognizer->SetRange( range ); + + // set auxiliary ranges for hwr engine + for ( TInt i=1; iAddAuxiliaryRange( range ); + } + + SetCase( iCase ); + } + } + + +// --------------------------------------------------------------------------------------------- +// Set case +// --------------------------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetCase( TInt aCase ) + { + iCase = aCase; + + if ( !iRecognizer ) + { + iNeedSetCase = ETrue; + } + else + { + // set letter to lower first when LowerCase + // set letter to upper first when UpperCase and TextCase + if ( aCase == ECaseLower ) + { + iRecognizer->SetFirstLetterOrder( ELowerFirst ); + } + else + { + iRecognizer->SetFirstLetterOrder( EUpperFirst ); + } + } + } + +// --------------------------------------------------------------------------------------------- +// Set number mode for hwr engine +// --------------------------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetNumberMode( const TAknEditorNumericKeymap& aNumberMode ) + { + iNumberMode = aNumberMode; + + if ( !iRecognizer ) + { + iNeedSetNumberMode = ETrue; + } + else + { + iRecognizer->SetNumberMode( aNumberMode ); + if( aNumberMode != EKeymapFromResource ) + { + ResetCustomKeyMap(); + } + } + } + +// --------------------------------------------------------------------------------------------- +// Get stroke end mark from hwr engine +// --------------------------------------------------------------------------------------------- +// +TPoint CAknFepHwrEngine::StrokeEndMark() const + { + if ( iRecognizer ) + { + return iRecognizer->StrokeEndMark(); + } + else + { + return TPoint( KDefaultStrokeEndMarkX, KDefaultStrokeEndMarkY ); + } + } + +// --------------------------------------------------------------------------------------------- +// Set primary candidate num for hwr engine +// --------------------------------------------------------------------------------------------- +// +TInt CAknFepHwrEngine::SetPrimaryCandidateNum( TInt aNum ) + { + if ( iRecognizer ) + { + return iRecognizer->SetCandidateNum( aNum ); + } + else + { + return KErrGeneral; + } + } + +// --------------------------------------------------------------------------------------------- +// Set aux candidate num that should be shown +// --------------------------------------------------------------------------------------------- +// +TInt CAknFepHwrEngine::SetAuxCandidateNum( TInt aNum ) + { + if ( iRecognizer ) + { + return iRecognizer->SetAuxCandidateNum( aNum ); + } + else + { + return KErrGeneral; + } + } + + +// --------------------------------------------------------------------------------------------- +// Get aux candidate num that should be shown +// --------------------------------------------------------------------------------------------- +// +TInt CAknFepHwrEngine::GetAuxCandidateNum() + { + if ( iRecognizer ) + { + return iRecognizer->GetAuxCandidateNum(); + } + else + { + return KErrGeneral; + } + } + +// --------------------------------------------------------------------------------------------- +// Set total candidate num that should be shown +// --------------------------------------------------------------------------------------------- +// +TInt CAknFepHwrEngine::SetCandidatesMaxCount( TInt aCount ) + { + if ( aCount > 0 ) + { + iTotalCandidateNum = aCount; + return KErrNone; + } + else + { + return KErrGeneral; + } + } + +// --------------------------------------------------------------------------------------------- +// Set language +// --------------------------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetLanguageL( TInt aLanguage ) + { + if ( ( iLanguage == aLanguage ) || + ( aLanguage != ELangPrcChinese && + aLanguage != ELangHongKongChinese && + aLanguage != ELangTaiwanChinese ) ) + { + return; + } + + iLanguage = aLanguage; + switch ( iLanguage ) + { + case ELangPrcChinese: + { + if ( iPtiEngine->ActivateLanguageL( iLanguage, EPtiEnginePinyinVkb ) != KErrNone ) + { + iPtiEngine->ActivateLanguageL( iLanguage, EPtiEnginePinyin ); + } + } + break; + case ELangHongKongChinese: + if ( iPtiEngine->ActivateLanguageL( iLanguage, EPtiEngineStrokeByPhrase ) != KErrNone ) + { + iPtiEngine->ActivateLanguageL( ELangHongKongChinese, EPtiEngineStroke ); + } + break; + case ELangTaiwanChinese: + if ( iPtiEngine->ActivateLanguageL( iLanguage, EPtiEngineZhuyinVkb ) != KErrNone ) + { + iPtiEngine->ActivateLanguageL( ELangTaiwanChinese, EPtiEngineZhuyin ); + } + break; + default: + return; + } + + iRecognizer = NULL; + + if( !iIdle->IsActive() ) + { + iIdle->Start( TCallBack( BackgroundTaskL, this ) ); + } + } + +// --------------------------------------------------------------------------------------------- +// CAknFepHwrEngine::DoIdleConstructL +// Do background construct. +// --------------------------------------------------------------------------------------------- +// +void CAknFepHwrEngine::DoIdleConstructL() + { + if ( iRecognizer ) + { + return; + } + + iRecognizer = iPtiEngine->GetHwrRecognizerL( TLanguage( iLanguage ) ); + + iOwner->SetStrokeEndMark(); + SetPrimaryCandidateNum( KPremaryCandidateCount ); + SetAuxCandidateNum( KAuxCandidateCount ); + + if ( iNeedSetRange ) + { + SetRanges( iNeedPermittedRanges ); + iNeedPermittedRanges.Reset(); + iNeedSetRange = EFalse; + } + + if ( iNeedSetCase ) + { + SetCase( iCase ); + iNeedSetCase = EFalse; + } + + if ( iNeedSetNumberMode ) + { + SetNumberMode( TAknEditorNumericKeymap( iNumberMode ) ); + iNeedSetNumberMode = EFalse; + } + } + +// --------------------------------------------------------------------------------------------- +// CAknFepHwrEngine::BackgroundConstructL +// Do background construct. +// --------------------------------------------------------------------------------------------- +// +TBool CAknFepHwrEngine::BackgroundTaskL( TAny* aPtr ) + { + CAknFepHwrEngine* self = static_cast( aPtr ); + self->DoIdleConstructL(); + return EFalse; + } + +// --------------------------------------------------------------------------- +// Set recognition range for hwr engine +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetRecognitionRange( const TInt aRange, + TRecognitionRange& aRecognitionRange ) + { + aRecognitionRange.iLanguage = TLanguage( iLanguage ); + + switch ( aRange ) + { + case ERangeNative: + { + if ( iLanguage == ELangPrcChinese ) + { + aRecognitionRange.iSubRange = EPtiRangePRCChinese; + } + else if ( iLanguage == ELangHongKongChinese ) + { + aRecognitionRange.iSubRange = EPtiRangeHKChinese; + } + else + { + aRecognitionRange.iSubRange = EPtiRangeTWChinese; + } + break; + } + case ERangeEnglish: + aRecognitionRange.iLanguage = ELangEnglish; + aRecognitionRange.iSubRange = EPtiRangeLatin; + + break; + case ERangeNumber: + aRecognitionRange.iSubRange = EPtiRangeNumber; + + break; + case ERangeSymbol: + // The symbol mode is associated with iLanguage instead of iPremaryRange + aRecognitionRange.iLanguage = TLanguage( iLanguage ); + aRecognitionRange.iSubRange = EPtiRangeSymbol; + + break; + default: + break; + } + } + +// --------------------------------------------------------------------------- +// Set recognition range for hwr engine +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::SetCustomKeymapL( const TDesC& aKeyMap ) + { + ResetCustomKeyMap(); + + iCustomKeymap = HBufC::NewL( aKeyMap.Length() + KNumberString().Length() ); + iCustomKeymap->Des().Copy( KNumberString() ); + iCustomKeymap->Des().Append( aKeyMap ); + } + +// --------------------------------------------------------------------------- +// Set recognition range for hwr engine +// --------------------------------------------------------------------------- +// +void CAknFepHwrEngine::ResetCustomKeyMap() + { + delete iCustomKeymap; + iCustomKeymap = NULL; + } +TInt CAknFepHwrEngine::SetInputAreaSize(TSize& aSize) + { + if(iRecognizer) + { + return iRecognizer->SetInputAreaSize(aSize); + } + else + { + return KErrNotFound; + } + } +TInt CAknFepHwrEngine::SetScreenSize(TSize& aSize) + { + if(iRecognizer) + { + return iRecognizer->SetScreenSize(aSize); + } + else + { + return KErrNotFound; + } + } +//End Of File