fep/frontendprocessor/test/feps/TFEP4.CPP
changeset 0 eb1f2e154e89
child 20 ebd48d2de13c
equal deleted inserted replaced
-1:000000000000 0:eb1f2e154e89
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**  @file
       
    19      @internalComponent
       
    20 */ 
       
    21 
       
    22 #include <e32std.h>
       
    23 #include <e32base.h>
       
    24 #include <e32keys.h>
       
    25 #include <s32strm.h>
       
    26 #include <gdi.h>
       
    27 #include <txtfrmat.h>
       
    28 #include <fbs.h>
       
    29 #include <bitstd.h>
       
    30 #include <bitdev.h>
       
    31 #include <w32std.h>
       
    32 #include <frmtlay.h>
       
    33 #include <coemain.h>
       
    34 #include <coeaui.h>
       
    35 #include <coecntrl.h>
       
    36 #include <coefepff.h>
       
    37 #include <fepbase.h>
       
    38 #include <fepitfr.h>
       
    39 #include <techview/eikon.hrh>
       
    40 #include <techview/eikdialg.h>
       
    41 #include <techview/eikchkbx.h>
       
    42 #include <techview/eikbutb.h>
       
    43 #include <techview/eikchlst.h>
       
    44 #include <gulutil.h>	// for FontUtils, together with egul.lib
       
    45 
       
    46 #include "tfep4.hrh"
       
    47 #include "TFEP4.H"
       
    48 #include "TFEP4COM.H"
       
    49 
       
    50 // constants
       
    51 
       
    52 enum TPanic
       
    53 	{
       
    54 	EPanicBackupAlreadyExists=1,
       
    55 	EPanicBadIndex1,
       
    56 	EPanicBadIndex2,
       
    57 	EPanicNotExpectedToBeSimulatingKeyEvent1,
       
    58 	EPanicNotExpectedToBeSimulatingKeyEvent2,
       
    59 	EPanicBadAttributeUid1,
       
    60 	EPanicBadAttributeUid2,
       
    61 	EPanicBadAttributeUid3,
       
    62 	EPanicBadAttributeUid4,
       
    63 	EPanicBadInputMethod1,
       
    64 	EPanicBadInputMethod2,
       
    65 	EPanicBadInputMethod3,
       
    66 	EPanicBadInputMethod4,
       
    67 	EPanicBadInputMethod5,
       
    68 	EPanicBadTextLength1,
       
    69 	EPanicBadTextLength2,
       
    70 	EPanicBadKeyCode1,
       
    71 	EPanicBadKeyCode2,
       
    72 	EPanicBadKeyCode3,
       
    73 	EPanicBadKeyCode4,
       
    74 	EPanicBadCharacterInBuffer,
       
    75 	EPanicInconsistentState,
       
    76 	EPanicNegativeIndex,
       
    77 	EPanicArithmeticConfusion,
       
    78 	EPanicBadLengthOfTextBeforeSelection,
       
    79 	EPanicSelectionExtendsPastEndOfDocument,
       
    80 	EPanicBadLengthOfTextAfterSelection,
       
    81 	EPanicBadLengthOfSelection,
       
    82 	EPanicBadHeight,
       
    83 	EPanicIsAlreadyActive,
       
    84 	EPanicNoFepAwareTextEditorAlthoughCurrentlyInlineEditing,
       
    85 	EPanicBadKeyResponse,
       
    86 	EPanicUnexpectedButtonId,
       
    87 	EPanicBadCheckBoxState,
       
    88 	EPanicBadNumberOfAttributes
       
    89 	};
       
    90 
       
    91 _LIT(KLitTFEP4, "TFEP4");
       
    92 #if defined(_UNICODE)
       
    93 const TUint KEllipsisCharacter=0x2026;
       
    94 _LIT(KLitCompositionFontTypefaceName, "publicDomainUnicode");
       
    95 //_LIT(KLitCompositionFontTypefaceName, "SimHei");
       
    96 //_LIT(KLitCompositionFontTypefaceName, "STFangSong");
       
    97 #else
       
    98 const TUint KEllipsisCharacter=0x85;
       
    99 _LIT(KLitCompositionFontTypefaceName, "courier");
       
   100 #endif
       
   101 _LIT(KLitStatusFontTypefaceName, "SwissA");		// original "arial"
       
   102 _LIT(KLitNoFocusedFepAwareTextEditor, "No focused FEP-aware text-editor");
       
   103 _LIT(KLitNoFocusedFepAwareTextEditorSupportingState, "No focused FEP-aware text-editor supporting state");
       
   104 _LIT(KLitNotAvailable, "[not available]");
       
   105 //_LIT(KLitTooLong, "[too long]");
       
   106 _LIT(KLitQuotationMark, "\"");
       
   107 _LIT(KLitTextBeforeSelectionColonSpace, "Text before selection: ");
       
   108 _LIT(KLitTextAfterSelectionColonSpace, "Text after selection: ");
       
   109 _LIT(KLitSelectionColonSpace, "Selection: ");
       
   110 _LIT(KLitInputMethodColonSpace, "Input method: ");
       
   111 _LIT(KLitPlain, "plain");
       
   112 _LIT(KLitHexadecimalCharacterCode, "hexadecimal character-code");
       
   113 _LIT(KLitPinYin, "pin yin");
       
   114 _LIT(KLitInlineEditingColonSpace, "Inline editing: ");
       
   115 _LIT(KLitEnabled, "enabled");
       
   116 _LIT(KLitDisabled, "disabled");
       
   117 _LIT(KLitOpeningSquareBracket, "[");
       
   118 _LIT(KLitCaptionColonSpace, "Caption: ");
       
   119 _LIT(KLitStateColonSpace, "State: ");
       
   120 _LIT(KLitInputCapabilitiesColonSpace, "Input-capabilities: ");
       
   121 _LIT(KLitNone, "none");
       
   122 _LIT(KLitWesternNumericIntegerPositive, "Western numeric integer positive");
       
   123 _LIT(KLitWesternNumericIntegerNegative, "Western numeric integer negative");
       
   124 _LIT(KLitWesternNumericReal, "Western numeric real");
       
   125 _LIT(KLitWesternAlphabetic, "Western alphabetic");
       
   126 _LIT(KLitJapaneseHiragana, "Japanese hiragana");
       
   127 _LIT(KLitJapaneseKatakanaHalfWidth, "Japanese katakana half-width");
       
   128 _LIT(KLitJapaneseKatakanaFullWidth, "Japanese katakana full-width");
       
   129 _LIT(KLitDialableCharacters, "dialable characters");
       
   130 _LIT(KLitSecretText, "secret text");
       
   131 _LIT(KLitAllText, "all text");
       
   132 _LIT(KLitNavigation, "navigation");
       
   133 _LIT(KLitExtensionsColonSpace, "extensions: ");
       
   134 _LIT(KLitPhoneticAlphabet, "phonetic alphabet");
       
   135 _LIT(KLitCommaSpace, ", ");
       
   136 _LIT(KLitClosingSquareBracket, "]");
       
   137 
       
   138 LOCAL_D const TText* const KPhoneticAlphabet[]=
       
   139 	{
       
   140 	_S("Alpha"),
       
   141 	_S("Bravo"),
       
   142 	_S("Charlie"),
       
   143 	_S("Delta"),
       
   144 	_S("Echo"),
       
   145 	_S("Foxtrot"),
       
   146 	_S("Golf"),
       
   147 	_S("Hotel"),
       
   148 	_S("India"),
       
   149 	_S("Juliette"),
       
   150 	_S("Kilo"),
       
   151 	_S("Lima"),
       
   152 	_S("Mike"),
       
   153 	_S("November"),
       
   154 	_S("Oscar"),
       
   155 	_S("Papa"),
       
   156 	_S("Quebec"),
       
   157 	_S("Romeo"),
       
   158 	_S("Sierra"),
       
   159 	_S("Tango"),
       
   160 	_S("Uniform"),
       
   161 	_S("Victor"),
       
   162 	_S("Whiskey"),
       
   163 	_S("X-Ray"),
       
   164 	_S("Yankee"),
       
   165 	_S("Zulu")
       
   166 	};
       
   167 
       
   168 // local and global functions
       
   169 LOCAL_C inline TBool IsLowSurrogate(TText16 aInt16)
       
   170 /**
       
   171 @return True, if aText16 is low surrogate; false, otherwise.
       
   172 */
       
   173     {
       
   174     return (aInt16 & 0xFC00) == 0xDC00;
       
   175     }
       
   176 
       
   177 LOCAL_C void Panic(TPanic aPanic)
       
   178 	{
       
   179 	User::Panic(KLitTFEP4, aPanic);
       
   180 	}
       
   181 
       
   182 GLDEF_C TInt E32Dll(
       
   183 					)
       
   184 	{
       
   185 	return KErrNone;
       
   186 	}
       
   187 
       
   188 // TTstTextBackup
       
   189 
       
   190 #pragma warning(disable: 4355) // "'this' : used in base member initializer list"
       
   191 
       
   192 TTstTextBackup::TTstTextBackup(TDes& aText)
       
   193 	:iCleanupItem(Cleanup, this),
       
   194 	 iOriginal(aText),
       
   195 	 iBackup(NULL)
       
   196 	{
       
   197 	}
       
   198 
       
   199 #pragma warning(default: 4355)
       
   200 
       
   201 void TTstTextBackup::PushOntoCleanupStackL()
       
   202 	{
       
   203 	__ASSERT_DEBUG(iBackup==NULL, Panic(EPanicBackupAlreadyExists));
       
   204 	iBackup=iOriginal.AllocL();
       
   205 	CleanupStack::PushL(iCleanupItem);
       
   206 	}
       
   207 
       
   208 void TTstTextBackup::PopOffCleanupStack()
       
   209 	{
       
   210 	delete iBackup;
       
   211 	CleanupStack::Pop();
       
   212 	}
       
   213 
       
   214 void TTstTextBackup::Cleanup(TAny* aTextBackup)
       
   215 	{
       
   216 	TTstTextBackup* const textBackup=STATIC_CAST(TTstTextBackup*, aTextBackup);
       
   217 	textBackup->iOriginal=*textBackup->iBackup;
       
   218 	delete textBackup->iBackup;
       
   219 	}
       
   220 
       
   221 // CTstInsertionPoint
       
   222 
       
   223 CTstInsertionPoint* CTstInsertionPoint::NewL(RWindowBase& aWindow, CCoeEnv& aConeEnvironment)
       
   224 	{
       
   225 	CTstInsertionPoint* const insertionPoint=new(ELeave) CTstInsertionPoint(aConeEnvironment.WsSession());
       
   226 	CleanupStack::PushL(insertionPoint);
       
   227 	insertionPoint->ConstructL(aWindow, aConeEnvironment.ScreenDevice()->DisplayMode());
       
   228 	CleanupStack::Pop(); // insertionPoint
       
   229 	return insertionPoint;
       
   230 	}
       
   231 
       
   232 CTstInsertionPoint::~CTstInsertionPoint()
       
   233 	{
       
   234 	iSprite.Close();
       
   235 	delete iSpriteMember.iBitmap; // must be deleted after iSprite is closed as iSprite has a reference to it
       
   236 	// iSpriteMember.iMaskBitmap is not deleted as it is the same as iSpriteMember.iBitmap
       
   237 	}
       
   238 
       
   239 void CTstInsertionPoint::SetPosition(const TPoint& aPosition)
       
   240 	{
       
   241 	iPosition=aPosition;
       
   242 	if (iFlags&EFlagOn)
       
   243 		{
       
   244 		iSprite.SetPosition(iPosition);
       
   245 		}
       
   246 	}
       
   247 
       
   248 void CTstInsertionPoint::SetOn(TBool aOn)
       
   249 	{
       
   250 	if (!aOn!=!(iFlags&EFlagOn)) // fold non-zero values on both sides before comparing for inequality
       
   251 		{
       
   252 		DoSetOn(aOn);
       
   253 		}
       
   254 	}
       
   255 
       
   256 CTstInsertionPoint::CTstInsertionPoint(RWsSession& aWindowServerSession)
       
   257 	:iSprite(aWindowServerSession),
       
   258 	 iPosition(0, 0),
       
   259 	 iFlags(0)
       
   260 	{
       
   261 	iSpriteMember.iBitmap=NULL;
       
   262 	iSpriteMember.iMaskBitmap=NULL;
       
   263 	}
       
   264 
       
   265 void CTstInsertionPoint::ConstructL(RWindowBase& aWindow, TDisplayMode aDisplayMode)
       
   266 	{
       
   267 	iSpriteMember.iBitmap=CreateBitmapL(aDisplayMode);
       
   268 	iSpriteMember.iMaskBitmap=iSpriteMember.iBitmap;
       
   269 	iSpriteMember.iInvertMask=ETrue;
       
   270 	iSpriteMember.iDrawMode=CGraphicsContext::EDrawModePEN;
       
   271 	iSpriteMember.iOffset.iX=-(CTstInsertionPoint::EWidth/2);
       
   272 	iSpriteMember.iOffset.iY=0;
       
   273 	iSpriteMember.iInterval=0;
       
   274 	User::LeaveIfError(iSprite.Construct(aWindow, iPosition, 0));
       
   275 	User::LeaveIfError(iSprite.AppendMember(iSpriteMember));
       
   276 	DoSetOn(EFalse);
       
   277 	User::LeaveIfError(iSprite.Activate());
       
   278 	}
       
   279 
       
   280 CFbsBitmap* CTstInsertionPoint::CreateBitmapL(TDisplayMode aDisplayMode)
       
   281 	{
       
   282 	CFbsBitmap* const bitmap=new(ELeave) CFbsBitmap;
       
   283 	CleanupStack::PushL(bitmap);
       
   284 	User::LeaveIfError(bitmap->Create(TSize(CTstInsertionPoint::EWidth, CTstInsertionPoint::EHeight), aDisplayMode));
       
   285 	CFbsBitmapDevice* const bitmapDevice=CFbsBitmapDevice::NewL(bitmap);
       
   286 	CleanupStack::PushL(bitmapDevice);
       
   287 	CFbsBitGc* const graphicsContext=CFbsBitGc::NewL();
       
   288 	CleanupStack::PushL(graphicsContext);
       
   289 	graphicsContext->Activate(bitmapDevice);
       
   290 	graphicsContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   291 	graphicsContext->SetBrushColor(KRgbWhite);
       
   292 	graphicsContext->SetPenStyle(CGraphicsContext::ESolidPen);
       
   293 	graphicsContext->SetPenColor(KRgbBlack);
       
   294 	graphicsContext->Clear();
       
   295 	const TPoint bottomLeft(0, CTstInsertionPoint::EHeight-1);
       
   296 	const TPoint bottomRight(CTstInsertionPoint::EWidth-1, CTstInsertionPoint::EHeight-1);
       
   297 	const TPoint top(CTstInsertionPoint::EWidth/2, 0);
       
   298 	graphicsContext->DrawLine(bottomLeft, bottomRight);
       
   299 	graphicsContext->DrawLine(bottomRight, top);
       
   300 	graphicsContext->DrawLine(top, bottomLeft);
       
   301 	CleanupStack::PopAndDestroy(2); // graphicsContext and bitmapDevice
       
   302 	CleanupStack::Pop(); // bitmap
       
   303 	return bitmap;
       
   304 	}
       
   305 
       
   306 void CTstInsertionPoint::DoSetOn(TBool aOn)
       
   307 	{
       
   308 	iSprite.SetPosition(aOn? iPosition: TPoint(-(EWidth*4), -(EHeight*4)));
       
   309 	if (aOn)
       
   310 		{
       
   311 		iFlags|=EFlagOn;
       
   312 		}
       
   313 	else
       
   314 		{
       
   315 		iFlags&=~EFlagOn;
       
   316 		}
       
   317 	}
       
   318 
       
   319 // TTstArrayOfOneCtrlCharacter
       
   320 
       
   321 TTstArrayOfOneCtrlCharacter::TTstArrayOfOneCtrlCharacter(TUint aCharacter)
       
   322 	:iCharacter(aCharacter)
       
   323 	{
       
   324 	}
       
   325 
       
   326 TArray<CCoeFep::MModifiedCharacter> TTstArrayOfOneCtrlCharacter::ArrayOfModifiedCharacters()
       
   327 	{
       
   328 	return TArray<CCoeFep::MModifiedCharacter>(NumberOfModifiedCharacters, ModifiedCharacter, (const CBase*)this);
       
   329 	}
       
   330 
       
   331 TInt TTstArrayOfOneCtrlCharacter::NumberOfModifiedCharacters(const CBase*)
       
   332 	{
       
   333 	return 1;
       
   334 	}
       
   335 
       
   336 const TAny* TTstArrayOfOneCtrlCharacter::ModifiedCharacter(const CBase* aThis, TInt aIndex)
       
   337 	{
       
   338 	__ASSERT_ALWAYS(aIndex==0, Panic(EPanicBadIndex1));
       
   339 	return aThis;
       
   340 	}
       
   341 
       
   342 TUint TTstArrayOfOneCtrlCharacter::CharacterCode() const
       
   343 	{
       
   344 	return iCharacter;
       
   345 	}
       
   346 
       
   347 TUint TTstArrayOfOneCtrlCharacter::ModifierMask() const
       
   348 	{
       
   349 	return EModifierCtrl|EModifierShift|EModifierLeftShift|EModifierRightShift;
       
   350 	}
       
   351 
       
   352 TUint TTstArrayOfOneCtrlCharacter::ModifierValues() const
       
   353 	{
       
   354 	return EModifierCtrl;
       
   355 	}
       
   356 
       
   357 // CTstControl
       
   358 
       
   359 CTstControl* CTstControl::NewL(CTstFep& aFep)
       
   360 	{
       
   361 	CTstControl* const control=new(ELeave) CTstControl(aFep);
       
   362 	CleanupStack::PushL(control);
       
   363 	control->ConstructL();
       
   364 	CleanupStack::Pop(); // control
       
   365 	return control;
       
   366 	}
       
   367 
       
   368 CTstControl::~CTstControl()
       
   369 	{
       
   370 	if (iFlags&EFlagInsideInlineEditingTransaction)
       
   371 		{
       
   372 		CancelInlineEdit(*iInputCapabilities.FepAwareTextEditor());
       
   373 		}
       
   374 	iCoeEnv->ReleaseScreenFont(iCompositionFont);
       
   375 	iCoeEnv->ReleaseScreenFont(iStatusFont);
       
   376 	STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->RemoveFromStack(this);
       
   377 	delete iInsertionPoint;
       
   378 	}
       
   379 
       
   380 void CTstControl::CancelTransaction()
       
   381 	{
       
   382 	__ASSERT_DEBUG(!iFep.IsSimulatingKeyEvent() || ((~iFlags&EFlagInsideInlineEditingTransaction) && (iBuffer.Length()==0)), Panic(EPanicNotExpectedToBeSimulatingKeyEvent1));
       
   383 	TBool needToDraw=EFalse;
       
   384 	if (iFlags&EFlagInsideInlineEditingTransaction)
       
   385 		{
       
   386 		CancelInlineEdit(*iInputCapabilities.FepAwareTextEditor());
       
   387 		needToDraw=ETrue;
       
   388 		}
       
   389 	if (iBuffer.Length()>0)
       
   390 		{
       
   391 		ResetBuffer();
       
   392 		needToDraw=ETrue;
       
   393 		}
       
   394 	if (needToDraw)
       
   395 		{
       
   396 		DrawNow();
       
   397 		}
       
   398 	}
       
   399 
       
   400 void CTstControl::IsOnHasChangedState()
       
   401 	{
       
   402 	ChangeSetupAndResetBufferAndDrawNow(NULL);
       
   403 	}
       
   404 
       
   405 void CTstControl::OfferPointerEventL(CCoeFep::TEventResponse& aEventResponse, const TPointerEvent& aPointerEvent, const CCoeControl* aWindowOwningControl)
       
   406 	{
       
   407 	// this function must correctly set aEventResponse *before* calling anything that can leave
       
   408 	if (aWindowOwningControl==this)
       
   409 		{
       
   410 		aEventResponse=CCoeFep::EEventWasConsumed;
       
   411 		HandlePointerEventL(aPointerEvent);
       
   412 		}
       
   413 	else
       
   414 		{
       
   415 		aEventResponse=CCoeFep::EEventWasNotConsumed;
       
   416 		}
       
   417 	}
       
   418 
       
   419 TInt CTstControl::NumberOfAttributes()
       
   420 	{
       
   421 	return 2;
       
   422 	}
       
   423 
       
   424 TUid CTstControl::AttributeAtIndex(TInt aIndex)
       
   425 	{
       
   426 	switch (aIndex)
       
   427 		{
       
   428 	case 0:
       
   429 		return TUid::Uid(ETstInlineEditingEnabledUid);
       
   430 	case 1:
       
   431 		return TUid::Uid(ETstInputMethodUid);
       
   432 #if defined(_DEBUG)
       
   433 	default:
       
   434 		Panic(EPanicBadIndex2);
       
   435 		break;
       
   436 #endif
       
   437 		}
       
   438 	return KNullUid;
       
   439 	}
       
   440 
       
   441 void CTstControl::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const
       
   442 	{
       
   443 	switch (aAttributeUid.iUid)
       
   444 		{
       
   445 	case ETstInlineEditingEnabledUid:
       
   446 		aStream.WriteUint8L((iFlags&EFlagInlineEditingEnabled)!=0);
       
   447 		break;
       
   448 	case ETstInputMethodUid:
       
   449 		aStream.WriteUint8L(iInputMethod);
       
   450 		break;
       
   451 #if defined(_DEBUG)
       
   452 	default:
       
   453 		Panic(EPanicBadAttributeUid1);
       
   454 		break;
       
   455 #endif
       
   456 		}
       
   457 	}
       
   458 
       
   459 void CTstControl::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream)
       
   460 	{
       
   461 	switch (aAttributeUid.iUid)
       
   462 		{
       
   463 	case ETstInlineEditingEnabledUid:
       
   464 		ChangeSetupAndResetBufferAndDrawNow(SetFlagInlineEditingEnabled, aStream.ReadUint8L());
       
   465 		break;
       
   466 	case ETstInputMethodUid:
       
   467 		{
       
   468 		TInt inputMethod=aStream.ReadUint8L();
       
   469 		if ((inputMethod!=EInputMethodPlain) && (inputMethod!=EInputMethodHexadecimalCharacterCode) && (inputMethod != EInputMethodPinYin))
       
   470 			{
       
   471 			User::Leave(KErrCorrupt);
       
   472 			}
       
   473 		ChangeSetupAndResetBufferAndDrawNow(SetInputMethod, inputMethod);
       
   474 		}
       
   475 		break;
       
   476 #if defined(_DEBUG)
       
   477 	default:
       
   478 		Panic(EPanicBadAttributeUid2);
       
   479 		break;
       
   480 #endif
       
   481 		}
       
   482 	}
       
   483 
       
   484 void CTstControl::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream, TBool aInlineEditingEnabled, TInt aInputMethod)
       
   485 	{
       
   486 	switch (aAttributeUid.iUid)
       
   487 		{
       
   488 	case ETstInlineEditingEnabledUid:
       
   489 		aStream.WriteUint8L(aInlineEditingEnabled!=EFalse);
       
   490 		break;
       
   491 	case ETstInputMethodUid:
       
   492 		aStream.WriteUint8L(aInputMethod);
       
   493 		break;
       
   494 #if defined(_DEBUG)
       
   495 	default:
       
   496 		Panic(EPanicBadAttributeUid3);
       
   497 		break;
       
   498 #endif
       
   499 		}
       
   500 	}
       
   501 
       
   502 void CTstControl::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream, TBool& aInlineEditingEnabled, TInt& aInputMethod)
       
   503 	{
       
   504 	switch (aAttributeUid.iUid)
       
   505 		{
       
   506 	case ETstInlineEditingEnabledUid:
       
   507 		aInlineEditingEnabled=aStream.ReadUint8L();
       
   508 		break;
       
   509 	case ETstInputMethodUid:
       
   510 		aInputMethod=aStream.ReadUint8L();
       
   511 		break;
       
   512 #if defined(_DEBUG)
       
   513 	default:
       
   514 		Panic(EPanicBadAttributeUid4);
       
   515 		break;
       
   516 #endif
       
   517 		}
       
   518 	}
       
   519 
       
   520 void CTstControl::HandleGainingForeground()
       
   521 	{
       
   522 	DrawableWindow()->MoveToGroup(iCoeEnv->WsSession().GetFocusWindowGroup()); // ignore the error returned
       
   523 	ChangeSetupAndResetBufferAndDrawNow(SetForeground, ETrue);
       
   524 	}
       
   525 
       
   526 void CTstControl::HandleLosingForeground()
       
   527 	{
       
   528 	ChangeSetupAndResetBufferAndDrawNow(SetForeground, EFalse);
       
   529 	}
       
   530 
       
   531 void CTstControl::HandleChangeInFocus()
       
   532 	{
       
   533 	ChangeSetupAndResetBufferAndDrawNow(SetInputCapabilities, NULL);
       
   534 	}
       
   535 
       
   536 void CTstControl::HandleDestructionOfFocusedItem()
       
   537 	{
       
   538 	if (!IsBeingDestroyed())
       
   539 		{
       
   540 		const TCoeInputCapabilities inputCapabilities(STATIC_CAST(const CCoeAppUi*, iCoeEnv->AppUi())->InputCapabilities());
       
   541 		if (inputCapabilities.FepAwareTextEditor()==NULL)
       
   542 			{
       
   543 			iFlags&=~EFlagInsideInlineEditingTransaction; // turn this off now so that ChangeSetupAndResetBufferAndDrawNow does not try to call CancelInlineEdit on an object that has probably been destroyed by now
       
   544 			}
       
   545 		ChangeSetupAndResetBufferAndDrawNow(SetInputCapabilities, REINTERPRET_CAST(TInt, &inputCapabilities));
       
   546 		}
       
   547 	}
       
   548 
       
   549 CTstControl::CTstControl(CTstFep& aFep)
       
   550 	:iFep(aFep),
       
   551 	 iInputMethod(EInputMethodHexadecimalCharacterCode),
       
   552 	 iFlags(0),
       
   553 	 iBuffer(KNullDesC),
       
   554 	 iSelectedCompositionText(0, 0),
       
   555 	 iInputCapabilities(TCoeInputCapabilities::ENone),
       
   556 	 iCompositionFont(NULL),
       
   557 	 iStatusFont(NULL),
       
   558 	 iInsertionPoint(NULL),
       
   559 	 iPositionOnWindowBeingDragged(0, 0)
       
   560 	{
       
   561 	}
       
   562 
       
   563 void CTstControl::ConstructL()
       
   564 	{
       
   565 	CreateWindowL();
       
   566 	EnableDragEvents();
       
   567 	ClaimPointerGrab();
       
   568 	SetNonFocusing();
       
   569 	RDrawableWindow& window=*DrawableWindow();
       
   570 	window.SetOrdinalPosition(0, ECoeWinPriorityFep);
       
   571 	window.SetShadowHeight(3);
       
   572 	TFontSpec compositionFontSpec(KLitCompositionFontTypefaceName, 200);
       
   573 	compositionFontSpec.iTypeface.SetIsProportional(EFalse);
       
   574 	//compositionFontSpec.SetScriptTypeForMetrics(ELangPrcChinese);
       
   575 	iCompositionFont=iCoeEnv->CreateScreenFontL(compositionFontSpec);
       
   576 	//iStatusFont=iCoeEnv->CreateScreenFontL(TFontSpec(KLitStatusFontTypefaceName, 120));
       
   577 	iStatusFont=iCoeEnv->CreateScreenFontL(TFontSpec(KLitStatusFontTypefaceName, FontUtils::TwipsFromPoints(8)));
       
   578 	iInsertionPoint=CTstInsertionPoint::NewL(window, *iCoeEnv);
       
   579 	SetPositionOfInsertionPointInBuffer(0);
       
   580 	const TInt statusFontHeightInPixels=iStatusFont->HeightInPixels();
       
   581 	const TSize size(320, 1 + EGapAboveCompositionLine + iCompositionFont->HeightInPixels() + EGapBelowCompositionLine
       
   582 						+ EGapAboveCompositionLine + iCompositionFont->HeightInPixels() + EGapBelowCompositionLine		// character selector
       
   583 						+ EGapAboveTopStatusLine
       
   584 						+ (4 * (statusFontHeightInPixels + EGapBetweenEachStatusLine))
       
   585 						+ statusFontHeightInPixels + EGapBelowBottomStatusLine + 1);
       
   586 	const TSize screenSize(iCoeEnv->ScreenDevice()->SizeInPixels());
       
   587 	SetExtent(TPoint(screenSize.iWidth-(size.iWidth+10), screenSize.iHeight-(size.iHeight+10)), size);
       
   588 	STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->AddToStackL(this, ECoeStackPriorityFep, ECoeStackFlagRefusesFocus|ECoeStackFlagSharable);
       
   589 	ChangeSetupAndResetBufferAndDrawNow(SetForeground, iCoeEnv->RootWin().Identifier()==iCoeEnv->WsSession().GetFocusWindowGroup());
       
   590 	ChangeSetupAndResetBufferAndDrawNow(SetFocus, EFalse);
       
   591 	ChangeSetupAndResetBufferAndDrawNow(SetFlagInlineEditingEnabled, ETrue);
       
   592 	ChangeSetupAndResetBufferAndDrawNow(SetInputMethod, EInputMethodHexadecimalCharacterCode);
       
   593 	ChangeSetupAndResetBufferAndDrawNow(SetInputCapabilities, NULL);
       
   594 	}
       
   595 
       
   596 void CTstControl::SetForeground(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter)
       
   597 	{
       
   598 	SetFlag(aControl, aChangeWasMade, aParameter, EFlagForeground);
       
   599 	}
       
   600 
       
   601 void CTstControl::SetFocus(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter)
       
   602 	{
       
   603 	aChangeWasMade=EFalse;
       
   604 	if (!aParameter!=!aControl.IsFocused()) // fold non-zero values on both sides before comparing for inequality
       
   605 		{
       
   606 		CCoeAppUi& appUi=*STATIC_CAST(CCoeAppUi*, aControl.iCoeEnv->AppUi());
       
   607 		appUi.UpdateStackedControlFlags(&aControl, (aParameter? 0: ECoeStackFlagRefusesFocus), ECoeStackFlagRefusesFocus);
       
   608 		appUi.HandleStackChanged();
       
   609 		aChangeWasMade=ETrue;
       
   610 		TBool notUsed;
       
   611 		SetInputCapabilities(aControl, notUsed, NULL);
       
   612 		}
       
   613 	}
       
   614 
       
   615 void CTstControl::SetFlagInlineEditingEnabled(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter)
       
   616 	{
       
   617 	SetFlag(aControl, aChangeWasMade, aParameter, EFlagInlineEditingEnabled);
       
   618 	}
       
   619 
       
   620 void CTstControl::SetInputMethod(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter)
       
   621 	{
       
   622 	__ASSERT_DEBUG((aParameter==EInputMethodPlain) || (aParameter==EInputMethodHexadecimalCharacterCode) || (aParameter==EInputMethodPinYin), Panic(EPanicBadInputMethod1));
       
   623 	aChangeWasMade=EFalse;
       
   624 	if (aControl.iInputMethod!=aParameter)
       
   625 		{
       
   626 		aControl.iInputMethod=aParameter;
       
   627 		aChangeWasMade=ETrue;
       
   628 		}
       
   629 	}
       
   630 
       
   631 void CTstControl::SetInputCapabilities(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter)
       
   632 	{
       
   633 	aChangeWasMade=EFalse;
       
   634 	TCoeInputCapabilities inputCapabilities(TCoeInputCapabilities::ENone);
       
   635 	if (!aControl.IsFocused())
       
   636 		{
       
   637 		inputCapabilities=(aParameter!=NULL)? *REINTERPRET_CAST(const TCoeInputCapabilities*, aParameter): STATIC_CAST(const CCoeAppUi*, aControl.iCoeEnv->AppUi())->InputCapabilities();
       
   638 		}
       
   639 	if (aControl.iInputCapabilities!=inputCapabilities)
       
   640 		{
       
   641 		aControl.iInputCapabilities=inputCapabilities;
       
   642 		aChangeWasMade=ETrue;
       
   643 		}
       
   644 	}
       
   645 
       
   646 void CTstControl::SetFlag(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter, TUint aFlag)
       
   647 	{
       
   648 	aChangeWasMade=EFalse;
       
   649 	if (!aParameter!=!(aControl.iFlags&aFlag)) // fold non-zero values on both sides before comparing for inequality
       
   650 		{
       
   651 		aControl.iFlags^=aFlag;
       
   652 		aChangeWasMade=ETrue;
       
   653 		}
       
   654 	}
       
   655 
       
   656 void CTstControl::ChangeSetupAndResetBufferAndDrawNow(FChangeFunction aChangeFunction, TInt aParameter)
       
   657 	{
       
   658 	__ASSERT_DEBUG(!iFep.IsSimulatingKeyEvent() || ((~iFlags&EFlagInsideInlineEditingTransaction) && (iBuffer.Length()==0)), Panic(EPanicNotExpectedToBeSimulatingKeyEvent2));
       
   659 	TBool needToDraw=EFalse;
       
   660 	if (iFlags&EFlagInsideInlineEditingTransaction)
       
   661 		{
       
   662 		CancelInlineEdit(*iInputCapabilities.FepAwareTextEditor());
       
   663 		needToDraw=ETrue;
       
   664 		}
       
   665 	if (aChangeFunction!=NULL)
       
   666 		{
       
   667 		TBool changeWasMade;
       
   668 		(*aChangeFunction)(*this, changeWasMade, aParameter);
       
   669 		if (changeWasMade)
       
   670 			{
       
   671 			needToDraw=ETrue;
       
   672 			}
       
   673 		}
       
   674 	if (iBuffer.Length()>0)
       
   675 		{
       
   676 		ResetBuffer();
       
   677 		needToDraw=ETrue;
       
   678 		}
       
   679 	const TBool potentiallyInlineEditing=((iInputCapabilities.FepAwareTextEditor()!=NULL) && (iFlags&EFlagInlineEditingEnabled)); // iInputCapabilities.FepAwareTextEditor may return a different value here to the call at the start of the function, hence the need to call it again
       
   680 	iInsertionPoint->SetOn(!IsFocused() && !potentiallyInlineEditing);
       
   681 	if (!potentiallyInlineEditing!=!(iFlags&EFlagHasNoCompositionWindow)) // fold non-zero values on both sides before comparing for inequality
       
   682 		{
       
   683 		const TInt heightOfCompositionWindow=EGapAboveCompositionLine+iCompositionFont->HeightInPixels()+EGapBelowCompositionLine;
       
   684 		TInt windowAdjustmentY;
       
   685 		if (potentiallyInlineEditing)
       
   686 			{
       
   687 			windowAdjustmentY=heightOfCompositionWindow;
       
   688 			iFlags|=EFlagHasNoCompositionWindow;
       
   689 			}
       
   690 		else
       
   691 			{
       
   692 			windowAdjustmentY=-heightOfCompositionWindow;
       
   693 			iFlags&=~EFlagHasNoCompositionWindow;
       
   694 			}
       
   695 		TRect rectangle(Position(), Size()); // creating rectangle from Rect() will give the wrong result as this control owns a window (its top left position would come out as TPoint(0, 0) rather than what Position() returns)
       
   696 		rectangle.iTl.iY+=windowAdjustmentY;
       
   697 		SetRect(rectangle);
       
   698 		needToDraw=ETrue;
       
   699 		}
       
   700 	const TBool shouldBeVisible=(iFep.IsOn() && (iFlags&EFlagForeground));
       
   701 	if (!IsVisible()!=!shouldBeVisible) // fold non-zero values on both sides before comparing for inequality
       
   702 		{
       
   703 		MakeVisible(shouldBeVisible);
       
   704 		needToDraw=EFalse;
       
   705 		}
       
   706 	if (needToDraw)
       
   707 		{
       
   708 		DrawNow();
       
   709 		}
       
   710 	}
       
   711 
       
   712 void CTstControl::InsertCompositionCharacterAndDrawNowL(TUint aCharacterCode)
       
   713 	{
       
   714 	const TInt positionOfNewText=iSelectedCompositionText.LowerPos();
       
   715 	if (positionOfNewText<EMaximumLengthOfBuffer)
       
   716 		{
       
   717 		TTstTextBackup textBackup=iBuffer;
       
   718 		textBackup.PushOntoCleanupStackL();
       
   719 		const TCoeInputCapabilities::MCoeFepSpecificExtensions* fepSpecificInputCapabilityExtensions=iInputCapabilities.FepSpecificExtensions(TUid::Uid(KTestFep4Uid));
       
   720 		const TUint upperCaseCharacterCode=User::UpperCase(aCharacterCode);
       
   721 		TPtrC textToInsert;
       
   722 		TBuf<1> buffer;
       
   723 		TInt newPositionOfInsertionPointInBuffer=positionOfNewText;
       
   724 		if ((iInputMethod==EInputMethodPlain) && (fepSpecificInputCapabilityExtensions!=NULL) && fepSpecificInputCapabilityExtensions->SupportsPhoneticAlphabet() && (upperCaseCharacterCode>='A') && (upperCaseCharacterCode<='Z'))
       
   725 			{
       
   726 			textToInsert.Set(TPtrC(KPhoneticAlphabet[upperCaseCharacterCode-'A']));
       
   727 			const TInt lengthOfRoomForTextToInsert=EMaximumLengthOfBuffer-positionOfNewText;
       
   728 			if (textToInsert.Length()>lengthOfRoomForTextToInsert)
       
   729 				{
       
   730 				textToInsert.Set(textToInsert.Left(lengthOfRoomForTextToInsert));
       
   731 				}
       
   732 			newPositionOfInsertionPointInBuffer+=textToInsert.Length();
       
   733 			}
       
   734 		else
       
   735 			{
       
   736 			buffer.Append(aCharacterCode);
       
   737 			textToInsert.Set(buffer);
       
   738 			++newPositionOfInsertionPointInBuffer;
       
   739 			}
       
   740 		iBuffer.Delete(positionOfNewText, iSelectedCompositionText.Length());
       
   741 		const TInt lengthToDeleteToMakeRoom=textToInsert.Length()-(EMaximumLengthOfBuffer-iBuffer.Length());
       
   742 		if (lengthToDeleteToMakeRoom>0)
       
   743 			{
       
   744 			iBuffer.Delete(iBuffer.Length()-lengthToDeleteToMakeRoom, lengthToDeleteToMakeRoom);
       
   745 			}
       
   746 		iBuffer.Insert(positionOfNewText, textToInsert);
       
   747 		__ASSERT_DEBUG((iInputMethod==EInputMethodPlain) || (iInputMethod==EInputMethodHexadecimalCharacterCode) || (iInputMethod==EInputMethodPinYin), Panic(EPanicBadInputMethod4));
       
   748 		if (iInputMethod==EInputMethodHexadecimalCharacterCode)
       
   749 			{
       
   750 			if (newPositionOfInsertionPointInBuffer>=ENumberOfHexadecimalDigitsPerCharacterCode)
       
   751 				{
       
   752 				TUint characterCode=0;
       
   753 				for (TInt i=ENumberOfHexadecimalDigitsPerCharacterCode; ; --i)
       
   754 					{
       
   755 					if (i<=0)
       
   756 						{
       
   757 						// to support surrogate
       
   758 						TInt byteCount = characterCode <= 0xFFFF ? 1 : 2;
       
   759 						const TInt positionToInsertCharacterCode=newPositionOfInsertionPointInBuffer-ENumberOfHexadecimalDigitsPerCharacterCode;
       
   760 						iBuffer.Delete(positionToInsertCharacterCode, ENumberOfHexadecimalDigitsPerCharacterCode-byteCount);
       
   761 						if (byteCount == 1)
       
   762 							{
       
   763 							iBuffer[positionToInsertCharacterCode]=(TText)characterCode;
       
   764 							}
       
   765 						else
       
   766 							{
       
   767 							iBuffer[positionToInsertCharacterCode] = (TText)(0xD7C0 + (characterCode >> 10));
       
   768 							iBuffer[positionToInsertCharacterCode+1] = (TText)(0xDC00 | (characterCode & 0x03FF));
       
   769 							}
       
   770 						newPositionOfInsertionPointInBuffer-=ENumberOfHexadecimalDigitsPerCharacterCode-byteCount;
       
   771 						break;
       
   772 						}
       
   773 					const TCharUC hexadecimalDigit=iBuffer[newPositionOfInsertionPointInBuffer-i];
       
   774 					characterCode*=16;
       
   775 					if ((hexadecimalDigit>='0') && (hexadecimalDigit<='9'))
       
   776 						{
       
   777 						characterCode+=hexadecimalDigit-'0';
       
   778 						}
       
   779 					else if ((hexadecimalDigit>='A') && (hexadecimalDigit<='F'))
       
   780 						{
       
   781 						characterCode+=(hexadecimalDigit-'A')+10;
       
   782 						}
       
   783 					else
       
   784 						{
       
   785 						break;
       
   786 						}
       
   787 					}
       
   788 				}
       
   789 			}
       
   790 		else if (iInputMethod == EInputMethodPinYin)
       
   791 			{
       
   792 			// to support pinyin
       
   793 			if (newPositionOfInsertionPointInBuffer > 0)
       
   794 				{
       
   795 				if (aCharacterCode == 0x20)		// last inputted characters is space
       
   796 					{
       
   797 					TBool found = EFalse;
       
   798 					TPtrC pinyin;		// founded pinyin
       
   799 					// skip over "illegal" Pinyin character, including Chinese characters
       
   800 					TInt posOfFirstPinyinChar = 0;
       
   801 					while (posOfFirstPinyinChar < iBuffer.Length())	//newPositionOfInsertionPointInBuffer)
       
   802 						{
       
   803 						if (CPinyinSelector::IsValidPinyinChar(iBuffer[posOfFirstPinyinChar]))
       
   804 							break;
       
   805 						posOfFirstPinyinChar++;
       
   806 						}
       
   807 					if (posOfFirstPinyinChar < iBuffer.Length())	//newPositionOfInsertionPointInBuffer)
       
   808 						{
       
   809 						TInt posOfLastPinyinChar = iBuffer.Length() - 1;	//newPositionOfInsertionPointInBuffer - 1;
       
   810 						while (posOfLastPinyinChar > posOfFirstPinyinChar)
       
   811 							{
       
   812 							// try to find long-est, legal pinyin
       
   813 							TInt length = posOfLastPinyinChar - posOfFirstPinyinChar + 1;	//+1?
       
   814 							pinyin.Set(iBuffer.Ptr()+posOfFirstPinyinChar, length);
       
   815 							TBool legal = iPinYinSelector.SetPinyin(&pinyin);
       
   816 							if (legal)
       
   817 								{
       
   818 								found = ETrue;
       
   819 								break;
       
   820 								}
       
   821 							posOfLastPinyinChar--;
       
   822 							}
       
   823 						if (found && pinyin.Length()>0)
       
   824 							{
       
   825 							TInt characterCode = iPinYinSelector.NextCharacter();
       
   826 							if (characterCode != 0xFFFFFFFF)
       
   827 								{
       
   828 								TInt byteCount = (characterCode <= 0xFFFF) ? 1 : 2;		// actually it is 16-bit count
       
   829 								TInt positionToInsertCharacterCode = posOfFirstPinyinChar;
       
   830 								// assert: positionOfNewText > positionToInsertCharacterCode
       
   831 								if (positionOfNewText > positionToInsertCharacterCode)
       
   832 									{
       
   833 									iBuffer.Delete(positionOfNewText, 1);	// space
       
   834 									// if (pinyin.Length() <= byteCount)...
       
   835 									iBuffer.Delete(positionToInsertCharacterCode, pinyin.Length()-byteCount);	// pinyin
       
   836 									}
       
   837 								else
       
   838 									{
       
   839 									// if (pinyin.Length() <= byteCount)...
       
   840 									iBuffer.Delete(positionToInsertCharacterCode, pinyin.Length()-byteCount);	// pinyin
       
   841 									iBuffer.Delete(positionOfNewText, 1);	// space
       
   842 									positionToInsertCharacterCode--;
       
   843 									}
       
   844 								if (byteCount == 1)
       
   845 									{
       
   846 									iBuffer[positionToInsertCharacterCode]=(TText)characterCode;
       
   847 									}
       
   848 								else
       
   849 									{
       
   850 									iBuffer[positionToInsertCharacterCode] = (TText)(0xD7C0 + (characterCode >> 10));
       
   851 									iBuffer[positionToInsertCharacterCode+1] = (TText)(0xDC00 | (characterCode & 0x03FF));
       
   852 									}
       
   853 								newPositionOfInsertionPointInBuffer = positionToInsertCharacterCode + byteCount;
       
   854 								}
       
   855 							}
       
   856 						}
       
   857 					}
       
   858 				}
       
   859 			}
       
   860 		SetPositionOfInsertionPointInBuffer(newPositionOfInsertionPointInBuffer);
       
   861 		MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
   862 		if ((fepAwareTextEditor==NULL) || !(iFlags&EFlagInlineEditingEnabled))
       
   863 			{
       
   864 			DrawNow();
       
   865 			}
       
   866 		else
       
   867 			{
       
   868 			if (iInputMethod == EInputMethodPinYin)
       
   869 				DrawNow();	// draw candidate characters for current pinyin
       
   870 			SetInlineTextL(*fepAwareTextEditor);
       
   871 			}
       
   872 		textBackup.PopOffCleanupStack();
       
   873 		}
       
   874 	} // positionOfNewText newPositionOfInsertionPointInBuffer iCursorPos
       
   875 
       
   876 void CTstControl::SetInlineTextL(MCoeFepAwareTextEditor& aFepAwareTextEditor)
       
   877 	{
       
   878 	if (iFlags&EFlagInsideInlineEditingTransaction)
       
   879 		{
       
   880 		aFepAwareTextEditor.UpdateFepInlineTextL(iBuffer, iSelectedCompositionText.iCursorPos);
       
   881 		}
       
   882 	else
       
   883 		{
       
   884 		aFepAwareTextEditor.StartFepInlineEditL(iBuffer, iSelectedCompositionText.iCursorPos, ETrue, this, *this, *this);
       
   885 		iFlags|=EFlagInsideInlineEditingTransaction;
       
   886 		}
       
   887 	}
       
   888 
       
   889 void CTstControl::CancelInlineEdit(MCoeFepAwareTextEditor& aFepAwareTextEditor)
       
   890 	{
       
   891 	aFepAwareTextEditor.CancelFepInlineEdit();
       
   892 	iFlags&=~EFlagInsideInlineEditingTransaction;
       
   893 	}
       
   894 
       
   895 void CTstControl::CommitInlineEditL(MCoeFepAwareTextEditor& aFepAwareTextEditor)
       
   896 	{
       
   897 	aFepAwareTextEditor.CommitFepInlineEditL(*iCoeEnv);
       
   898 	iFlags&=~EFlagInsideInlineEditingTransaction;
       
   899 	}
       
   900 
       
   901 void CTstControl::ResetBuffer()
       
   902 	{
       
   903 	SetPositionOfInsertionPointInBuffer(0);
       
   904 	iBuffer.SetLength(0);
       
   905 	}
       
   906 
       
   907 void CTstControl::SetPositionOfInsertionPointInBuffer(TInt aPositionOfInsertionPointInBuffer)
       
   908 	{
       
   909 	SetPositionOfInsertionPointInBuffer(aPositionOfInsertionPointInBuffer, aPositionOfInsertionPointInBuffer);
       
   910 	}
       
   911 
       
   912 void CTstControl::SetPositionOfInsertionPointInBuffer(TInt aPositionOfInsertionPointInBuffer, TInt aPositionOfAnchorInBuffer)
       
   913 	{
       
   914 	iSelectedCompositionText.iCursorPos=aPositionOfInsertionPointInBuffer;
       
   915 	iSelectedCompositionText.iAnchorPos=aPositionOfAnchorInBuffer;
       
   916 	iInsertionPoint->SetPosition(PositionOfInsertionPointOnWindow());
       
   917 	}
       
   918 
       
   919 TPoint CTstControl::PositionOfInsertionPointOnWindow() const
       
   920 	{
       
   921 	return TPoint(1+EGapLeftOfEachLine+iCompositionFont->TextWidthInPixels(iBuffer.Left(iSelectedCompositionText.iCursorPos)), 1+EGapAboveCompositionLine+iCompositionFont->HeightInPixels());
       
   922 	}
       
   923 
       
   924 TInt CTstControl::PositionInBuffer(TInt aX) const
       
   925 	{
       
   926 	const TInt lengthOfBuffer=iBuffer.Length();
       
   927 	TInt previousX=0; // dummy initialization to prevent compiler warning "local variable 'previousX' may be used without having been initialized"
       
   928 	for (TInt i=0; ; ++i)
       
   929 		{
       
   930 		if (i>lengthOfBuffer)
       
   931 			{
       
   932 			return lengthOfBuffer;
       
   933 			}
       
   934 		const TInt x=1+EGapLeftOfEachLine+iCompositionFont->TextWidthInPixels(iBuffer.Left(i));
       
   935 		if (x>aX)
       
   936 			{
       
   937 			__ASSERT_DEBUG(i>=0, Panic(EPanicNegativeIndex));
       
   938 			if (i<=0)
       
   939 				{
       
   940 				return 0;
       
   941 				}
       
   942 			if (aX-previousX<x-aX)
       
   943 				{
       
   944 				return i-1;
       
   945 				}
       
   946 			return i;
       
   947 			}
       
   948 		previousX=x;
       
   949 		}
       
   950 	}
       
   951 
       
   952 TBool CTstControl::IsLegalNonDigitForRealNumber(const TCharUC& aKeyCodeInUpperCase) const
       
   953 	{
       
   954 	const TInt startOfSelectedText=iSelectedCompositionText.LowerPos();
       
   955 	const TInt endOfSelectedText=iSelectedCompositionText.HigherPos();
       
   956 	TInt positionOfExistingDecimalPoint=iBuffer.Locate('.');
       
   957 	if ((positionOfExistingDecimalPoint>=startOfSelectedText) && (positionOfExistingDecimalPoint<endOfSelectedText))
       
   958 		{
       
   959 		positionOfExistingDecimalPoint=KErrNotFound;
       
   960 		}
       
   961 	TInt positionOfExistingE=iBuffer.Locate('E');
       
   962 	if ((positionOfExistingE>=startOfSelectedText) && (positionOfExistingE<endOfSelectedText))
       
   963 		{
       
   964 		positionOfExistingE=KErrNotFound;
       
   965 		}
       
   966 	if (aKeyCodeInUpperCase=='.')
       
   967 		{
       
   968 		return (positionOfExistingDecimalPoint==KErrNotFound) && ((positionOfExistingE==KErrNotFound) || (positionOfExistingE>=endOfSelectedText));
       
   969 		}
       
   970 	if (aKeyCodeInUpperCase=='E')
       
   971 		{
       
   972 		return (positionOfExistingE==KErrNotFound) && ((positionOfExistingDecimalPoint==KErrNotFound) || (positionOfExistingDecimalPoint<startOfSelectedText));
       
   973 		}
       
   974 	return EFalse;
       
   975 	}
       
   976 
       
   977 void CTstControl::GetFormatAtDocumentPosition(TCharFormat& aFormat, TInt aDocumentPosition, const MCoeFepAwareTextEditor& aFepAwareTextEditor)
       
   978 	{
       
   979 	if (aDocumentPosition<0)
       
   980 		{
       
   981 		aDocumentPosition=0;
       
   982 		}
       
   983 	const TInt documentLength=aFepAwareTextEditor.DocumentLengthForFep();
       
   984 	if (aDocumentPosition>documentLength)
       
   985 		{
       
   986 		aDocumentPosition=documentLength;
       
   987 		}
       
   988 	aFepAwareTextEditor.GetFormatForFep(aFormat, aDocumentPosition);
       
   989 	}
       
   990 
       
   991 TInt CTstControl::NumberOfCharactersInBuffer(const CBase* aControl)
       
   992 	{
       
   993 #if 0
       
   994 	return STATIC_CAST(const CTstControl*, aControl)->iBuffer.Length();
       
   995 #else
       
   996 	// should not return unpaired surrogate
       
   997 	CTstControl* control = STATIC_CAST(CTstControl*, CONST_CAST(CBase*, aControl));
       
   998 	return control->iBuffer.Length();
       
   999 #endif
       
  1000 	}
       
  1001 
       
  1002 const TAny* CTstControl::CharacterInBuffer(const CBase* aControl, TInt aIndex)
       
  1003 	{
       
  1004 #if 0
       
  1005 	CTstControl* control=STATIC_CAST(CTstControl*, CONST_CAST(CBase*, aControl));
       
  1006 	control->iCharacterCode=control->iBuffer[aIndex];
       
  1007 	return &control->iCharacterCode;
       
  1008 #else
       
  1009 	// should not return unpaired surrogate
       
  1010 	CTstControl* control=STATIC_CAST(CTstControl*, CONST_CAST(CBase*, aControl));
       
  1011 	control->iCharacterCode=control->iBuffer[aIndex];
       
  1012 	return &control->iCharacterCode;
       
  1013 #endif
       
  1014 	}
       
  1015 
       
  1016 TKeyResponse CTstControl::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aEventCode)
       
  1017 	{
       
  1018 	// CTstFep::OfferKeyEventL assumes that this will not leave if it returns EKeyWasNotConsumed
       
  1019 	FEP_START_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, aEventCode);
       
  1020 	const TBool isFocused=IsFocused();
       
  1021 	const TCharUC keyCodeInUpperCase=aKeyEvent.iCode;
       
  1022 	TInt bufferLength=iBuffer.Length();
       
  1023 	
       
  1024 	// should we reset pinyin selector?
       
  1025 	TBool needResetPinyinSelector = ETrue;
       
  1026 	if (keyCodeInUpperCase == EKeyPageUp || keyCodeInUpperCase == EKeyPageDown)
       
  1027 		needResetPinyinSelector = EFalse;
       
  1028 	if (keyCodeInUpperCase >= '0' && keyCodeInUpperCase <= '9')
       
  1029 		{
       
  1030 		if (!iPinYinSelector.IsReseted())
       
  1031 			needResetPinyinSelector = EFalse;
       
  1032 		}
       
  1033 	if (needResetPinyinSelector)
       
  1034 		iPinYinSelector.Reset();
       
  1035 		
       
  1036 	if ((aKeyEvent.iModifiers&EModifierRightShift) && !isFocused)
       
  1037 		{
       
  1038 		if (keyCodeInUpperCase=='W')
       
  1039 			{
       
  1040  			if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1041 				{
       
  1042 				TBool didIt=EFalse;
       
  1043 				MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  1044 				if (fepAwareTextEditor!=NULL)
       
  1045 					{
       
  1046 					MCoeFepAwareTextEditor_Extension1* const extension=fepAwareTextEditor->Extension1();
       
  1047 					if (extension!=NULL)
       
  1048 						{
       
  1049 						TTextCursor textCursor;
       
  1050 						textCursor.iType=TTextCursor::ETypeHollowRectangle;
       
  1051 						textCursor.iHeight=0; // ignored by CEikEdwin as it checks for iWidth.
       
  1052 						textCursor.iAscent=0; // ignored by CEikEdwin
       
  1053 						textCursor.iWidth=5;
       
  1054 						textCursor.iFlags=TTextCursor::EFlagNoFlash;
       
  1055 						textCursor.iColor=TRgb(255,0,0);
       
  1056 						extension->SetCursorType(didIt,textCursor);
       
  1057 						}
       
  1058 					}
       
  1059 				if (!didIt)
       
  1060 					{
       
  1061 					User::InfoPrint(_L("Couldn't set the cursor-type"));
       
  1062 					}
       
  1063 				}
       
  1064 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1065 			}
       
  1066 		else if (bufferLength==0)
       
  1067 			{
       
  1068 			switch (keyCodeInUpperCase)
       
  1069 				{
       
  1070 			case 'M':
       
  1071   				ChangeSetupAndResetBufferAndDrawNow(SetInputMethod, (iInputMethod+1<EInputMethodOnePastTheLast)? iInputMethod+1: 0);
       
  1072   				// client app may not have the capability "WriteDeviceData"
       
  1073   				//iFep.WriteAttributeDataAndBroadcastL(TUid::Uid(ETstInputMethodUid));
       
  1074   				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1075 
       
  1076 			case 'F':
       
  1077 				ChangeSetupAndResetBufferAndDrawNow(SetFocus, ETrue);
       
  1078 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1079 			case 'I':
       
  1080 				ChangeSetupAndResetBufferAndDrawNow(SetFlagInlineEditingEnabled, !(iFlags&EFlagInlineEditingEnabled));
       
  1081 				// client app may not have the capability "WriteDeviceData"
       
  1082 				//iFep.WriteAttributeDataAndBroadcastL(TUid::Uid(ETstInlineEditingEnabledUid));
       
  1083 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1084 			case 'X':
       
  1085 			case 'C':
       
  1086 			case 'V':
       
  1087 				{
       
  1088 				//TTstArrayOfOneCtrlCharacter arrayOfOneCtrlCharacter(keyCodeInUpperCase-('A'-1)); // the TTstArrayOfOneCtrlCharacter object cannot be an anonymous (temporary) object as its lifetime must be guaranteed to last until iFep.SimulateKeyEventsL returns
       
  1089                 //iFep.SimulateKeyEventsL(arrayOfOneCtrlCharacter.ArrayOfModifiedCharacters());
       
  1090 				const TInt numberOfCharacters = 11;
       
  1091 			    CArrayFix<TUint>* arrayOfCharacters=new(ELeave) CArrayFixFlat<TUint>(numberOfCharacters); // a RArray would be better than a CArrayFix, but unfortunately RArray doesn't (yet) have a TArray interface
       
  1092 			    CleanupStack::PushL(arrayOfCharacters);
       
  1093 			    int i;
       
  1094 			    TUint32 cjkBase = 0x20020;
       
  1095 			    TUint32 ch;
       
  1096 			    for (i=0; i<numberOfCharacters - 3; i++)
       
  1097 			        {
       
  1098 			            ch = cjkBase++;
       
  1099 			            TUint32 hi = ((ch - 0x10000) / 0x400) + 0xD800;
       
  1100 			            TUint32 lo = ((ch - 0x10000) % 0x400) + 0xDC00;
       
  1101 			            arrayOfCharacters->AppendL(hi);
       
  1102 			            arrayOfCharacters->AppendL(lo);
       
  1103 			            i++;
       
  1104 			        }
       
  1105                 ch++;
       
  1106                 TUint32 hi = ((ch - 0x10000) / 0x400) + 0xD800;
       
  1107                 TUint32 lo = ((ch - 0x10000) % 0x400) + 0xDC00;
       
  1108                 arrayOfCharacters->AppendL(lo);
       
  1109                 arrayOfCharacters->AppendL(hi);
       
  1110                 arrayOfCharacters->AppendL(hi);
       
  1111 			    iFep.SimulateKeyEventsL(arrayOfCharacters->Array());
       
  1112 			    CleanupStack::PopAndDestroy();
       
  1113 				}
       
  1114 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1115 			case 'T':
       
  1116 				{
       
  1117 				MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  1118 				if (fepAwareTextEditor==NULL)
       
  1119 					{
       
  1120 					User::InfoPrint(KLitNoFocusedFepAwareTextEditor);
       
  1121 					}
       
  1122 				else
       
  1123 					{
       
  1124 					MCoeFepAwareTextEditor_Extension1* const extension1=fepAwareTextEditor->Extension1();
       
  1125 					if (extension1==NULL)
       
  1126 						{
       
  1127 						User::InfoPrint(KLitNoFocusedFepAwareTextEditorSupportingState);
       
  1128 						}
       
  1129 					else
       
  1130 						{
       
  1131 						MCoeFepAwareTextEditor_Extension1::CState* const state=extension1->State(TUid::Uid(KTestFep4Uid));
       
  1132 						if (state!=NULL)
       
  1133 							{
       
  1134 							STATIC_CAST(CStateInformation*, state)->IncrementMeaninglessNumber(); // this cast is safe as KTestFep4Uid is used to retrieve state
       
  1135 							}
       
  1136 						else
       
  1137 							{
       
  1138 							CStateInformation* stateInformation=CStateInformation::NewLC(1);
       
  1139 							extension1->SetStateTransferingOwnershipL(stateInformation, TUid::Uid(KTestFep4Uid));
       
  1140 							CleanupStack::Pop(stateInformation);
       
  1141 							}
       
  1142 						DrawNow();
       
  1143 						}
       
  1144 					}
       
  1145 				}
       
  1146 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1147 			case 'N':
       
  1148 				{
       
  1149 				const MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  1150 				if (fepAwareTextEditor==NULL)
       
  1151 					{
       
  1152 					User::InfoPrint(KLitNotAvailable);
       
  1153 					}
       
  1154 				else
       
  1155 					{
       
  1156 					TCursorSelection cursorSelection;
       
  1157 					fepAwareTextEditor->GetCursorSelectionForFep(cursorSelection);
       
  1158 					TPoint position;
       
  1159 					TInt height;
       
  1160 					TInt ascent;
       
  1161 					fepAwareTextEditor->GetScreenCoordinatesForFepL(position,height,ascent,cursorSelection.LowerPos());
       
  1162 					position.iY+=height-ascent;
       
  1163 					const TSize screenSize(iCoeEnv->ScreenDevice()->SizeInPixels());
       
  1164 					const TInt xMaximum=screenSize.iWidth-iSize.iWidth;
       
  1165 					if ((position.iX<0) || (xMaximum<0))
       
  1166 						{
       
  1167 						position.iX=0;
       
  1168 						}
       
  1169 					else if (position.iX>xMaximum)
       
  1170 						{
       
  1171 						position.iX=xMaximum;
       
  1172 						}
       
  1173 					const TInt yMaximum=screenSize.iHeight-iSize.iHeight;
       
  1174 					if ((position.iY<0) || (yMaximum<0))
       
  1175 						{
       
  1176 						position.iY=0;
       
  1177 						}
       
  1178 					else
       
  1179 						{
       
  1180 						const TInt yOverlapIfFepIsBelow=position.iY-yMaximum;
       
  1181 						if (yOverlapIfFepIsBelow>0)
       
  1182 							{
       
  1183 							const TInt yPositionIfFepIsAbove=Max(0, position.iY-(height+iSize.iHeight));
       
  1184 							const TInt yOverlapIfFepIsAbove=(yPositionIfFepIsAbove+iSize.iHeight)-(position.iY-height);
       
  1185 							if (yOverlapIfFepIsAbove<yOverlapIfFepIsBelow)
       
  1186 								{
       
  1187 								position.iY=yPositionIfFepIsAbove;
       
  1188 								}
       
  1189 							}
       
  1190 						}
       
  1191 					SetPosition(position);
       
  1192 					}
       
  1193 				}
       
  1194 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1195 			case 'B':
       
  1196 			case 'A':
       
  1197 			case 'S':
       
  1198 				{
       
  1199 				const MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  1200 				TBuf<40+EMaximumLengthOfDisplayOfContextInformation> textToDisplay;
       
  1201 				if (fepAwareTextEditor==NULL)
       
  1202 					{
       
  1203 					textToDisplay=KLitNotAvailable;
       
  1204 					}
       
  1205 				else
       
  1206 					{
       
  1207 					TCursorSelection cursorSelection;
       
  1208 					fepAwareTextEditor->GetCursorSelectionForFep(cursorSelection);
       
  1209 					switch (keyCodeInUpperCase)
       
  1210 						{
       
  1211 					case 'B':
       
  1212 						{
       
  1213 						TInt lengthToRetrieve=EMaximumLengthOfDisplayOfContextInformation+1;
       
  1214 						TInt documentPositionBeforeSelection=cursorSelection.LowerPos()-lengthToRetrieve;
       
  1215 						if (documentPositionBeforeSelection<0)
       
  1216 							{
       
  1217 							lengthToRetrieve+=documentPositionBeforeSelection; // same as doing "lengthToRetrieve=cursorSelection.LowerPos()", hence the assert below
       
  1218 							__ASSERT_DEBUG(lengthToRetrieve==cursorSelection.LowerPos(), Panic(EPanicArithmeticConfusion));
       
  1219 							documentPositionBeforeSelection=0;
       
  1220 							}
       
  1221 						fepAwareTextEditor->GetEditorContentForFep(textToDisplay, documentPositionBeforeSelection, lengthToRetrieve);
       
  1222 						const TInt lengthOfTextBeforeSelection=textToDisplay.Length();
       
  1223 						if (lengthOfTextBeforeSelection>EMaximumLengthOfDisplayOfContextInformation)
       
  1224 							{
       
  1225 							textToDisplay.Delete(0, (lengthOfTextBeforeSelection-EMaximumLengthOfDisplayOfContextInformation)-1);
       
  1226 							__ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfTextBeforeSelection));
       
  1227 							textToDisplay[0]=KEllipsisCharacter;
       
  1228 							}
       
  1229 						}
       
  1230 						textToDisplay.Insert(0, KLitQuotationMark);
       
  1231 						textToDisplay.Append(KLitQuotationMark);
       
  1232 						textToDisplay.Insert(0, KLitTextBeforeSelectionColonSpace);
       
  1233 						break;
       
  1234 					case 'A':
       
  1235 						{
       
  1236 						const TInt documentLength=fepAwareTextEditor->DocumentLengthForFep();
       
  1237 						const TInt documentPositionAfterSelection=cursorSelection.HigherPos();
       
  1238 						if (documentPositionAfterSelection>documentLength)
       
  1239 							{
       
  1240 							__ASSERT_DEBUG(documentPositionAfterSelection==documentLength+1, Panic(EPanicSelectionExtendsPastEndOfDocument));
       
  1241 							}
       
  1242 						else
       
  1243 							{
       
  1244 							fepAwareTextEditor->GetEditorContentForFep(textToDisplay, documentPositionAfterSelection, EMaximumLengthOfDisplayOfContextInformation+1);
       
  1245 							const TInt lengthOfTextAfterSelection=textToDisplay.Length();
       
  1246 							if (lengthOfTextAfterSelection>EMaximumLengthOfDisplayOfContextInformation)
       
  1247 								{
       
  1248 								textToDisplay.Delete(EMaximumLengthOfDisplayOfContextInformation, (lengthOfTextAfterSelection-EMaximumLengthOfDisplayOfContextInformation)-1);
       
  1249 								__ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfTextAfterSelection));
       
  1250 								textToDisplay[EMaximumLengthOfDisplayOfContextInformation]=KEllipsisCharacter;
       
  1251 								}
       
  1252 							}
       
  1253 						}
       
  1254 						textToDisplay.Insert(0, KLitQuotationMark);
       
  1255 						textToDisplay.Append(KLitQuotationMark);
       
  1256 						textToDisplay.Insert(0, KLitTextAfterSelectionColonSpace);
       
  1257 						break;
       
  1258 					case 'S':
       
  1259 						fepAwareTextEditor->GetEditorContentForFep(textToDisplay, cursorSelection.LowerPos(), cursorSelection.Length());
       
  1260 						{
       
  1261 						const TInt lengthOfSelection=textToDisplay.Length();
       
  1262 						if (lengthOfSelection>EMaximumLengthOfDisplayOfContextInformation)
       
  1263 							{
       
  1264 							textToDisplay.Delete(EMaximumLengthOfDisplayOfContextInformation, (lengthOfSelection-EMaximumLengthOfDisplayOfContextInformation)-1);
       
  1265 							__ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfSelection));
       
  1266 							textToDisplay[EMaximumLengthOfDisplayOfContextInformation]=KEllipsisCharacter;
       
  1267 							}
       
  1268 						}
       
  1269 						textToDisplay.Insert(0, KLitQuotationMark);
       
  1270 						textToDisplay.Append(KLitQuotationMark);
       
  1271 						textToDisplay.Insert(0, KLitSelectionColonSpace);
       
  1272 						break;
       
  1273 #if defined(_DEBUG)
       
  1274 					default:
       
  1275 						Panic(EPanicBadKeyCode1);
       
  1276 						break;
       
  1277 #endif
       
  1278 						}
       
  1279 					}
       
  1280 				User::InfoPrint(textToDisplay);
       
  1281 				}
       
  1282 				FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1283 				}
       
  1284 			}
       
  1285 		}
       
  1286 	if (iInputCapabilities.IsNone() && !isFocused)
       
  1287 		{
       
  1288 		FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasNotConsumed); // returns from this function
       
  1289 		}
       
  1290 	switch (keyCodeInUpperCase)
       
  1291 		{
       
  1292 	case EKeyEnter:
       
  1293 	case EKeyEscape:
       
  1294 		if (isFocused)
       
  1295 			{
       
  1296 			ChangeSetupAndResetBufferAndDrawNow(SetFocus, EFalse);
       
  1297 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1298 			}
       
  1299 		if (bufferLength>0)
       
  1300 			{
       
  1301 			TBool needToDraw=ETrue;
       
  1302 			switch (keyCodeInUpperCase)
       
  1303 				{
       
  1304 			case EKeyEnter:
       
  1305 				if (~iFlags&EFlagInsideInlineEditingTransaction)
       
  1306 					{
       
  1307 					iFep.SimulateKeyEventsL(TArray<TUint>(NumberOfCharactersInBuffer, CharacterInBuffer, this));
       
  1308 					}
       
  1309 				else
       
  1310 					{
       
  1311 					CommitInlineEditL(*iInputCapabilities.FepAwareTextEditor());
       
  1312 					// for pinyin, need redraw candidate characters
       
  1313 					if (iInputMethod != EInputMethodPinYin)
       
  1314 						needToDraw=EFalse;
       
  1315 					}
       
  1316 				break;
       
  1317 			case EKeyEscape:
       
  1318 				if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1319 					{
       
  1320 					CancelInlineEdit(*iInputCapabilities.FepAwareTextEditor());	
       
  1321 					needToDraw=EFalse;
       
  1322 					}
       
  1323 				break;
       
  1324 #if defined(_DEBUG)
       
  1325 			default:
       
  1326 				Panic(EPanicBadKeyCode2);
       
  1327 				break;
       
  1328 #endif
       
  1329 				}
       
  1330 			ResetBuffer();
       
  1331 			if (needToDraw)
       
  1332 				{
       
  1333 				DrawNow();
       
  1334 				}
       
  1335 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1336 			}
       
  1337 		break;
       
  1338 	case EKeyPageUp:
       
  1339 		// For Unicode IME: decrease last Unicode value.
       
  1340 		// For Pinyin IME: find previous character has the same pinyin.
       
  1341 	case EKeyPageDown:
       
  1342 		// For Unicode IME: increase last Unicode value.
       
  1343 		// For Pinyin IME: find next character has the same pinyin.
       
  1344 		if (iInputMethod==EInputMethodHexadecimalCharacterCode)
       
  1345 			{
       
  1346 			// unicode
       
  1347 			if (bufferLength > 0)
       
  1348 				{
       
  1349 				if (bufferLength > 1)
       
  1350 					{
       
  1351 					TText high = iBuffer[bufferLength-2];
       
  1352 					TText low = iBuffer[bufferLength-1];
       
  1353 					TInt characterCode;
       
  1354 					if ((high & 0xF800) == 0xD800 && (low & 0xF800) == 0xD800)
       
  1355 						{
       
  1356 						characterCode = ((high - 0xd7f7) << 10) + low;
       
  1357 						if (characterCode > 0x10000 & characterCode < 0x2FFFE)
       
  1358 							{
       
  1359 							if (keyCodeInUpperCase == EKeyPageUp)
       
  1360 								characterCode--;
       
  1361 							else
       
  1362 								characterCode++;
       
  1363 							iBuffer[bufferLength-2] = (TText)(0xD7C0 + (characterCode >> 10));
       
  1364 							iBuffer[bufferLength-1] = (TText)(0xDC00 | (characterCode & 0x03FF));
       
  1365 							if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1366 								{
       
  1367 								SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1368 								}
       
  1369 							else
       
  1370 								{
       
  1371 								DrawNow();
       
  1372 								}
       
  1373 							FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1374 							}
       
  1375 						}
       
  1376 					}
       
  1377 				else
       
  1378 					{
       
  1379 					if ((iBuffer[bufferLength-1] & 0xF800) != 0xD800)
       
  1380 						{
       
  1381 						TText characterCode = (keyCodeInUpperCase == EKeyPageUp) ? (iBuffer[bufferLength-1]-1) : (iBuffer[bufferLength-1]+1);
       
  1382 						if (characterCode <= 0xFFFF)
       
  1383 							{
       
  1384 							iBuffer[bufferLength-1] = characterCode;
       
  1385 							if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1386 								{
       
  1387 								SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1388 								}
       
  1389 							else
       
  1390 								{
       
  1391 								DrawNow();
       
  1392 								}
       
  1393 							FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1394 							}
       
  1395 						}
       
  1396 					}
       
  1397 				}
       
  1398 			}
       
  1399 		else if (iInputMethod==EInputMethodPinYin)
       
  1400 			{
       
  1401 			// pinyin
       
  1402 			if (bufferLength > 0)
       
  1403 				{
       
  1404 				TInt characterCode = (keyCodeInUpperCase == EKeyPageUp)
       
  1405 									? iPinYinSelector.PreviousPage()
       
  1406 									: iPinYinSelector.NextPage();
       
  1407 				if (characterCode != CPinyinSelector::EInvalidChar)
       
  1408 					{
       
  1409 					TInt positionOfNewText = iSelectedCompositionText.LowerPos();
       
  1410 					
       
  1411 					TInt byteCount = 1;		// byte count of current char
       
  1412 					if (bufferLength >= 2 && (iBuffer[positionOfNewText-1] & 0xF800) == 0xD800)
       
  1413 						{
       
  1414 						byteCount = 2;
       
  1415 						}
       
  1416 					if (characterCode > 0x10000 & characterCode < 0x2FFFE)
       
  1417 						{
       
  1418 						if (byteCount == 1)
       
  1419 							{
       
  1420 							_LIT(KOneSpace, " ");
       
  1421 							iBuffer.Insert(positionOfNewText-1, KOneSpace);
       
  1422 							positionOfNewText++;
       
  1423 							SetPositionOfInsertionPointInBuffer(positionOfNewText+1);
       
  1424 							}
       
  1425 						iBuffer[positionOfNewText-2] = (TText)(0xD7C0 + (characterCode >> 10));
       
  1426 						iBuffer[positionOfNewText-1] = (TText)(0xDC00 | (characterCode & 0x03FF));
       
  1427 						}
       
  1428 					else if (characterCode >=0 && characterCode <= 0xFFFF)
       
  1429 						{
       
  1430 						if (byteCount == 2)
       
  1431 							{
       
  1432 							iBuffer.Delete(positionOfNewText-1, 1);
       
  1433 							positionOfNewText--;
       
  1434 							SetPositionOfInsertionPointInBuffer(positionOfNewText);//-1);
       
  1435 							}
       
  1436 						iBuffer[positionOfNewText-1] = characterCode;
       
  1437 						}
       
  1438 					
       
  1439 					// redraw
       
  1440 					if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1441 						{
       
  1442 						DrawNow();		// for character selector
       
  1443 						SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1444 						}
       
  1445 					else
       
  1446 						{
       
  1447 						DrawNow();
       
  1448 						}
       
  1449 					FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1450 					}
       
  1451 				}
       
  1452 			}
       
  1453 		break;
       
  1454 	case EKeyDelete:
       
  1455 	case EKeyBackspace:
       
  1456 		if (!isFocused && (bufferLength>0))
       
  1457 			{
       
  1458 			TCursorSelection portionToDelete(iSelectedCompositionText.iCursorPos, iSelectedCompositionText.iAnchorPos);
       
  1459 			const TBool deleteLeft=((keyCodeInUpperCase==EKeyBackspace) && !(aKeyEvent.iModifiers&EModifierShift));
       
  1460 			if (portionToDelete.Length()==0)
       
  1461 				{
       
  1462 				if (deleteLeft)
       
  1463 					{
       
  1464 					if (portionToDelete.iCursorPos>0)
       
  1465 						{
       
  1466 						//    If surrogate low part is deleted, then delete surrogate high part too
       
  1467 						if ( IsLowSurrogate( iBuffer[ portionToDelete.iCursorPos - 1 ] ) )
       
  1468 						    --portionToDelete.iCursorPos;
       
  1469 						--portionToDelete.iCursorPos;
       
  1470 						}
       
  1471 					}
       
  1472 				else
       
  1473 					{
       
  1474 					if (portionToDelete.iCursorPos<bufferLength)
       
  1475 						{
       
  1476 						++portionToDelete.iCursorPos;
       
  1477 						}
       
  1478 					}
       
  1479 				}
       
  1480 			if (portionToDelete.Length()>0)
       
  1481 				{
       
  1482 				TTstTextBackup textBackup=iBuffer;
       
  1483 				textBackup.PushOntoCleanupStackL();
       
  1484 				SetPositionOfInsertionPointInBuffer(portionToDelete.LowerPos());
       
  1485 				iBuffer.Delete(portionToDelete.LowerPos(), portionToDelete.Length());
       
  1486 				//  Reset buffer length because we may delete more than one byte for surrogate parts
       
  1487 				bufferLength = iBuffer.Length();
       
  1488 				if (~iFlags&EFlagInsideInlineEditingTransaction)
       
  1489 					{
       
  1490 					DrawNow();
       
  1491 					}
       
  1492 				else
       
  1493 					{
       
  1494 					if (bufferLength-1>0)
       
  1495 						{
       
  1496 						SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1497 						}
       
  1498 					else
       
  1499 						{
       
  1500 						CancelInlineEdit(*iInputCapabilities.FepAwareTextEditor());
       
  1501 						}
       
  1502 					}
       
  1503 				textBackup.PopOffCleanupStack();
       
  1504 				}
       
  1505 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1506 			}
       
  1507 		break;
       
  1508 	case EKeySpace:
       
  1509 		if (!isFocused && (bufferLength>0))
       
  1510 			{
       
  1511 			__ASSERT_DEBUG((iInputMethod==EInputMethodPlain) || (iInputMethod==EInputMethodHexadecimalCharacterCode) || (iInputMethod==EInputMethodPinYin), Panic(EPanicBadInputMethod2));
       
  1512 			if ((iInputMethod==EInputMethodPlain) && (iSelectedCompositionText.iCursorPos<bufferLength))
       
  1513 				{
       
  1514 				const TInt increment=(aKeyEvent.iModifiers&EModifierShift)? -1: 1;
       
  1515 				const TCharUC limit=(aKeyEvent.iModifiers&EModifierShift)? 'A': 'Z';
       
  1516 				const TCharUC characterToAdjust=iBuffer[iSelectedCompositionText.iCursorPos];
       
  1517 				__ASSERT_DEBUG((characterToAdjust>='A') && (characterToAdjust<='Z'), Panic(EPanicBadCharacterInBuffer));
       
  1518 				if (characterToAdjust!=limit)
       
  1519 					{
       
  1520 					TTstTextBackup textBackup=iBuffer;
       
  1521 					textBackup.PushOntoCleanupStackL();
       
  1522 					iBuffer[iSelectedCompositionText.iCursorPos]=(TText)(iBuffer[iSelectedCompositionText.iCursorPos]+increment);
       
  1523 					if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1524 						{
       
  1525 						SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1526 						}
       
  1527 					else
       
  1528 						{
       
  1529 						DrawNow();
       
  1530 						}
       
  1531 					textBackup.PopOffCleanupStack();
       
  1532 					}
       
  1533 				}
       
  1534 			else if (iInputMethod == EInputMethodPinYin)
       
  1535 				{
       
  1536 				iCharacterCode=aKeyEvent.iCode; // set iCharacterCode to aKeyEvent.iCode rather than keyCodeInUpperCase so that the original case is preserved
       
  1537 				iFep.MakeDeferredFunctionCall(*this); // deferred call to InsertCompositionCharacterAndDrawNowL
       
  1538 				if (bufferLength==0)
       
  1539 					{
       
  1540 					iCoeEnv->ForEachFepObserverCall(FepObserverHandleStartOfTransactionL); // must be called before inserting the composition character as an application's HandleStartOfTransactionL function may move focus to a control supporting inline-editing
       
  1541 					}
       
  1542 				}
       
  1543 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1544 			}
       
  1545 		break;
       
  1546 	case '1':
       
  1547 	case '2':
       
  1548 	case '3':
       
  1549 	case '4':
       
  1550 	case '5':
       
  1551 	case '6':
       
  1552 	case '7':
       
  1553 	case '8':
       
  1554 	case '9':
       
  1555 		if (iInputMethod==EInputMethodPinYin)
       
  1556 			{
       
  1557 			if (!isFocused && (bufferLength>0))
       
  1558 				{
       
  1559 				if (!iPinYinSelector.IsReseted())
       
  1560 					{
       
  1561 					TInt characterCode = iPinYinSelector.CharacterInCurrentPage(keyCodeInUpperCase-'0'-1);
       
  1562 					// below code copy from EPageDown
       
  1563 					if (characterCode != CPinyinSelector::EInvalidChar)
       
  1564 						{
       
  1565 						TInt positionOfNewText = iSelectedCompositionText.LowerPos();
       
  1566 						
       
  1567 						TInt byteCount = 1;		// byte count of current char
       
  1568 						if (bufferLength >= 2 && (iBuffer[positionOfNewText-1] & 0xF800) == 0xD800)
       
  1569 							{
       
  1570 							byteCount = 2;
       
  1571 							}
       
  1572 						if (characterCode > 0x10000 & characterCode < 0x2FFFE)
       
  1573 							{
       
  1574 							if (byteCount == 1)
       
  1575 								{
       
  1576 								_LIT(KOneSpace, " ");
       
  1577 								iBuffer.Insert(positionOfNewText-1, KOneSpace);
       
  1578 								positionOfNewText++;
       
  1579 								SetPositionOfInsertionPointInBuffer(positionOfNewText+1);
       
  1580 								}
       
  1581 							iBuffer[positionOfNewText-2] = (TText)(0xD7C0 + (characterCode >> 10));
       
  1582 							iBuffer[positionOfNewText-1] = (TText)(0xDC00 | (characterCode & 0x03FF));
       
  1583 							}
       
  1584 						else if (characterCode >=0 && characterCode <= 0xFFFF)
       
  1585 							{
       
  1586 							if (byteCount == 2)
       
  1587 								{
       
  1588 								iBuffer.Delete(positionOfNewText-1, 1);
       
  1589 								positionOfNewText--;
       
  1590 								SetPositionOfInsertionPointInBuffer(positionOfNewText);//-1);
       
  1591 								}
       
  1592 							iBuffer[positionOfNewText-1] = characterCode;
       
  1593 							}
       
  1594 						
       
  1595 						if (positionOfNewText < iBuffer.Length())
       
  1596 							{
       
  1597 							// simulate a SPACE keypress, to process next pinyin
       
  1598 							iCharacterCode = 32; // set iCharacterCode to aKeyEvent.iCode rather than keyCodeInUpperCase so that the original case is preserved
       
  1599 							iFep.MakeDeferredFunctionCall(*this); // deferred call to InsertCompositionCharacterAndDrawNowL
       
  1600 							}
       
  1601 
       
  1602 						// redraw
       
  1603 						if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1604 							{
       
  1605 							DrawNow();		// for character selector
       
  1606 							SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1607 							}
       
  1608 						else
       
  1609 							{
       
  1610 							DrawNow();
       
  1611 							}
       
  1612 						FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1613 						}
       
  1614 					}
       
  1615 				}
       
  1616 			break;
       
  1617 			}
       
  1618 		else
       
  1619 			{
       
  1620 			// goto default case for other IME
       
  1621 			goto __label_default;
       
  1622 			}
       
  1623 	case EKeyHome:
       
  1624 	case EKeyEnd:
       
  1625 //	case EKeyPageUp:
       
  1626 //	case EKeyPageDown:
       
  1627 	case EKeyLeftArrow:
       
  1628 	case EKeyRightArrow:
       
  1629 	case EKeyUpArrow:
       
  1630 	case EKeyDownArrow:
       
  1631 		if (isFocused)
       
  1632 			{
       
  1633 			TPoint offset(0, 0);
       
  1634 			TInt magnification=10;
       
  1635 			switch (keyCodeInUpperCase)
       
  1636 				{
       
  1637 			case EKeyLeftArrow:
       
  1638 				offset.iX=-1;
       
  1639 				break;
       
  1640 			case EKeyRightArrow:
       
  1641 				offset.iX=1;
       
  1642 				break;
       
  1643 			case EKeyUpArrow:
       
  1644 				offset.iY=-1;
       
  1645 				break;
       
  1646 			case EKeyDownArrow:
       
  1647 				offset.iY=1;
       
  1648 				break;
       
  1649 			case EKeyHome:
       
  1650 				offset.iX=-iPosition.iX;
       
  1651 				offset.iY=-iPosition.iY;
       
  1652 				magnification=1;
       
  1653 				break;
       
  1654 			case EKeyEnd:
       
  1655 				{
       
  1656 				const TSize screenWidth(iCoeEnv->ScreenDevice()->SizeInPixels());
       
  1657 				offset.iX=(screenWidth.iWidth-iSize.iWidth)-iPosition.iX;
       
  1658 				offset.iY=(screenWidth.iHeight-iSize.iHeight)-iPosition.iY;
       
  1659 				}
       
  1660 				magnification=1;
       
  1661 				break;
       
  1662 			case EKeyPageUp:
       
  1663 				offset.iY=-iSize.iHeight;
       
  1664 				magnification=1;
       
  1665 				break;
       
  1666 			case EKeyPageDown:
       
  1667 				offset.iY=iSize.iHeight;
       
  1668 				magnification=1;
       
  1669 				break;
       
  1670 #if defined(_DEBUG)
       
  1671 			default:
       
  1672 				Panic(EPanicBadKeyCode3);
       
  1673 				break;
       
  1674 #endif
       
  1675 				}
       
  1676 			if (aKeyEvent.iModifiers&EModifierCtrl)
       
  1677 				{
       
  1678 				offset.iX*=magnification;
       
  1679 				offset.iY*=magnification;
       
  1680 				}
       
  1681 			SetPosition(TPoint(iPosition.iX+offset.iX, iPosition.iY+offset.iY));
       
  1682 			if (iFlags&EFlagWindowIsBeingDragged)
       
  1683 				{
       
  1684 				iPositionOnWindowBeingDragged.iX-=offset.iX;
       
  1685 				iPositionOnWindowBeingDragged.iY-=offset.iY;
       
  1686 				}
       
  1687 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1688 			}
       
  1689 		if (bufferLength>0)
       
  1690 			{
       
  1691 			TInt newPositionOfInsertionPointInBuffer=iSelectedCompositionText.iCursorPos;
       
  1692 			switch (keyCodeInUpperCase)
       
  1693 				{
       
  1694 			case EKeyLeftArrow:
       
  1695 				if (newPositionOfInsertionPointInBuffer>0)
       
  1696 					{
       
  1697 					--newPositionOfInsertionPointInBuffer;
       
  1698 					}
       
  1699 				break;
       
  1700 			case EKeyRightArrow:
       
  1701 				if (newPositionOfInsertionPointInBuffer<bufferLength)
       
  1702 					{
       
  1703 					++newPositionOfInsertionPointInBuffer;
       
  1704 					}
       
  1705 				break;
       
  1706 			case EKeyHome:
       
  1707 			case EKeyPageUp:
       
  1708 			case EKeyUpArrow:
       
  1709 				newPositionOfInsertionPointInBuffer=0;
       
  1710 				break;
       
  1711 			case EKeyEnd:
       
  1712 			case EKeyPageDown:
       
  1713 			case EKeyDownArrow:
       
  1714 				newPositionOfInsertionPointInBuffer=bufferLength;
       
  1715 				break;
       
  1716 #if defined(_DEBUG)
       
  1717 			default:
       
  1718 				Panic(EPanicBadKeyCode4);
       
  1719 				break;
       
  1720 #endif
       
  1721 				}
       
  1722 			if (iSelectedCompositionText.iCursorPos!=newPositionOfInsertionPointInBuffer)
       
  1723 				{
       
  1724 				if ((iSelectedCompositionText.Length()>0) && !(aKeyEvent.iModifiers&EModifierShift))
       
  1725 					{
       
  1726 					if (newPositionOfInsertionPointInBuffer<iSelectedCompositionText.iCursorPos)
       
  1727 						{
       
  1728 						newPositionOfInsertionPointInBuffer=iSelectedCompositionText.LowerPos();
       
  1729 						}
       
  1730 					else
       
  1731 						{
       
  1732 						newPositionOfInsertionPointInBuffer=iSelectedCompositionText.HigherPos();
       
  1733 						}
       
  1734 					}
       
  1735 				}
       
  1736 			const TInt newPositionOfAnchorInBuffer=(aKeyEvent.iModifiers&EModifierShift)? iSelectedCompositionText.iAnchorPos: newPositionOfInsertionPointInBuffer;
       
  1737 			if ((iSelectedCompositionText.iCursorPos!=newPositionOfInsertionPointInBuffer) || (iSelectedCompositionText.iAnchorPos!=newPositionOfAnchorInBuffer))
       
  1738 				{
       
  1739 				const TBool needToDraw=((iSelectedCompositionText.Length()>0) || (aKeyEvent.iModifiers&EModifierShift)); // don't need to draw if there is no selected text as a result of this event, or if there previously was no selected text before this event
       
  1740 				SetPositionOfInsertionPointInBuffer(newPositionOfInsertionPointInBuffer, newPositionOfAnchorInBuffer);
       
  1741 				if (iFlags&EFlagInsideInlineEditingTransaction)
       
  1742 					{
       
  1743 					SetInlineTextL(*iInputCapabilities.FepAwareTextEditor());
       
  1744 					}
       
  1745 				else if (needToDraw)
       
  1746 					{
       
  1747 					DrawNow();
       
  1748 					}
       
  1749 				}
       
  1750 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1751 			}
       
  1752 		break;
       
  1753 	default:
       
  1754 __label_default:
       
  1755 		if (isFocused)
       
  1756 			{
       
  1757 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1758 			}
       
  1759 		TBool isLegalCompositionCharacter=EFalse;
       
  1760 		switch (iInputMethod)
       
  1761 			{
       
  1762 		case EInputMethodPlain:
       
  1763 			if (iInputCapabilities.SupportsAllText())
       
  1764 				{
       
  1765 				isLegalCompositionCharacter=keyCodeInUpperCase.IsPrint();
       
  1766 				}
       
  1767 			else
       
  1768 				{
       
  1769 				const TBool isDigit=((keyCodeInUpperCase>='0') && (keyCodeInUpperCase<='9'));
       
  1770 				isLegalCompositionCharacter=(iInputCapabilities.SupportsWesternNumericIntegerPositive() && isDigit);
       
  1771 				if (isLegalCompositionCharacter)
       
  1772 					{
       
  1773 					break;
       
  1774 					}
       
  1775 				isLegalCompositionCharacter=(iInputCapabilities.SupportsWesternNumericIntegerNegative() && (isDigit || ((iSelectedCompositionText.LowerPos()==0) && (keyCodeInUpperCase=='-'))));
       
  1776 				if (isLegalCompositionCharacter)
       
  1777 					{
       
  1778 					break;
       
  1779 					}
       
  1780 				isLegalCompositionCharacter=(iInputCapabilities.SupportsWesternNumericReal() && (isDigit || IsLegalNonDigitForRealNumber(keyCodeInUpperCase)));
       
  1781 				if (isLegalCompositionCharacter)
       
  1782 					{
       
  1783 					break;
       
  1784 					}
       
  1785 				const TUint foldFlags=(TChar::EFoldCase|TChar::EFoldAccents);
       
  1786 				const TUint foldedKeyCode=User::Fold(keyCodeInUpperCase, foldFlags);
       
  1787 				isLegalCompositionCharacter=(iInputCapabilities.SupportsWesternAlphabetic() && (foldedKeyCode>=User::Fold('A', foldFlags)) && (foldedKeyCode<=User::Fold('Z', foldFlags)));
       
  1788 				if (isLegalCompositionCharacter)
       
  1789 					{
       
  1790 					break;
       
  1791 					}
       
  1792 				}
       
  1793 			break;
       
  1794 		case EInputMethodHexadecimalCharacterCode:
       
  1795 			isLegalCompositionCharacter=keyCodeInUpperCase.IsHexDigit();
       
  1796 			break;
       
  1797 		case EInputMethodPinYin:
       
  1798 			isLegalCompositionCharacter = (keyCodeInUpperCase.IsAlpha() || keyCodeInUpperCase.IsSpace());
       
  1799 			break;
       
  1800 		case EInputMethodOnePastTheLast:
       
  1801 #if defined(_DEBUG)
       
  1802 		default:
       
  1803 			Panic(EPanicBadInputMethod3);
       
  1804 #endif
       
  1805 			break;
       
  1806 			}
       
  1807 		if (isLegalCompositionCharacter)
       
  1808 			{
       
  1809 			iCharacterCode=aKeyEvent.iCode; // set iCharacterCode to aKeyEvent.iCode rather than keyCodeInUpperCase so that the original case is preserved
       
  1810 			iFep.MakeDeferredFunctionCall(*this); // deferred call to InsertCompositionCharacterAndDrawNowL
       
  1811 			if (bufferLength==0)
       
  1812 				{
       
  1813 				iCoeEnv->ForEachFepObserverCall(FepObserverHandleStartOfTransactionL); // must be called before inserting the composition character as an application's HandleStartOfTransactionL function may move focus to a control supporting inline-editing
       
  1814 				}
       
  1815 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1816 			}
       
  1817 		if (bufferLength>0)
       
  1818 			{
       
  1819 			FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function
       
  1820 			}
       
  1821 		break;
       
  1822 		}
       
  1823 	FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasNotConsumed); // returns from this function
       
  1824 	}
       
  1825 
       
  1826 void CTstControl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
       
  1827 	{
       
  1828 	switch (aPointerEvent.iType)
       
  1829 		{
       
  1830 	case TPointerEvent::EButton1Down:
       
  1831 		if (IsFocused() ||
       
  1832 			(iFlags&EFlagHasNoCompositionWindow) ||
       
  1833 			(aPointerEvent.iPosition.iX<1) || (aPointerEvent.iPosition.iX>=iSize.iWidth-1) ||
       
  1834 			(aPointerEvent.iPosition.iY<1) || (aPointerEvent.iPosition.iY>=1+EGapAboveCompositionLine+iCompositionFont->HeightInPixels()+EGapBelowCompositionLine))
       
  1835 			{
       
  1836 			iFlags|=EFlagWindowIsBeingDragged;
       
  1837 			iPositionOnWindowBeingDragged=aPointerEvent.iPosition;
       
  1838 			}
       
  1839 		else
       
  1840 			{
       
  1841 			if (~iFlags&EFlagInsideInlineEditingTransaction)
       
  1842 				{
       
  1843 				const TInt newPositionOfInsertionPointInBuffer=PositionInBuffer(aPointerEvent.iPosition.iX);
       
  1844 				const TInt newPositionOfAnchorInBuffer=(aPointerEvent.iModifiers&EModifierShift)? iSelectedCompositionText.iAnchorPos: newPositionOfInsertionPointInBuffer;
       
  1845 				if ((iSelectedCompositionText.iCursorPos!=newPositionOfInsertionPointInBuffer) || (iSelectedCompositionText.iAnchorPos!=newPositionOfAnchorInBuffer))
       
  1846 					{
       
  1847 					const TBool needToDraw=((iSelectedCompositionText.Length()>0) || (aPointerEvent.iModifiers&EModifierShift)); // don't need to draw if there is no selected text as a result of this event, or if there previously was no selected text before this event
       
  1848 					SetPositionOfInsertionPointInBuffer(newPositionOfInsertionPointInBuffer, newPositionOfAnchorInBuffer);
       
  1849 					if (needToDraw)
       
  1850 						{
       
  1851 						DrawNow();
       
  1852 						}
       
  1853 					}
       
  1854 				}
       
  1855 			}
       
  1856 		break;
       
  1857 	case TPointerEvent::EDrag:
       
  1858 		if (iFlags&EFlagWindowIsBeingDragged)
       
  1859 			{
       
  1860 			SetPosition(aPointerEvent.iParentPosition-iPositionOnWindowBeingDragged);
       
  1861 			}
       
  1862 		else
       
  1863 			{
       
  1864 			if (~iFlags&EFlagInsideInlineEditingTransaction)
       
  1865 				{
       
  1866 				const TInt newPositionOfInsertionPointInBuffer=PositionInBuffer(aPointerEvent.iPosition.iX);
       
  1867 				if (iSelectedCompositionText.iCursorPos!=newPositionOfInsertionPointInBuffer)
       
  1868 					{
       
  1869 					SetPositionOfInsertionPointInBuffer(newPositionOfInsertionPointInBuffer, iSelectedCompositionText.iAnchorPos);
       
  1870 					DrawNow();
       
  1871 					}
       
  1872 				}
       
  1873 			}
       
  1874 		break;
       
  1875 	case TPointerEvent::EButton1Up:
       
  1876 		iFlags&=~EFlagWindowIsBeingDragged;
       
  1877 		break;
       
  1878 #if defined(__GCC32__)
       
  1879 	default:
       
  1880 		break;
       
  1881 #endif
       
  1882 		}
       
  1883 	}
       
  1884 
       
  1885 void CTstControl::Draw(const TRect&) const
       
  1886 	{
       
  1887 	CWindowGc& graphicsContext=SystemGc();
       
  1888 	graphicsContext.SetPenStyle(CGraphicsContext::ESolidPen);
       
  1889 	graphicsContext.SetPenColor(KRgbBlack);
       
  1890 	graphicsContext.SetBrushStyle(CGraphicsContext::ENullBrush);
       
  1891 	TRect rectangle(Rect());
       
  1892 	graphicsContext.DrawRect(rectangle);
       
  1893 	rectangle.Shrink(1, 1);
       
  1894 	graphicsContext.SetBrushStyle(CGraphicsContext::ESolidBrush);
       
  1895 	if (IsFocused())
       
  1896 		{
       
  1897 		__ASSERT_DEBUG(iBuffer.Length()==0, Panic(EPanicInconsistentState));
       
  1898 		// the pen color is still black here
       
  1899 		graphicsContext.SetBrushColor(KRgbBlack);
       
  1900 		graphicsContext.DrawRect(rectangle);
       
  1901 		const TPoint center=rectangle.Center();
       
  1902 		graphicsContext.SetPenColor(KRgbWhite);
       
  1903 		const TPoint leftArrowHead((rectangle.iTl.iX+center.iX)/2, center.iY);
       
  1904 		const TPoint rightArrowHead((center.iX+rectangle.iBr.iX)/2, center.iY);
       
  1905 		const TPoint topArrowHead(center.iX, (rectangle.iTl.iY+center.iY)/2);
       
  1906 		const TPoint bottomArrowHead(center.iX, (center.iY+rectangle.iBr.iY)/2);
       
  1907 		graphicsContext.DrawLine(leftArrowHead, rightArrowHead);
       
  1908 		graphicsContext.Plot(rightArrowHead);
       
  1909 		graphicsContext.DrawLine(topArrowHead, bottomArrowHead);
       
  1910 		graphicsContext.Plot(bottomArrowHead);
       
  1911 		graphicsContext.DrawLine(TPoint(leftArrowHead.iX+EArrowHeadSize, leftArrowHead.iY+EArrowHeadSize), leftArrowHead);
       
  1912 		graphicsContext.DrawLine(TPoint(leftArrowHead.iX+EArrowHeadSize, leftArrowHead.iY-EArrowHeadSize), leftArrowHead);
       
  1913 		graphicsContext.DrawLine(TPoint(rightArrowHead.iX-EArrowHeadSize, rightArrowHead.iY-EArrowHeadSize), rightArrowHead);
       
  1914 		graphicsContext.DrawLine(TPoint(rightArrowHead.iX-EArrowHeadSize, rightArrowHead.iY+EArrowHeadSize), rightArrowHead);
       
  1915 		graphicsContext.DrawLine(TPoint(topArrowHead.iX-EArrowHeadSize, topArrowHead.iY+EArrowHeadSize), topArrowHead);
       
  1916 		graphicsContext.DrawLine(TPoint(topArrowHead.iX+EArrowHeadSize, topArrowHead.iY+EArrowHeadSize), topArrowHead);
       
  1917 		graphicsContext.DrawLine(TPoint(bottomArrowHead.iX+EArrowHeadSize, bottomArrowHead.iY-EArrowHeadSize), bottomArrowHead);
       
  1918 		graphicsContext.DrawLine(TPoint(bottomArrowHead.iX-EArrowHeadSize, bottomArrowHead.iY-EArrowHeadSize), bottomArrowHead);
       
  1919 		}
       
  1920 	else
       
  1921 		{
       
  1922 		TRect temp(rectangle);
       
  1923 		temp.iBr.iY=temp.iTl.iY;
       
  1924 		graphicsContext.SetBrushColor(KRgbWhite);
       
  1925 		if (~iFlags&EFlagHasNoCompositionWindow)
       
  1926 			{
       
  1927 			graphicsContext.UseFont(iCompositionFont);
       
  1928 			temp.iBr.iY+=EGapAboveCompositionLine+iCompositionFont->HeightInPixels()+EGapBelowCompositionLine;
       
  1929 			TRect temp2=temp;
       
  1930 			const TInt startOfSelectedCompositionText=iSelectedCompositionText.LowerPos();
       
  1931 			const TPtrC textBeforeSelectedText(iBuffer.Left(startOfSelectedCompositionText));
       
  1932 			temp2.iBr.iX=temp2.iTl.iX;
       
  1933 			temp2.iBr.iX+=iCompositionFont->TextWidthInPixels(textBeforeSelectedText);
       
  1934 			graphicsContext.SetPenColor(KRgbRed);
       
  1935 			graphicsContext.DrawText(textBeforeSelectedText, temp2, EGapAboveCompositionLine+iCompositionFont->AscentInPixels(), CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1936 			
       
  1937 			const TPtrC selectedText(iBuffer.Mid(startOfSelectedCompositionText, iSelectedCompositionText.Length()));
       
  1938 			temp2.iTl.iX=temp2.iBr.iX;
       
  1939 			temp2.iBr.iX+=iCompositionFont->TextWidthInPixels(selectedText);
       
  1940 			graphicsContext.SetPenColor(KRgbGreen);
       
  1941 			graphicsContext.DrawText(selectedText, temp2, EGapAboveCompositionLine+iCompositionFont->AscentInPixels(), CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1942 			
       
  1943 			const TPtrC textAfterSelectedText(iBuffer.Mid(iSelectedCompositionText.HigherPos()));
       
  1944 			temp2.iTl.iX=temp2.iBr.iX;
       
  1945 			temp2.iBr.iX=temp.iBr.iX;
       
  1946 			graphicsContext.SetPenColor(KRgbBlue);//KRgbRed);
       
  1947 			graphicsContext.DrawText(textAfterSelectedText, temp2, EGapAboveCompositionLine+iCompositionFont->AscentInPixels(), CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1948 			graphicsContext.DiscardFont();
       
  1949 			graphicsContext.SetPenColor(KRgbBlack);
       
  1950 			}
       
  1951 		
       
  1952 		TBuf<200> textToDisplay;
       
  1953 		const TInt statusFontHeightInPixels=iStatusFont->HeightInPixels();
       
  1954 		const TInt statusFontAscentInPixels=iStatusFont->AscentInPixels();
       
  1955 		
       
  1956 		// character selector
       
  1957 		graphicsContext.SetBrushColor(KRgbBlue);
       
  1958 		graphicsContext.SetPenColor(KRgbYellow);
       
  1959 		graphicsContext.UseFont(iCompositionFont);
       
  1960 		iPinYinSelector.GetPageDescriptor(&textToDisplay);
       
  1961 		temp.iTl.iY = temp.iBr.iY;
       
  1962 		temp.iBr.iY += EGapAboveCompositionLine + iCompositionFont->HeightInPixels() + EGapBelowCompositionLine;
       
  1963 		graphicsContext.DrawText(textToDisplay, temp, EGapAboveCompositionLine+iCompositionFont->AscentInPixels(), CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1964 		graphicsContext.DiscardFont();
       
  1965 		
       
  1966 		graphicsContext.SetBrushColor(KRgbGray);
       
  1967 		graphicsContext.SetPenColor(KRgbBlack);
       
  1968 		graphicsContext.UseFont(iStatusFont);
       
  1969 
       
  1970 		// Input method: ...
       
  1971 		textToDisplay=KLitInputMethodColonSpace;
       
  1972 		switch (iInputMethod)
       
  1973 			{
       
  1974 		case EInputMethodPlain:
       
  1975 			textToDisplay.Append(KLitPlain);
       
  1976 			break;
       
  1977 		case EInputMethodHexadecimalCharacterCode:
       
  1978 			textToDisplay.Append(KLitHexadecimalCharacterCode);
       
  1979 			break;
       
  1980 		case EInputMethodPinYin:
       
  1981 			textToDisplay.Append(KLitPinYin);
       
  1982 			break;
       
  1983 		default:
       
  1984 #if defined(_DEBUG)
       
  1985 			Panic(EPanicBadInputMethod5);
       
  1986 #endif
       
  1987 			break;
       
  1988 			}
       
  1989 		temp.iTl.iY=temp.iBr.iY;
       
  1990 		temp.iBr.iY+=EGapAboveTopStatusLine+statusFontHeightInPixels+EGapBetweenEachStatusLine;
       
  1991 		graphicsContext.DrawText(textToDisplay, temp, EGapAboveTopStatusLine+statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1992 		
       
  1993 		// Inline editing: ...
       
  1994 		textToDisplay=KLitInlineEditingColonSpace;
       
  1995 		textToDisplay.Append((iFlags&EFlagInlineEditingEnabled)? KLitEnabled(): KLitDisabled());
       
  1996 		temp.iTl.iY=temp.iBr.iY;
       
  1997 		temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachStatusLine;
       
  1998 		graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  1999 		
       
  2000 		// [Caption: "..."]
       
  2001 		textToDisplay=KLitOpeningSquareBracket;
       
  2002 		textToDisplay.Append(KLitCaptionColonSpace);
       
  2003 		textToDisplay.Append(KLitQuotationMark);
       
  2004 		const MCoeCaptionRetrieverForFep* captionRetrieverForFep=iInputCapabilities.CaptionRetrieverForFep();
       
  2005 		if (captionRetrieverForFep!=NULL)
       
  2006 			{
       
  2007 			TBuf<51> caption;
       
  2008 			captionRetrieverForFep->GetCaptionForFep(caption);
       
  2009 			const TInt captionLength=caption.Length();
       
  2010 			if (captionLength==caption.MaxLength())
       
  2011 				{
       
  2012 				caption[captionLength-1]=KEllipsisCharacter;
       
  2013 				}
       
  2014 			textToDisplay.Append(caption);
       
  2015 			}
       
  2016 		textToDisplay.Append(KLitQuotationMark);
       
  2017 		textToDisplay.Append(KLitClosingSquareBracket);
       
  2018 		temp.iTl.iY=temp.iBr.iY;
       
  2019 		temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachStatusLine;
       
  2020 		graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  2021 		
       
  2022 		// [State: "..."]
       
  2023 		textToDisplay=KLitOpeningSquareBracket;
       
  2024 		textToDisplay.Append(KLitStateColonSpace);
       
  2025 		textToDisplay.Append(KLitQuotationMark);
       
  2026 		MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  2027 		if (fepAwareTextEditor!=NULL)
       
  2028 			{
       
  2029 			MCoeFepAwareTextEditor_Extension1* const extension1=fepAwareTextEditor->Extension1();
       
  2030 			if (extension1!=NULL)
       
  2031 				{
       
  2032 				MCoeFepAwareTextEditor_Extension1::CState* const state=extension1->State(TUid::Uid(KTestFep4Uid));
       
  2033 				if (state!=NULL)
       
  2034 					{
       
  2035 					textToDisplay.AppendNum(STATIC_CAST(CStateInformation*, state)->MeaninglessNumber()); // this cast is safe as KTestFep4Uid is used to retrieve state
       
  2036 					}
       
  2037 				}
       
  2038 			}
       
  2039 		textToDisplay.Append(KLitQuotationMark);
       
  2040 		textToDisplay.Append(KLitClosingSquareBracket);
       
  2041 		temp.iTl.iY=temp.iBr.iY;
       
  2042 		temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachStatusLine;
       
  2043 		graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  2044 		
       
  2045 		// [Input-capabilities: ...]
       
  2046 		textToDisplay=KLitOpeningSquareBracket;
       
  2047 		textToDisplay.Append(KLitInputCapabilitiesColonSpace);
       
  2048 		if (iInputCapabilities.IsNone())
       
  2049 			{
       
  2050 			textToDisplay.Append(KLitNone);
       
  2051 			}
       
  2052 		else
       
  2053 			{
       
  2054 			TBool deleteLastSeparator=EFalse;
       
  2055 			if (iInputCapabilities.SupportsWesternNumericIntegerPositive())
       
  2056 				{
       
  2057 				textToDisplay.Append(KLitWesternNumericIntegerPositive);
       
  2058 				textToDisplay.Append(KLitCommaSpace);
       
  2059 				deleteLastSeparator=ETrue;
       
  2060 				}
       
  2061 			if (iInputCapabilities.SupportsWesternNumericIntegerNegative())
       
  2062 				{
       
  2063 				textToDisplay.Append(KLitWesternNumericIntegerNegative);
       
  2064 				textToDisplay.Append(KLitCommaSpace);
       
  2065 				deleteLastSeparator=ETrue;
       
  2066 				}
       
  2067 			if (iInputCapabilities.SupportsWesternNumericReal())
       
  2068 				{
       
  2069 				textToDisplay.Append(KLitWesternNumericReal);
       
  2070 				textToDisplay.Append(KLitCommaSpace);
       
  2071 				deleteLastSeparator=ETrue;
       
  2072 				}
       
  2073 			if (iInputCapabilities.SupportsWesternAlphabetic())
       
  2074 				{
       
  2075 				textToDisplay.Append(KLitWesternAlphabetic);
       
  2076 				textToDisplay.Append(KLitCommaSpace);
       
  2077 				deleteLastSeparator=ETrue;
       
  2078 				}
       
  2079 			if (iInputCapabilities.SupportsJapaneseHiragana())
       
  2080 				{
       
  2081 				textToDisplay.Append(KLitJapaneseHiragana);
       
  2082 				textToDisplay.Append(KLitCommaSpace);
       
  2083 				deleteLastSeparator=ETrue;
       
  2084 				}
       
  2085 			if (iInputCapabilities.SupportsJapaneseKatakanaHalfWidth())
       
  2086 				{
       
  2087 				textToDisplay.Append(KLitJapaneseKatakanaHalfWidth);
       
  2088 				textToDisplay.Append(KLitCommaSpace);
       
  2089 				deleteLastSeparator=ETrue;
       
  2090 				}
       
  2091 			if (iInputCapabilities.SupportsJapaneseKatakanaFullWidth())
       
  2092 				{
       
  2093 				textToDisplay.Append(KLitJapaneseKatakanaFullWidth);
       
  2094 				textToDisplay.Append(KLitCommaSpace);
       
  2095 				deleteLastSeparator=ETrue;
       
  2096 				}
       
  2097 			if (iInputCapabilities.SupportsDialableCharacters())
       
  2098 				{
       
  2099 				textToDisplay.Append(KLitDialableCharacters);
       
  2100 				textToDisplay.Append(KLitCommaSpace);
       
  2101 				deleteLastSeparator=ETrue;
       
  2102 				}
       
  2103 			if (iInputCapabilities.SupportsSecretText())
       
  2104 				{
       
  2105 				textToDisplay.Append(KLitSecretText);
       
  2106 				textToDisplay.Append(KLitCommaSpace);
       
  2107 				deleteLastSeparator=ETrue;
       
  2108 				}
       
  2109 			if (iInputCapabilities.SupportsAllText())
       
  2110 				{
       
  2111 				textToDisplay.Append(KLitAllText);
       
  2112 				textToDisplay.Append(KLitCommaSpace);
       
  2113 				deleteLastSeparator=ETrue;
       
  2114 				}
       
  2115 			if (iInputCapabilities.SupportsNavigation())
       
  2116 				{
       
  2117 				textToDisplay.Append(KLitNavigation);
       
  2118 				textToDisplay.Append(KLitCommaSpace);
       
  2119 				deleteLastSeparator=ETrue;
       
  2120 				}
       
  2121 			const TCoeInputCapabilities::MCoeFepSpecificExtensions* const fepSpecificInputCapabilityExtensions=iInputCapabilities.FepSpecificExtensions(TUid::Uid(KTestFep4Uid));
       
  2122 			if (fepSpecificInputCapabilityExtensions!=NULL)
       
  2123 				{
       
  2124 				textToDisplay.Append(KLitExtensionsColonSpace);
       
  2125 				if (fepSpecificInputCapabilityExtensions->SupportsPhoneticAlphabet())
       
  2126 					{
       
  2127 					textToDisplay.Append(KLitPhoneticAlphabet);
       
  2128 					textToDisplay.Append(KLitCommaSpace);
       
  2129 					deleteLastSeparator=ETrue;
       
  2130 					}
       
  2131 				}
       
  2132 			if (deleteLastSeparator)
       
  2133 				{
       
  2134 				const TInt lengthToDelete=KLitCommaSpace().Length();
       
  2135 				textToDisplay.Delete(textToDisplay.Length()-lengthToDelete, lengthToDelete);
       
  2136 				}
       
  2137 			}
       
  2138 		textToDisplay.Append(KLitClosingSquareBracket);
       
  2139 		temp.iTl.iY=temp.iBr.iY;
       
  2140 		temp.iBr.iY=rectangle.iBr.iY;
       
  2141 		__ASSERT_DEBUG(temp.iBr.iY==temp.iTl.iY+statusFontHeightInPixels+EGapBelowBottomStatusLine, Panic(EPanicBadHeight));
       
  2142 		graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine);
       
  2143 		graphicsContext.DiscardFont();
       
  2144 		}
       
  2145 	}
       
  2146 
       
  2147 void CTstControl::DrawText(const TParam& aParam, const TLineInfo& aLineInfo, const TCharFormat& aFormat, const TDesC& aText, const TPoint& aTextOrigin, TInt aExtraPixels) const
       
  2148 	{
       
  2149 	MFormCustomDraw::DrawText(aParam, aLineInfo, aFormat, aText, aTextOrigin, aExtraPixels);
       
  2150 	// ?? draw the dotted underline whose phase starts at aParam.iTextLayoutTopLeft.iX
       
  2151 	}
       
  2152 
       
  2153 void CTstControl::GetFormatOfFepInlineText(TCharFormat& aFormat, TInt& aNumberOfCharactersWithSameFormat, TInt aPositionOfCharacter) const
       
  2154 	{
       
  2155 	const TInt lengthOfSelection=iSelectedCompositionText.Length();
       
  2156 	const TInt startOfSelectedInlineText=iSelectedCompositionText.LowerPos();
       
  2157 	const TInt endOfSelectedInlineText=iSelectedCompositionText.HigherPos();
       
  2158 	const MCoeFepAwareTextEditor& fepAwareTextEditor=*iInputCapabilities.FepAwareTextEditor();
       
  2159 	TCursorSelection cursorSelection;
       
  2160 	fepAwareTextEditor.GetCursorSelectionForFep(cursorSelection);
       
  2161 	TCharFormat formatBeforeInlineText;
       
  2162 	GetFormatAtDocumentPosition(formatBeforeInlineText, cursorSelection.LowerPos()-1, fepAwareTextEditor);
       
  2163 	TCharFormat formatAfterInlineText;
       
  2164 	GetFormatAtDocumentPosition(formatAfterInlineText, cursorSelection.HigherPos()+1, fepAwareTextEditor);
       
  2165 	aFormat=formatBeforeInlineText;
       
  2166 	if ((lengthOfSelection>0) && (aPositionOfCharacter>=startOfSelectedInlineText) && (aPositionOfCharacter<endOfSelectedInlineText))
       
  2167 		{
       
  2168 		aFormat.iFontPresentation.iTextColor=KRgbGreen;
       
  2169 		}
       
  2170 	else
       
  2171 		{
       
  2172 		aFormat.iFontPresentation.iTextColor=KRgbRed;
       
  2173 		}
       
  2174 	if ((formatBeforeInlineText.iFontPresentation.iUnderline!=EUnderlineOn) && (formatAfterInlineText.iFontPresentation.iUnderline!=EUnderlineOn))
       
  2175 		{
       
  2176 		aFormat.iFontPresentation.iUnderline=EUnderlineOn;
       
  2177 		}
       
  2178 	else if ((formatBeforeInlineText.iFontPresentation.iUnderline!=EUnderlineOff) && (formatAfterInlineText.iFontPresentation.iUnderline!=EUnderlineOff))
       
  2179 		{
       
  2180 		aFormat.iFontPresentation.iUnderline=EUnderlineOff;
       
  2181 		}
       
  2182 	else
       
  2183 		{
       
  2184 		aFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosSuperscript);
       
  2185 		}
       
  2186 	const TInt endOfRunOfCharactersOfSameFormat=((lengthOfSelection==0) || (aPositionOfCharacter>=endOfSelectedInlineText))?
       
  2187 													iBuffer.Length():
       
  2188 												(aPositionOfCharacter>=startOfSelectedInlineText)?
       
  2189 													endOfSelectedInlineText:
       
  2190 													startOfSelectedInlineText;
       
  2191 	aNumberOfCharactersWithSameFormat=endOfRunOfCharactersOfSameFormat-aPositionOfCharacter;
       
  2192 	}
       
  2193 
       
  2194 void CTstControl::HandlePointerEventInInlineTextL(TPointerEvent::TType aType, TUint, TInt aPositionInInlineText)
       
  2195 	{
       
  2196 	MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor();
       
  2197 	__ASSERT_DEBUG(fepAwareTextEditor!=NULL, Panic(EPanicNoFepAwareTextEditorAlthoughCurrentlyInlineEditing));
       
  2198 	const TCursorSelection oldSelectedCompositionText=iSelectedCompositionText;
       
  2199 	switch (aType)
       
  2200 		{
       
  2201 	case TPointerEvent::EButton1Down:
       
  2202 		iSelectedCompositionText.iAnchorPos=aPositionInInlineText;
       
  2203 		// fall through
       
  2204 	case TPointerEvent::EDrag:
       
  2205 		iSelectedCompositionText.iCursorPos=aPositionInInlineText;
       
  2206 		break;
       
  2207 #if defined(__GCC32__)
       
  2208 	default:
       
  2209 		break;
       
  2210 #endif
       
  2211 		}
       
  2212 	if ((iSelectedCompositionText.iCursorPos!=oldSelectedCompositionText.iCursorPos) || (iSelectedCompositionText.iAnchorPos!=oldSelectedCompositionText.iAnchorPos))
       
  2213 		{
       
  2214 		fepAwareTextEditor->UpdateFepInlineTextL(iBuffer, iSelectedCompositionText.iCursorPos);
       
  2215 		}
       
  2216 	}
       
  2217 
       
  2218 void CTstControl::ExecuteFunctionL()
       
  2219 	{
       
  2220 	InsertCompositionCharacterAndDrawNowL(iCharacterCode);
       
  2221 	}
       
  2222 
       
  2223 // CTstControl::CStateInformation
       
  2224 
       
  2225 CTstControl::CStateInformation* CTstControl::CStateInformation::NewLC(TInt aMeaninglessNumber)
       
  2226 	{
       
  2227 	CStateInformation* const stateInformation=new(ELeave) CStateInformation;
       
  2228 	CleanupStack::PushL(stateInformation);
       
  2229 	stateInformation->ConstructL(aMeaninglessNumber);
       
  2230 	return stateInformation;
       
  2231 	}
       
  2232 
       
  2233 CTstControl::CStateInformation::~CStateInformation()
       
  2234 	{
       
  2235 	delete iMeaninglessNumber;
       
  2236 	}
       
  2237 
       
  2238 CTstControl::CStateInformation::CStateInformation()
       
  2239 	:iMeaninglessNumber(NULL)
       
  2240 	{
       
  2241 	}
       
  2242 
       
  2243 void CTstControl::CStateInformation::ConstructL(TInt aMeaninglessNumber)
       
  2244 	{
       
  2245 	BaseConstructL();
       
  2246 	iMeaninglessNumber=new(ELeave) TInt(aMeaninglessNumber);
       
  2247 	}
       
  2248 
       
  2249 // CTstFep
       
  2250 
       
  2251 CTstFep::CTstFep(CCoeEnv& aConeEnvironment)
       
  2252 	:CCoeFep(aConeEnvironment)
       
  2253 	{
       
  2254 	}
       
  2255 
       
  2256 void CTstFep::ConstructL(const CCoeFepParameters& aFepParameters)
       
  2257 	{
       
  2258 	BaseConstructL(aFepParameters);
       
  2259 	iControl=CTstControl::NewL(*this);
       
  2260 	ReadAllAttributesL();
       
  2261 	iControl->ActivateL();
       
  2262 	}
       
  2263 
       
  2264 CTstFep::~CTstFep()
       
  2265 	{
       
  2266 	delete iControl;
       
  2267 	}
       
  2268 
       
  2269 void CTstFep::CancelTransaction()
       
  2270 	{
       
  2271 	iControl->CancelTransaction();
       
  2272 	}
       
  2273 
       
  2274 void CTstFep::IsOnHasChangedState()
       
  2275 	{
       
  2276 	iControl->IsOnHasChangedState();
       
  2277 	}
       
  2278 
       
  2279 void CTstFep::OfferKeyEventL(TEventResponse& aEventResponse, const TKeyEvent& aKeyEvent, TEventCode aEventCode)
       
  2280 	{
       
  2281 	// this function must correctly set aEventResponse *before* calling anything that can leave
       
  2282 	aEventResponse=EEventWasConsumed; // this assumes that CTstControl::OfferKeyEventL will not leave if it returns EKeyWasNotConsumed
       
  2283 	switch (iControl->OfferKeyEventL(aKeyEvent, aEventCode))
       
  2284 		{
       
  2285 	case EKeyWasNotConsumed:
       
  2286 		aEventResponse=EEventWasNotConsumed;
       
  2287 		break;
       
  2288 	case EKeyWasConsumed:
       
  2289 		aEventResponse=EEventWasConsumed;
       
  2290 		break;
       
  2291 #if defined(_DEBUG)
       
  2292 	default:
       
  2293 		Panic(EPanicBadKeyResponse);
       
  2294 		break;
       
  2295 #endif
       
  2296 		}
       
  2297 	}
       
  2298 
       
  2299 void CTstFep::OfferPointerEventL(TEventResponse& aEventResponse, const TPointerEvent& aPointerEvent, const CCoeControl* aWindowOwningControl)
       
  2300 	{
       
  2301 	iControl->OfferPointerEventL(aEventResponse, aPointerEvent, aWindowOwningControl);
       
  2302 	}
       
  2303 
       
  2304 void CTstFep::OfferPointerBufferReadyEventL(TEventResponse& aEventResponse, const CCoeControl*)
       
  2305 	{
       
  2306 	aEventResponse=EEventWasNotConsumed;
       
  2307 	}
       
  2308 
       
  2309 TInt CTstFep::NumberOfAttributes() const
       
  2310 	{
       
  2311 	return CTstControl::NumberOfAttributes();
       
  2312 	}
       
  2313 
       
  2314 TUid CTstFep::AttributeAtIndex(TInt aIndex) const
       
  2315 	{
       
  2316 	return CTstControl::AttributeAtIndex(aIndex);
       
  2317 	}
       
  2318 
       
  2319 void CTstFep::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const
       
  2320 	{
       
  2321 	iControl->WriteAttributeDataToStreamL(aAttributeUid, aStream);
       
  2322 	}
       
  2323 
       
  2324 void CTstFep::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream)
       
  2325 	{
       
  2326 	iControl->ReadAttributeDataFromStreamL(aAttributeUid, aStream);
       
  2327 	}
       
  2328 
       
  2329 void CTstFep::HandleGainingForeground()
       
  2330 	{
       
  2331 	iControl->HandleGainingForeground();
       
  2332 	}
       
  2333 
       
  2334 void CTstFep::HandleLosingForeground()
       
  2335 	{
       
  2336 	iControl->HandleLosingForeground();
       
  2337 	}
       
  2338 
       
  2339 void CTstFep::HandleChangeInFocus()
       
  2340 	{
       
  2341 	iControl->HandleChangeInFocus();
       
  2342 	}
       
  2343 
       
  2344 void CTstFep::HandleDestructionOfFocusedItem()
       
  2345 	{
       
  2346 	iControl->HandleDestructionOfFocusedItem();
       
  2347 	}
       
  2348 
       
  2349 // TTstResourceFileId
       
  2350 
       
  2351 #pragma warning(disable: 4355) // "'this' : used in base member initializer list"
       
  2352 
       
  2353 TTstResourceFileId::TTstResourceFileId(CCoeEnv& aConeEnvironment, TInt aResourceFileId)
       
  2354 	:TCleanupItem(UnloadResourceFile, this),
       
  2355 	 iConeEnvironment(aConeEnvironment),
       
  2356 	 iResourceFileId(aResourceFileId)
       
  2357 	{
       
  2358 	}
       
  2359 
       
  2360 #pragma warning(default: 4355)
       
  2361 
       
  2362 void TTstResourceFileId::UnloadResourceFile(TAny* aThis)
       
  2363 	{
       
  2364 	TTstResourceFileId& resourceFileId=*STATIC_CAST(TTstResourceFileId*, aThis);
       
  2365 	resourceFileId.iConeEnvironment.DeleteResourceFile(resourceFileId.iResourceFileId);
       
  2366 	}
       
  2367 
       
  2368 // CTstSettingsDialog
       
  2369 
       
  2370 CTstSettingsDialog::CTstSettingsDialog()
       
  2371 	:iInlineEditingEnabled(ETrue),
       
  2372 	 iInputMethod(0)
       
  2373 	{
       
  2374 	}
       
  2375 
       
  2376 TBool CTstSettingsDialog::OkToExitL(TInt aButtonId)
       
  2377 	{
       
  2378 	__ASSERT_ALWAYS(aButtonId==EEikBidOk, Panic(EPanicUnexpectedButtonId));
       
  2379 	switch (STATIC_CAST(CEikCheckBox*, Control(EControlIdInlineEditingEnabled))->State())
       
  2380 		{
       
  2381 	case CEikButtonBase::EClear:
       
  2382 		iInlineEditingEnabled=EFalse;
       
  2383 		break;
       
  2384 	case CEikButtonBase::ESet:
       
  2385 		iInlineEditingEnabled=ETrue;
       
  2386 		break;
       
  2387 	case CEikButtonBase::EIndeterminate:
       
  2388 #if defined(_DEBUG)
       
  2389 	default:
       
  2390 		Panic(EPanicBadCheckBoxState);
       
  2391 #endif
       
  2392 		break;
       
  2393 		}
       
  2394 	iInputMethod=STATIC_CAST(CEikChoiceListBase*, Control(EControlIdInputMethod))->CurrentItem();
       
  2395 	TFixedArray<TUid, 2> attributeUids;
       
  2396 	__ASSERT_DEBUG(NumberOfAttributes()==2, Panic(EPanicBadNumberOfAttributes));
       
  2397 	attributeUids[0].iUid=AttributeAtIndex(0).iUid;
       
  2398 	attributeUids[1].iUid=AttributeAtIndex(1).iUid;
       
  2399 	WriteAttributeDataAndBroadcastL(*iCoeEnv, attributeUids.Array());
       
  2400 	return ETrue;
       
  2401 	}
       
  2402 
       
  2403 void CTstSettingsDialog::PreLayoutDynInitL()
       
  2404 	{
       
  2405 	ReadAllAttributesL(*iCoeEnv);
       
  2406 	STATIC_CAST(CEikCheckBox*, Control(EControlIdInlineEditingEnabled))->SetState(iInlineEditingEnabled? CEikButtonBase::ESet: CEikButtonBase::EClear);
       
  2407 	STATIC_CAST(CEikChoiceListBase*, Control(EControlIdInputMethod))->SetCurrentItem(iInputMethod);
       
  2408 	}
       
  2409 
       
  2410 TInt CTstSettingsDialog::NumberOfAttributes() const
       
  2411 	{
       
  2412 	return CTstControl::NumberOfAttributes();
       
  2413 	}
       
  2414 
       
  2415 TUid CTstSettingsDialog::AttributeAtIndex(TInt aIndex) const
       
  2416 	{
       
  2417 	return CTstControl::AttributeAtIndex(aIndex);
       
  2418 	}
       
  2419 
       
  2420 void CTstSettingsDialog::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const
       
  2421 	{
       
  2422 	CTstControl::WriteAttributeDataToStreamL(aAttributeUid, aStream, iInlineEditingEnabled, iInputMethod);
       
  2423 	}
       
  2424 
       
  2425 void CTstSettingsDialog::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream)
       
  2426 	{
       
  2427 	CTstControl::ReadAttributeDataFromStreamL(aAttributeUid, aStream, iInlineEditingEnabled, iInputMethod);
       
  2428 	}
       
  2429 
       
  2430 CPinyinSelector::CPinyinSelector()
       
  2431 	{
       
  2432 	iPinyinTable = &pinyinTable;
       
  2433 	iPageSize = 6;
       
  2434 	iReset = ETrue;
       
  2435 	iCurrentPinyin = NULL;
       
  2436 	}
       
  2437 
       
  2438 TBool CPinyinSelector::SetPinyin(const TDesC *aCurrentPinyin, TInt aIndexInCurrentPinyin)
       
  2439 	{
       
  2440 	TInt index;
       
  2441 	TBool found = EFalse;
       
  2442 	iReset = ETrue;
       
  2443 	for (index=0; index<iPinyinTable->iPinyinCharacterPairCount; index++)
       
  2444 		{
       
  2445 //		if (aCurrentPinyin->Compare(iPinyinTable->iPairArray[index].iPinYin) == 0)
       
  2446 		TPtrC py(iPinyinTable->iPairArray[index].iPinYin, iPinyinTable->iPairArray[index].iPinYinLength);
       
  2447 		if (aCurrentPinyin->Compare(py) == 0)
       
  2448 			{
       
  2449 			iCurrentPinyin = &(iPinyinTable->iPairArray[index]);
       
  2450 			iIndexInCurrentPinyin = aIndexInCurrentPinyin;
       
  2451 			found = ETrue;
       
  2452 			iReset = EFalse;
       
  2453 			return found;
       
  2454 			}
       
  2455 		}
       
  2456 	if (!found)
       
  2457 		{
       
  2458 #if defined(_DEBUG)
       
  2459 //		Panic(EPanicBadIndex1);
       
  2460 #endif
       
  2461 		return found;
       
  2462 		}
       
  2463 	return found;
       
  2464 	}
       
  2465 
       
  2466 TInt CPinyinSelector::PreviousCharacter()
       
  2467 	{
       
  2468 	if (iReset)
       
  2469 		return EInvalidChar;
       
  2470 	if (iIndexInCurrentPinyin > 0)
       
  2471 		{
       
  2472 		iIndexInCurrentPinyin--;
       
  2473 		}
       
  2474 	if (iIndexInCurrentPinyin < 0)
       
  2475 		iIndexInCurrentPinyin = 0;
       
  2476 	if (iIndexInCurrentPinyin > iCurrentPinyin->iCharacterCount - 1)
       
  2477 		iIndexInCurrentPinyin = iCurrentPinyin->iCharacterCount - 1;
       
  2478 	return iCurrentPinyin->iCharacterArray[iIndexInCurrentPinyin];
       
  2479 	}
       
  2480 
       
  2481 TInt CPinyinSelector::NextCharacter()
       
  2482 	{
       
  2483 	if (iReset)
       
  2484 		return EInvalidChar;
       
  2485 	if (iIndexInCurrentPinyin < iCurrentPinyin->iCharacterCount - 1)
       
  2486 		{
       
  2487 		iIndexInCurrentPinyin++;
       
  2488 		}
       
  2489 	if (iIndexInCurrentPinyin < 0)
       
  2490 		iIndexInCurrentPinyin = 0;
       
  2491 	if (iIndexInCurrentPinyin > iCurrentPinyin->iCharacterCount - 1)
       
  2492 		iIndexInCurrentPinyin = iCurrentPinyin->iCharacterCount - 1;
       
  2493 	return iCurrentPinyin->iCharacterArray[iIndexInCurrentPinyin];
       
  2494 	}
       
  2495 
       
  2496 void CPinyinSelector::SetPageSize(TInt nPageSize)
       
  2497 	{
       
  2498 	iPageSize = nPageSize;
       
  2499 	if (iPageSize < 1)
       
  2500 		iPageSize = 1;
       
  2501 	if (iPageSize > 8)
       
  2502 		iPageSize = 8;
       
  2503 	}
       
  2504 
       
  2505 TInt CPinyinSelector::NextPage()
       
  2506 	{
       
  2507 	if (iReset)
       
  2508 		return EInvalidChar;
       
  2509 	
       
  2510 	TInt firstIndexInThisPage = ((iIndexInCurrentPinyin+iPageSize-1) / iPageSize) * iPageSize;
       
  2511 	if (firstIndexInThisPage + iPageSize < iCurrentPinyin->iCharacterCount)
       
  2512 		{
       
  2513 		iIndexInCurrentPinyin = firstIndexInThisPage + iPageSize;
       
  2514 		}
       
  2515 	if (iIndexInCurrentPinyin < 0)
       
  2516 		iIndexInCurrentPinyin = 0;
       
  2517 	if (iIndexInCurrentPinyin > iCurrentPinyin->iCharacterCount - 1)
       
  2518 		iIndexInCurrentPinyin = iCurrentPinyin->iCharacterCount - 1;
       
  2519 	return iCurrentPinyin->iCharacterArray[iIndexInCurrentPinyin];
       
  2520 	}
       
  2521 
       
  2522 TInt CPinyinSelector::PreviousPage()
       
  2523 	{
       
  2524 	if (iReset)
       
  2525 		return EInvalidChar;
       
  2526 	
       
  2527 	TInt firstIndexInThisPage = ((iIndexInCurrentPinyin+iPageSize-1) / iPageSize) * iPageSize;
       
  2528 	if (firstIndexInThisPage - iPageSize >= 0)
       
  2529 		{
       
  2530 		iIndexInCurrentPinyin = firstIndexInThisPage - iPageSize;
       
  2531 		}
       
  2532 	if (iIndexInCurrentPinyin < 0)
       
  2533 		iIndexInCurrentPinyin = 0;
       
  2534 	if (iIndexInCurrentPinyin > iCurrentPinyin->iCharacterCount - 1)
       
  2535 		iIndexInCurrentPinyin = iCurrentPinyin->iCharacterCount - 1;
       
  2536 	return iCurrentPinyin->iCharacterArray[iIndexInCurrentPinyin];
       
  2537 	}
       
  2538 
       
  2539 TInt CPinyinSelector::CharacterInCurrentPage(TInt aIndex)
       
  2540 	{
       
  2541 	if (aIndex < 0)
       
  2542 		aIndex = 0;
       
  2543 	
       
  2544 	TInt firstIndexInThisPage = ((iIndexInCurrentPinyin+iPageSize-1) / iPageSize) * iPageSize;
       
  2545 	aIndex += firstIndexInThisPage;
       
  2546 	if (aIndex > iCurrentPinyin->iCharacterCount - 1)
       
  2547 		aIndex = iCurrentPinyin->iCharacterCount - 1;
       
  2548 	
       
  2549 	return iCurrentPinyin->iCharacterArray[aIndex];
       
  2550 	}
       
  2551 
       
  2552 void CPinyinSelector::GetPageDescriptor(TBuf<200> *page) const
       
  2553 	{
       
  2554 	page->Zero();
       
  2555 #if 0
       
  2556 	// for debug
       
  2557 	_LIT(KTemp, "\x5DEE");
       
  2558 	page->Append(KTemp);
       
  2559 #endif
       
  2560 	if (iReset || iCurrentPinyin == NULL)
       
  2561 		return ;
       
  2562 
       
  2563 	TInt firstIndexInThisPage = ((iIndexInCurrentPinyin+iPageSize-1) / iPageSize) * iPageSize;
       
  2564 	TInt index = firstIndexInThisPage;
       
  2565 	while (index < firstIndexInThisPage+iPageSize && index < iCurrentPinyin->iCharacterCount)
       
  2566 		{
       
  2567 		_LIT(KFormat, "%d%c");
       
  2568 		_LIT(KOneSpace, " ");
       
  2569 		
       
  2570 		if (index != firstIndexInThisPage)
       
  2571 			page->Append(KOneSpace);
       
  2572 		TInt theChar = iCurrentPinyin->iCharacterArray[index];
       
  2573 		TBuf<200> temp;
       
  2574 		if (theChar < 0x10000)
       
  2575 			{
       
  2576 			temp.Format(KFormat, index-firstIndexInThisPage+1, theChar);
       
  2577 			}
       
  2578 		else
       
  2579 			{
       
  2580 			temp.Format(KFormat, index-firstIndexInThisPage+1, L' ');
       
  2581 			}
       
  2582 		page->Append(temp);
       
  2583 		index++;
       
  2584 		}
       
  2585 	}
       
  2586 
       
  2587 TBool CPinyinSelector::IsValidPinyinChar(TInt aChar)
       
  2588 	{
       
  2589 	TBool b = EFalse;
       
  2590 	if ('a' <= aChar && aChar <= 'z')
       
  2591 		b = ETrue;
       
  2592 	else if ('A' <= aChar && aChar <= 'Z')
       
  2593 		b = ETrue;
       
  2594 	return b;
       
  2595 	}
       
  2596 
       
  2597 void CPinyinSelector::Reset()
       
  2598 	{
       
  2599 	iReset = ETrue;
       
  2600 	}
       
  2601 
       
  2602 TBool CPinyinSelector::IsReseted()
       
  2603 	{
       
  2604 	return iReset;
       
  2605 	}