--- /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 <peninputlayoutbasecontrol.h>
+
+#include <AknsDrawUtils.h>
+#include <barsread.h>
+
+#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<CAknFepVkbDataMgr*>(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 <Length(); i++)
+ {
+ count += iElements[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