diff -r 000000000000 -r eb1f2e154e89 textinput/peninputvkbcn/ctrlsrc/peninputvkbcompositionfield.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textinput/peninputvkbcn/ctrlsrc/peninputvkbcompositionfield.cpp Tue Feb 02 01:02:04 2010 +0200 @@ -0,0 +1,1479 @@ +/* +* 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: vkb conposition field implementation +* +*/ + + +#include + +#include +#include + +#include "peninputvkbcompositionfield.h" + +#include "peninputvkbevent.h" + +#include "peninputvkb.hrh" + +#include "peninputvkbdataprovider.h" + +#include "AknFepVkbPinyinAnalyser.h" + +#include "AknFepVkbPinyinAnalyserDb.h" +#include "peninputvkbdatamgr.h" + +//Tone make +const TUint16 KCharToneMarkZhuyin1 = 0x0020; +const TUint16 KCharToneMarkPinyin1 = 0x02C9; +const TUint16 KCharToneMark2 = 0x02CA; +const TUint16 KCharToneMark3 = 0x02C7; +const TUint16 KCharToneMark4 = 0x02CB; +const TUint16 KCharToneMark5 = 0x02D9; + +const TInt32 KInvalidResId = -1; + +const TInt KInvalidImg = -1 ; + +//Manual stroke separator char +const TUint16 KStrokeManuSeparator = 0x2022; +//Manul separator char +const TUint KManulSeparator = 0x0027; // "'" +//Manul separator char +const TUint KAutoSeparator = 0x002e; //"." + + +_LIT(KWildChar, "\xFF1F"); + +_LIT(KInternalWildChar, "\x002B"); + +// --------------------------------------------------------- +// Helper function +// --------------------------------------------------------- +// +//Don't test aKey's length, treat as programming error! +inline TBool IsKeyToneMark(const TDesC& aKey) + { + return (aKey[0] == KCharToneMarkZhuyin1 || + aKey[0] == KCharToneMarkPinyin1 || + aKey[0] == KCharToneMark2 || + aKey[0] == KCharToneMark3 || + aKey[0] == KCharToneMark4 || + aKey[0] == KCharToneMark5 ); + } + +inline TBool IsKeyAutoSeparator(const TDesC& aKey) + { + return (aKey[0] == KAutoSeparator ); + } + +inline TBool IsKeyManualSeparator(const TDesC& aKey) + { + return (aKey[0] == KManulSeparator || aKey[0] == KStrokeManuSeparator); + } + +inline TBool IsKeyInternalWildChar(const TDesC& aKey) + { + return (aKey[0] == KInternalWildChar()[0] ); + } + + + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CCompositionElement* CCompositionElement::NewLC(const TDesC& aKey) + { + TInt keyType = EElementTypeCompositionChar; + if( IsKeyAutoSeparator(aKey) ) + { + keyType = EElementTypeAutoSeparator; + } + else if( IsKeyManualSeparator(aKey) ) + { + keyType = EElementTypeManualSeparator; + } + else if( IsKeyToneMark(aKey) ) + { + keyType = EElementTypeTonemark; + } + + CCompositionElement* self = new (ELeave) CCompositionElement(keyType); + + CleanupStack::PushL(self); + + if( IsKeyInternalWildChar(aKey) ) + { + self->BaseConstructL(KWildChar); + } + else + { + self->BaseConstructL(aKey); + } + + + return self; + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CCompositionElement::CCompositionElement(TInt aKeyType) +:iKeyType(aKeyType) + { + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +void CCompositionElement::BaseConstructL(const TDesC& aKey) + { + iKey = aKey.AllocL(); + } + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CCompositionElement::~CCompositionElement() + { + delete iKey; + } + +// --------------------------------------------------------- +// Get original input length +// --------------------------------------------------------- +// +TInt CCompositionElement::OriginalCount() const + { + TInt result = (IsAutoSeparator() || !iKey)? 0 : iKey->Length(); + + return result; + } + +// --------------------------------------------------------- +// UnConvert and insert the original elements back +// --------------------------------------------------------- +// +TInt CCompositionElement::UndoConvertL(CAknFepVkbCompositionField* /*aField*/, TInt /*aStartPos*/) + { + return 0; + } + +// --------------------------------------------------------- +// Get the content of original input +// --------------------------------------------------------- +// +const CCompositionElement* CCompositionElement::OriginalContent( TInt /*aIndex*/ ) const + { + return NULL; + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CCompositionConvertedElement* CCompositionConvertedElement::NewLC(const TDesC& aKey) + { + CCompositionConvertedElement* self = new (ELeave) CCompositionConvertedElement(); + + CleanupStack::PushL(self); + self->ConstructL(aKey); + + return self; + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CCompositionConvertedElement::CCompositionConvertedElement() +:CCompositionElement(EElementTypeConvertedChar) + { + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +void CCompositionConvertedElement::ConstructL(const TDesC& aKey) + { + BaseConstructL(aKey); + } + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CCompositionConvertedElement::~CCompositionConvertedElement() + { + iOriginalElements.ResetAndDestroy(); + iOriginalElements.Close(); + } + +// --------------------------------------------------------- +// UnConvert and insert the original elements back +// --------------------------------------------------------- +// +TInt CCompositionConvertedElement::UndoConvertL(CAknFepVkbCompositionField* aField, + TInt aStartPos) + { + ASSERT(aStartPos >=0 && aStartPos < aField->Length()); + + TInt length = iOriginalElements.Count(); + + for (TInt i = length -1 ; i >= 0 ; i --) + { + aField->InsertL(aStartPos, iOriginalElements[i] ); + + //ownership transfer to CAknFepVkbCompositionField + iOriginalElements.Remove(i); + } + + return length; + } + +// --------------------------------------------------------- +// Append an original element +// --------------------------------------------------------- +// +void CCompositionConvertedElement::AppendOriginal(const CCompositionElement* aElements) + { + iOriginalElements.Append(aElements); + } + +// --------------------------------------------------------- +// Get original input length +// --------------------------------------------------------- +// +TInt CCompositionConvertedElement::OriginalCount() const + { + return iOriginalElements.Count(); + } + +// --------------------------------------------------------- +// Get the content of original input +// --------------------------------------------------------- +// +const CCompositionElement* CCompositionConvertedElement::OriginalContent( TInt aIndex ) const + { + if( aIndex < 0 || aIndex > iOriginalElements.Count() - 1 ) + { + return NULL; + } + return iOriginalElements[aIndex]; + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CAknFepVkbCompositionField* CAknFepVkbCompositionField::NewL(TInt aMaxLength, + TRect aRect, + CFepUiLayout* aUiLayout, + TInt aControlId, + MAknFepVkbDataProvider* aDataProvider ) + { + CAknFepVkbCompositionField* self = new (ELeave) CAknFepVkbCompositionField(aMaxLength, + aRect, + aUiLayout, + aControlId, + aDataProvider ); + + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } + +// --------------------------------------------------------- +// C++ Constructor +// --------------------------------------------------------- +// +CAknFepVkbCompositionField::CAknFepVkbCompositionField(TInt aMaxLength, + TRect aRect, + CFepUiLayout* aUiLayout, + TInt aControlId, + MAknFepVkbDataProvider* aDataProvider) +: CFepLayoutEditAreaBase(aRect,aUiLayout,aControlId) + { + //iMaxLength <=0 means no max length limited + iMaxLength = aMaxLength; + iCurrentPos = 0; + iFirstSegment = NULL; + iDataProvider = aDataProvider; + + iIsValidSpells = EFalse; + + } + +// --------------------------------------------------------- +// 2nd Constructor +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::ConstructL() + { + //No cursor in construction + BaseConstructL(); + //iBufferForCommit = HBufC::NewL(KDefaultLen); + + + CPinyinAnalyserDbFeed* pZhuyinDb = CPinyinAnalyserDbFeed::NewL( EPinyinAnalyserTypeZhuyin ); + CleanupStack::PushL( pZhuyinDb ); + iZhuyinAnalyser = CAknFepVkbPinyinAnalyser::NewL( pZhuyinDb ); + CleanupStack::Pop( pZhuyinDb ); + + CPinyinAnalyserDbFeed* pPinyinDb = CPinyinAnalyserDbFeed::NewL( EPinyinAnalyserTypePinyin ); + CleanupStack::PushL( pPinyinDb ); + iPinyinAnalyser = CAknFepVkbPinyinAnalyser::NewL( pPinyinDb ); + CleanupStack::Pop( pPinyinDb ); + + + } + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CAknFepVkbCompositionField::~CAknFepVkbCompositionField() + { + iElements.ResetAndDestroy(); + iElements.Close(); + //delete iBufferForCommit; + delete iFirstSegment; + delete iZhuyinAnalyser; + delete iPinyinAnalyser; + } + +// --------------------------------------------------------- +// Handle events in +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleControlEvent(TInt aEventType, + CFepUiBaseCtrl* /*aCtrl*/, + const TDesC& aEventData) + { + TBuf<4> buf; + switch (aEventType) + { + case EEventVirtualKeyUp: + { + TKeyEvent* event = (TKeyEvent*) aEventData.Ptr(); + buf.Append(TChar(event->iScanCode)); + //assume keys are insertable + TRAP_IGNORE(HandleInsertL(buf)); + break; + } + case EVkbEventKeySpace: + { + TInt imLayout = iDataProvider->RequestData(EAknFepDataTypeIMLayout); + if (imLayout == EAknFepVkbImCnCangjie) + { + if(!IsValidSpell()) + { + break; + } + + RBuf firstCandidate(static_cast(iDataProvider)->Candidates()[0]); + firstCandidate.AppendNum( 0 ); + TRAP_IGNORE(HandleConvertedResultL(firstCandidate)); + } + else + { + TKeyEvent* event = (TKeyEvent*) aEventData.Ptr(); + buf.Append(TChar(event->iCode)); + //assume keys are insertable + TRAP_IGNORE(HandleInsertL(buf)); + } + break; + } + case EVkbEventKeyEnter: + TRAP_IGNORE(HandleFlushL()); + break; + case EPeninputLayoutEventBack: + TRAP_IGNORE(HandleBackL()); + break; + case EVkbEventLeftArrow: + { + TCursorSelection currentCursorSelection; + currentCursorSelection = Selection(); + + if (ETrue) + { + if (currentCursorSelection.iCursorPos == 0) + { + currentCursorSelection.iCursorPos = TextLength(); + } + else + { + currentCursorSelection.iCursorPos--; + if(currentCursorSelection.iCursorPos > 0 && + iElements[currentCursorSelection.iCursorPos - 1]->IsAutoSeparator()) + { + currentCursorSelection.iCursorPos--; + } + } + } + + TCursorSelection movedCursor(currentCursorSelection.iCursorPos, + currentCursorSelection.iCursorPos); + UpdateCursorSelection(movedCursor); + break; + } + case EVkbEventRightArrow: + { + TCursorSelection currentCursorSelection; + currentCursorSelection = Selection(); + + if (currentCursorSelection.iCursorPos == TextLength()) + { + currentCursorSelection.iCursorPos = 0; + } + else + { + currentCursorSelection.iCursorPos++; + if(currentCursorSelection.iCursorPos < TextLength() && + iElements[currentCursorSelection.iCursorPos - 1]->IsAutoSeparator()) + { + currentCursorSelection.iCursorPos++; + } + + } + + TCursorSelection movedCursor(currentCursorSelection.iCursorPos, + currentCursorSelection.iCursorPos); + UpdateCursorSelection(movedCursor); + break; + } + case EEventControlFocusLost: + SetFocus(EFalse); + break; + case EEventControlFocusGained: + SetFocus(); + break; + case EVkbEventCompFieldAnalysisResponse: + TRAP_IGNORE(HandleAnalysisResponseL(aEventData)); + break; + case EVkbEventCandidateSelected: + TRAP_IGNORE(HandleConvertedResultL(aEventData)); + break; + case EVkbEventWindowClose: + case EVkbEventClearContent: + TRAP_IGNORE(ClearTextL()); + break; + default: + break; + } + } + +// --------------------------------------------------------- +// Count of elements +// --------------------------------------------------------- +// +TInt CAknFepVkbCompositionField::Length() const + { + return iElements.Count(); + } + +// --------------------------------------------------------- +// Set warning color +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::SetWarningColor(const TRgb& aColor) + { + iWarningColor = aColor; + } + +// --------------------------------------------------------- +// Set normal color +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::SetNormalColor(const TRgb& aColor) + { + iNormalColor = aColor; + } + +// --------------------------------------------------------- +// Insert a key +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleInsertL(const TDesC& aKey) + { + CCompositionElement *element = CCompositionElement::NewLC(aKey); + + iCurrentPos = DisplayPosToInternaPos( iSelectedCompositionText.iCursorPos ); + + TBool updateText = EFalse; + //remove selection first + if( iSelectedCompositionText.Length() > 0) + { + RemoveSelection(); + updateText = ETrue; + } + + if (IsAllowedInsert(element)) + { + InsertElementL(element); + CleanupStack::Pop(element); + SendAnalysisRequestL(); + updateText = EFalse; + } + else + { + // If select all the chars in composition and input an invalid char, + // go to standby status. + if(Length() == 0) + { + ReportEvent(EVkbEventCompFieldNoChars); + ClearTextL(); + } + else + { + SendAnalysisRequestL(); + } + + CleanupStack::PopAndDestroy(element); + } + + if( updateText ) + { + UpdateTextL(); + } + } + +// --------------------------------------------------------- +// Insert an element +// --------------------------------------------------------- +// +//insert is only insert +void CAknFepVkbCompositionField::InsertElementL(const CCompositionElement* aElement) + { + if( IsReplaceFront(aElement) ) + { + Remove(iCurrentPos - 1, 1); + } + else if( IsReplaceBack(aElement) ) + { + Remove(iCurrentPos, 1); + } + + InsertL(iCurrentPos, aElement); + } + +// --------------------------------------------------------- +// Clear text +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::ClearTextL() + { + Clear(); + + UpdateTextL(); + + iNeedCreateWord = EFalse; + iConvertedElement = 0; + iIsValidSpells = ETrue; + } + +// --------------------------------------------------------- +// Submit all text +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleFlushL() + { + // Don't response when CangJieVkb state + if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnCangjie ) + { + return; + } + + HBufC* temp = HBufC::NewLC(iElements.Count()); + TPtr ptr = temp->Des(); + + for (TInt i = 0; i < iElements.Count(); i++) + { + if (!iElements[i]->IsTypeOf(EElementTypeAutoSeparator)) + { + ptr.Append(*iElements[i]->Key()); + } + } + + if (ptr.Length() > 0) + { + ReportEvent(EVkbEventCompFieldDataFlush, *temp); + ClearTextL(); + } + + CleanupStack::PopAndDestroy(temp); + } + +// --------------------------------------------------------- +// Handle back key +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleBackL() + { + if (Length() == 0) + { + return; + } + + iCurrentPos = DisplayPosToInternaPos( iSelectedCompositionText.iCursorPos ); + + if(iSelectedCompositionText.Length() > 0) + { + // update cursor position + RemoveSelection(); + } + else + { + TInt pos = iCurrentPos - 1; + if ( iCurrentPos == 0 ) + {//nothing to delete + return; + } + + //assure the element before cursor is not an auto separator + //cursor can not be put right after an auto separator + ASSERT(!iElements[pos]->IsAutoSeparator()); + + if (!iElements[pos]->IsTypeOf(EElementTypeConvertedChar)) + { + Remove(pos, 1, ETrue); + ReFomatAfterDelete(); + } + else + { + //current element is converted element, undo convert + TInt len = iElements[pos]->UndoConvertL(this, pos); + iCurrentPos -= ( len + 1 ); + if ( iCurrentPos < 0 ) + { + iCurrentPos = 0; + } + //remove the converted element + Remove(pos + len, 1); + iConvertedElement--; + if( iConvertedElement == 0 && iNeedCreateWord) + { + iNeedCreateWord = EFalse; + } + } + } + + if (Length() == 0) + { + ReportEvent(EVkbEventCompFieldNoChars); + ClearTextL(); + } + else + { + //no composition to analysis + if (IsFinishComposition()) + { + UpdateTextL(); + ReportEvent(EVkbEventCompFieldSubmit, iDisplayText); + ClearTextL(); + } + else + { + SendAnalysisRequestL(); + } + } + } + +// --------------------------------------------------------- +// Handle analysis response +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleAnalysisResponseL(const TDesC& aCompText) + { + + if ( ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnZhuyin + || iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnPinyin ) ) + { + if( iIsValidSpells ) + { + SetTextColor(iNormalColor); + } + else + { + SetTextColor(iWarningColor); + } + } + + if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnCangjie + || iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnStroke ) + { + if ( aCompText.Length() == 0 ) + { + iIsValidSpells = EFalse; + SetTextColor(iWarningColor); + } + else + { + iIsValidSpells = ETrue; + SetTextColor(iNormalColor); + } + + } + + if (aCompText.Length() > 0) + { + //merge the original elements with engine returned strings + //remove auto separator in orignal elements and insert auto separator + //add by engine + TInt origin = iFirstSegmentOffset; + TInt engine = 0; + while( engine < aCompText.Length() && origin < iElements.Count() ) + { + if( *(iElements[origin]) == aCompText[engine] ) + { + origin++; + engine++; + } + else if( iElements[origin]->IsAutoSeparator() ) + { + Remove(origin, 1); + iFirstSegmentLength--; + } + else if( IsKeyAutoSeparator(aCompText.Mid(engine,1)) ) + { + if( !iElements[origin]->IsManualSeparator() ) + { + CCompositionElement* element = + CCompositionElement::NewLC(aCompText.Mid(engine, 1)); + InsertL(origin, element); + CleanupStack::Pop(element); + iFirstSegmentLength++; + } + origin++; + engine++; + } + else + { + ASSERT(0); + } + } + //judge if invalid tone mark exist in iElements + if(aCompText.Length() < iElements.Count() - iFirstSegmentOffset) + { + if(origin <= iElements.Count() - 1 && iElements[origin]->IsTonemark()) + { + iIsValidSpells = EFalse; + SetTextColor(iWarningColor); + } + } + } + + UpdateTextL(); + Draw(); + UpdateArea(Rect(),EFalse); + } + +// --------------------------------------------------------- +// Handle converted result +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::HandleConvertedResultL(const TDesC& aConvertedText) + { + TInt index = iFirstSegmentOffset; + + //the last aConvertedText is the cell No of candidate list + for (TInt i = 0; i < aConvertedText.Length() - 1; i ++) + { + CCompositionConvertedElement* element = + CCompositionConvertedElement::NewLC(aConvertedText.Mid(i, 1)); + + TBool goOn = ETrue; + + while (index < Length() && !iElements[index]->IsTypeOf(EElementTypeConvertedChar) && goOn) + { + goOn = !iElements[index]->IsAuxilian(); + + if( iElements[index]->IsAutoSeparator() ) + { + Remove(index, 1); //remove automatic separator + } + else + { + element->AppendOriginal(iElements[index]); //transfer ownership to converted element + Remove(index, 1, EFalse); //remove the original element + } + } + + //insert the converted element + InsertL(index, element); + iCurrentPos = index + 1; + iConvertedElement++; + + CleanupStack::Pop(element); + index ++; + } + + if( IsFinishComposition() ) + { + UpdateTextL(); + ReportEvent(EVkbEventCompFieldSubmit, *iBuffer); + ClearTextL(); + } + else + { + //user takes part in composition + iNeedCreateWord = ETrue; + SendAnalysisRequestL(); + } + } + +// --------------------------------------------------------- +// Is there need to create new word +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::NeedCreateWord() + { + return iNeedCreateWord && iElements.Count() <= KCpiMaxInputPhraseLen; + } + +// --------------------------------------------------------- +// Remove elements +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::Remove(TInt aStartPos, TInt aLength, TBool aDestroy) + { + ASSERT (aStartPos >= 0 && aStartPos < Length()); + + TInt index = Min(aStartPos + aLength - 1, Length() -1); + + //adjust cursor position if necessary + if( iCurrentPos > aStartPos) + { + iCurrentPos -= index - aStartPos + 1; + } + + for (TInt i = index; i >= aStartPos; i --) + { + if (aDestroy) + { + delete iElements[i]; + } + + iElements.Remove(i); + } + } + +// --------------------------------------------------------- +// Insert an element +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::InsertL(TInt aPos, const CCompositionElement* aElement) + { + ASSERT (aPos >=0 && aPos <= Length()); + iElements.Insert(aElement, aPos); + if( iCurrentPos >= aPos ) + { + iCurrentPos ++; + } + } + +// --------------------------------------------------------- +// Clear element +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::Clear() + { + if (Length() == 0) + { + return; + } + + iCurrentPos = 0; + iElements.ResetAndDestroy(); + } + +// --------------------------------------------------------- +// Generate first segment +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::GetFirstSegmentL() + { + delete iFirstSegment; + iFirstSegment = NULL; + iFirstSegment = HBufC::NewL(Length()); + TPtr ptr = iFirstSegment->Des(); + + iFirstSegmentOffset = 0; + iFirstSegmentLength = 0; + + TInt i = 0; + for (i = 0; i < Length(); i++) + { + //start from the first unconverted element + if (!iElements[i]->IsTypeOf(EElementTypeConvertedChar) && + !iElements[i]->IsSeparator() ) + { + iFirstSegmentOffset = i; + ptr.Append((*iElements[i++]->Key())); + iFirstSegmentLength++; + while( i < Length() && !iElements[i]->IsTypeOf(EElementTypeConvertedChar) ) + { + if( !iElements[i]->IsAutoSeparator() ) + { + ptr.Append(*(iElements[i]->Key())); + } + + i++; + } + + break; + } + } + + iFirstSegmentLength = i - iFirstSegmentOffset; + if( ptr.Length() > 0 && + IsKeyManualSeparator(ptr.Right(1)) ) + { + ptr.SetLength(ptr.Length() - 1); + iFirstSegmentLength--; + } + } + +// --------------------------------------------------------- +// Update editbase cursor and text +// --------------------------------------------------------- +// assume the current all elements are valid +void CAknFepVkbCompositionField::UpdateTextL() + { + HBufC* displayText = HBufC::NewLC(iElements.Count()); + //adjust cursor to avoid autosepartor + if( iCurrentPos > 0 && iElements[iCurrentPos - 1]->IsAutoSeparator() ) + { + iCurrentPos--; + } + + TInt pos = iCurrentPos; + for( TInt i = 0; i < iElements.Count(); ++i ) + { + //deal with manual separator + if( iElements[i]->IsManualSeparator() ) + { + //valid format ensure i > 0 + if( iElements[i - 1]->IsTypeOf(EElementTypeConvertedChar)) + { + iElements[i]->Hide(ETrue); + } + else if( i + 1 < iElements.Count() && + iElements[i + 1]->IsTypeOf(EElementTypeConvertedChar) ) + { + iElements[i]->Hide(ETrue); + } + else + { + iElements[i]->Hide(EFalse); + } + } + //maybe other things + if(iElements[i]->IsVisible()) + { + { + displayText->Des().Append(iElements[i]->Key()->Left(1)); + } + } + else if( i < iCurrentPos) + { + pos--; + } + } + + TFepInputContextFieldData data; + data.iCmd = EPeninputICFInitial; + data.iStartPos = 0; + data.iLength = displayText->Length(); + data.iMidPos = -1; + data.iText.Set( *displayText ); + data.iCurSel = TCursorSelection(pos, pos); + data.iCursorVisibility = ETrue; + data.iCursorSelVisible = ETrue; + SetTextL( data ); + + CleanupStack::PopAndDestroy(displayText); + } + +// --------------------------------------------------------- +// Adjust cursor when pen down +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::AdjustSelectedCompositionText( + TInt& aPositionOfInsertionPointInBuffer) + { + TInt pos = DisplayPosToInternaPos(aPositionOfInsertionPointInBuffer); + pos--; + if (pos >=0 && pos < Length() && iElements[pos]->IsAutoSeparator()) + { + aPositionOfInsertionPointInBuffer --; + } + + if (aPositionOfInsertionPointInBuffer < 0) + { + aPositionOfInsertionPointInBuffer = 0; + } + } + +// --------------------------------------------------------- +// Update edit base content when scrolling +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::UpdateContent(const TCursorSelection& aCursorSel) + { + TInt cursorPos = aCursorSel.iCursorPos; + if (cursorPos < 0 ) + { + cursorPos = 0; + } + else if (cursorPos > iBuffer->Length()) + { + cursorPos = iBuffer->Length(); + } + + UpdateCursorSelection(TCursorSelection(cursorPos, aCursorSel.iAnchorPos)); + } + +// --------------------------------------------------------- +// Is allowed insert +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsAllowedInsert(const CCompositionElement* aElement) + { + if( (iCurrentPos == 0 || + iElements[iCurrentPos - 1]->IsTypeOf(EElementTypeConvertedChar)) && + aElement->IsAuxilian() ) + { + return EFalse; + } + + if (aElement->IsManualSeparator()) + { + //cursor must be larger than zero + if (iElements[iCurrentPos - 1]->IsTonemark() || + iElements[iCurrentPos - 1]->IsManualSeparator()) + { + return EFalse; + } + if ( (iElements.Count() >= iCurrentPos + 1) && + (iElements[iCurrentPos]->IsTonemark() || + iElements[iCurrentPos]->IsTypeOf(EElementTypeConvertedChar) || + iElements[iCurrentPos]->IsManualSeparator()) ) + { + return EFalse; + } + } + + if ( IsReplaceFront(aElement) || + IsReplaceBack(aElement)) + { + return ETrue; + } + + TInt count = 0; + for (TInt i = 0; i OriginalCount(); + } + + return (count < iMaxLength); + } + +// --------------------------------------------------------- +// Send analysis request +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::SendAnalysisRequestL() + { + GetFirstSegmentL(); + CAknFepVkbPinyinAnalyser* pAnalyser = NULL; + + if( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnZhuyin ) + { + pAnalyser = iZhuyinAnalyser; + } + else if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnPinyin ) + { + pAnalyser = iPinyinAnalyser; + } + + if ( pAnalyser ) + { + iIsValidSpells = pAnalyser->AnalyzeL( *iFirstSegment ); + + TPtrC compText( *pAnalyser->LastAnalysisResult() ); + TInt origin = iFirstSegmentOffset; + TInt engine = 0; + while( engine < compText.Length() && origin < iElements.Count() ) + { + if( *(iElements[origin]) == compText[engine] ) + { + origin++; + engine++; + } + else if( iElements[origin]->IsAutoSeparator() ) + { + Remove(origin, 1); + iFirstSegmentLength--; + } + else if( IsKeyAutoSeparator(compText.Mid(engine,1)) ) + { + if( !iElements[origin]->IsManualSeparator() ) + { + CCompositionElement* element = CCompositionElement::NewLC(compText.Mid(engine, 1)); + InsertL(origin, element); + CleanupStack::Pop(element); + iFirstSegmentLength++; + } + origin++; + engine++; + } + else + { + ASSERT(0); + } + } + + ReportEvent(EVkbEventCompFieldAnalysisReq, *pAnalyser->LastAnalysisResult() ); + } + else + { + ReportEvent(EVkbEventCompFieldAnalysisReq, *iFirstSegment); + } + } + +// --------------------------------------------------------- +// To test whether the all input keys are converted +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsFinishComposition() + { + for (TInt i = 0; i < Length(); i++) + { + if (!iElements[i]->IsTypeOf(EElementTypeConvertedChar)) + { + return EFalse; + } + } + + return ETrue; + } + +// --------------------------------------------------------- +// To test whether current pos element should be replaced by input one +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsReplacePosition(const CCompositionElement* aElement, + TInt aPos) + { + if( aElement->IsTonemark() ) + { + return iElements[aPos]->IsTonemark() || + iElements[aPos]->IsSeparator(); + } + else if(aElement->IsManualSeparator() ) + { + return iElements[aPos]->IsAutoSeparator(); + } + else + { + return EFalse; + } + } + +// --------------------------------------------------------- +// To test whether the one before current pos element should be replaced by input one +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsReplaceFront(const CCompositionElement* aElement) + { + if( iCurrentPos > 0 ) + { + return IsReplacePosition(aElement, iCurrentPos - 1); + } + + return EFalse; + } + +// --------------------------------------------------------- +// To test whether current pos element should be replaced by input one +// --------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsReplaceBack(const CCompositionElement* aElement) + { + if( iCurrentPos <= iElements.Count() - 1 ) + { + return IsReplacePosition(aElement, iCurrentPos); + } + + return EFalse; + } + +// --------------------------------------------------------- +// Redo the format after deletion +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::ReFomatAfterDelete() + { +//assumption +//1. delete only happen in cursor position +//2. before deletion, the format is OK + if( iElements.Count() == 0 ) + { + return; + } + + if( iCurrentPos == 0 ) + { + if( iElements[0]->IsSeparator() || + iElements[0]->IsTonemark()) + { + Remove(0, 1, ETrue); + } + } + else if( iCurrentPos <= iElements.Count() - 1) + { + if(iElements[iCurrentPos - 1]->IsAuxilian() && + iElements[iCurrentPos]->IsAuxilian() ) + { //one of two is need to be removed + if(iElements[iCurrentPos]->IsTonemark() || + iElements[iCurrentPos]->IsManualSeparator() ) + {//remove the one before cursor + Remove(iCurrentPos - 1, 1, ETrue); + //to simulate remove + insert opertion + iCurrentPos++; + } + else + {//remove the one on the cursor + Remove(iCurrentPos, 1, ETrue); + } + } + else if( iElements[iCurrentPos - 1]->IsAutoSeparator() && + iElements[iCurrentPos]->IsTypeOf(EElementTypeConvertedChar) ) + { + //remove auto separator before convert char + Remove(iCurrentPos - 1, 1, ETrue); + } + else if( iElements[iCurrentPos]->IsAutoSeparator() && + iElements[iCurrentPos - 1]->IsTypeOf(EElementTypeConvertedChar) ) + { + //remove auto separator before convert char + Remove(iCurrentPos, 1, ETrue); + } + } + else //if( iCurrentPos == iElements.Count() ) + { + if( iElements[iCurrentPos - 1]->IsAutoSeparator() ) + { + Remove(iCurrentPos - 1, 1); + } + } + } + +// --------------------------------------------------------- +// Get display cursor positon by internal cursor position +// --------------------------------------------------------- +// +TInt CAknFepVkbCompositionField::InternalPosToDisplayPos(TInt aInternalPos) + { + for(TInt i = 0; i < aInternalPos; i++) + { + if( !iElements[i]->IsVisible() ) + { + aInternalPos--; + } + } + + return aInternalPos; + } + +// --------------------------------------------------------- +// Get internal cursor positon by display cursor position +// --------------------------------------------------------- +// +TInt CAknFepVkbCompositionField::DisplayPosToInternaPos(TInt aDisplayPos) + { + TInt pos = 0; + TInt i = 0; + + for( i = 0; i < iElements.Count() && pos < aDisplayPos; i++ ) + { + if( iElements[i]->IsVisible() ) + { + pos++; + } + } + for( i++; i < iElements.Count(); i++ ) + { + if( iElements[i]->IsVisible() ) + { + break; + } + } + + return --i; + } + +// --------------------------------------------------------- +// Remove the selected text +// --------------------------------------------------------- +// +void CAknFepVkbCompositionField::RemoveSelection() + { + TInt lower = DisplayPosToInternaPos( iSelectedCompositionText.LowerPos() ); + TInt upper = DisplayPosToInternaPos( iSelectedCompositionText.HigherPos() ); + Remove(lower, upper - lower); + ReFomatAfterDelete(); + } + +// --------------------------------------------------------------------------- +// CAknFepVkbCompositionField::GetCreatedWordSpell +// (other items were commented in a header) +// --------------------------------------------------------------------------- +// +const TInt KSpellSpace = 8; // private protocol for PtiCpiCore +TPtrC CAknFepVkbCompositionField::GetCreatedWordSpell() + { + iCreateWordSpellBuffer.SetLength( 0 ); + //TUint16 bufText[10] = {0}; + //TUint16 bufSpell[100] = {0}; + + if( iNeedCreateWord ) + { + //for() + iCreateWordSpellBuffer.SetLength( KSpellSpace * iElements.Count() ); + iCreateWordSpellBuffer.FillZ(); + for ( int i = 0; i < iElements.Count(); i++ ) + { + //bufText[i] = ( *( iElements[i]->Key() ) )[0]; + + TUint16 temp = ( *( iElements[i]->Key() ) )[0]; + iCreateWordSpellBuffer[KSpellSpace*i] = ( *( iElements[i]->Key() ) )[0]; + for( int j=0; j < iElements[i]->OriginalCount(); j++ ) + { + const CCompositionElement* element = iElements[i]->OriginalContent( j ); + if( element && !element->IsSeparator() ) + { + //bufSpell[ i*KSpellSpace + j] = ( *( element->Key() ) )[0]; + iCreateWordSpellBuffer[KSpellSpace*i + j + 1] = ( *( element->Key() ) )[0];; + } + } + } + } + + return iCreateWordSpellBuffer; + } + +// --------------------------------------------------------------------------- +// CAknFepVkbCompositionField::IsValidSpell +// (other items were commented in a header) +// --------------------------------------------------------------------------- +// +TBool CAknFepVkbCompositionField::IsValidSpell() + { + // no just verify the Zhuyin & Pinyin spell, stoke&cangjie verify later + if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnZhuyin + || iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnPinyin ) + { + return iIsValidSpells; + } + if( ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnStroke + || iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnCangjie ) ) + { + return iIsValidSpells; + } + return ETrue; + } + +void CAknFepVkbCompositionField::ConstructFromResourceL() + { + if (iResourceId == KInvalidResId) + { + User::Leave(KErrArgument); + } + + TResourceReader reader; + CCoeEnv::Static()->CreateResourceReaderLC(reader, iResourceId); + + + TPtrC bmpFileName = reader.ReadTPtrC(); + TInt32 imgMajorSkinId = reader.ReadInt32(); + + TAknsItemID id; + TInt skinitemid; + + MAknsSkinInstance* skininstance = AknsUtils::SkinInstance(); + + const TInt16 compositionbgId = reader.ReadInt16(); + const TInt16 compositionbgIdmaskId = reader.ReadInt16(); + skinitemid = reader.ReadInt16(); + + id.Set( TInt( imgMajorSkinId ), skinitemid ); + + if ( compositionbgId != KInvalidImg ) + { + CFbsBitmap* compositionImg = NULL; + + if (compositionbgIdmaskId != KInvalidImg) + { + CFbsBitmap* compositionmaskImg = NULL; + + AknsUtils::CreateIconL(skininstance, + id, + compositionImg, + compositionmaskImg, + bmpFileName, + compositionbgId, + compositionbgIdmaskId); + + AknIconUtils::SetSize(compositionmaskImg, TSize(1,1), EAspectRatioNotPreserved); + SetBackgroundMaskBitmapL(compositionmaskImg); + } + else + { + AknsUtils::CreateIconL(skininstance, + id, + compositionImg, + bmpFileName, + compositionbgId); + } + + AknIconUtils::SetSize(compositionImg, TSize(1,1), EAspectRatioNotPreserved); + SetBackgroundBitmapL(compositionImg); + } + + CleanupStack::PopAndDestroy(); // reader + + } + +void CAknFepVkbCompositionField::SizeChanged(TRect aRect) + { + CFepLayoutEditAreaBase::SetRect(aRect); + if( BackgroundBmp() ) + { + CFbsBitmap* bmp = BackgroundBmp(); + if( aRect.Size() != bmp->SizeInPixels() ) + { + AknIconUtils::SetSize(bmp, aRect.Size(), EAspectRatioNotPreserved); + } + } + } +// End Of File