sl@0: /* sl@0: * Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: //#include "TCustomWrap.h" sl@0: #include "TGraphicsContext.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "tinlinetext.h" sl@0: sl@0: namespace LocalToTInlineText sl@0: { sl@0: sl@0: _LIT(KTInlineText, "TInlineText"); sl@0: const TInt KDisplayWidthWide = 202; sl@0: const TInt KDisplayWidthThin = 102; sl@0: const TInt KDisplayHeight = 100; sl@0: const TInt KPictureCharacter = 0xFFFC; sl@0: sl@0: CTInLineTextStep* TestStep = NULL; sl@0: #define TESTPOINT(p) TestStep->testpoint(p,(TText8*)__FILE__,__LINE__) sl@0: #define TESTPRINT(p) TestStep->print(p,(TText8*)__FILE__,__LINE__) sl@0: sl@0: sl@0: enum TInlineTextPanic { EAccessOutsideText = 1 }; sl@0: void Panic(TInlineTextPanic) sl@0: { sl@0: User::Panic(_L("TInlineText"), EAccessOutsideText); sl@0: } sl@0: sl@0: class CPinkSquare : public CPicture sl@0: { sl@0: public: sl@0: // Size of square in twips. sl@0: // 600 is 15 pixels using the standard test graphics device at sl@0: // its default resolution. sl@0: enum { KWidth = 600, KHeight = 600 }; sl@0: CPinkSquare() sl@0: {} sl@0: void Draw(CGraphicsContext& aGc, const TPoint& aTopLeft, const TRect& aClipRect, MGraphicsDeviceMap* aMap) const sl@0: { sl@0: // This picture is a magenta square sl@0: TPoint size(KWidth, KHeight); sl@0: if (aMap) sl@0: size = aMap->TwipsToPixels(size); sl@0: TRect rect(aTopLeft, aTopLeft + size); sl@0: aGc.SetClippingRect(aClipRect); sl@0: aGc.SetDrawMode(CGraphicsContext::EDrawModePEN); sl@0: aGc.SetPenColor(KRgbMagenta); sl@0: aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: aGc.SetBrushColor(KRgbMagenta); sl@0: aGc.DrawRect(rect); sl@0: } sl@0: void ExternalizeL(RWriteStream&) const sl@0: {} sl@0: void GetOriginalSizeInTwips(TSize& a) const sl@0: { sl@0: a.iWidth = CPinkSquare::KWidth; sl@0: a.iHeight = CPinkSquare::KHeight; sl@0: } sl@0: }; sl@0: sl@0: _LIT(KEnd, "\x2029"); sl@0: class TDocModel : public MLayDoc sl@0: { sl@0: public: sl@0: TDocModel(const TDesC& aDes) sl@0: : iDes(&aDes), iParagraphFormat(0) sl@0: {} sl@0: void SetParagraphFormat(CParaFormat* a) sl@0: { sl@0: iParagraphFormat = a; sl@0: } sl@0: // From MLayDoc sl@0: TInt LdDocumentLength() const sl@0: { return iDes->Length(); } sl@0: TInt LdToParagraphStart(TInt& a) const sl@0: { sl@0: TInt curr = a; sl@0: if (a < LdDocumentLength()) sl@0: { sl@0: a = iDes->Left(a).LocateReverse(0x2029); sl@0: a = a < 0? 0 : a + 1; sl@0: } sl@0: return curr - a; sl@0: } sl@0: void GetParagraphFormatL(CParaFormat* aFormat, TInt) const sl@0: { sl@0: if (iParagraphFormat) sl@0: { sl@0: aFormat->CopyL(*iParagraphFormat); sl@0: return; sl@0: } sl@0: aFormat->Reset(); sl@0: TTabStop tabStop; sl@0: tabStop.iTwipsPosition = 1000; sl@0: tabStop.iType = TTabStop::ELeftTab; sl@0: aFormat->StoreTabL(tabStop); sl@0: } sl@0: void GetChars(TPtrC& aView,TCharFormat& aFormat, TInt aStartPos)const sl@0: { sl@0: __ASSERT_ALWAYS(aStartPos <= LdDocumentLength(), Panic(EAccessOutsideText)); sl@0: __ASSERT_ALWAYS(aStartPos >= 0, Panic(EAccessOutsideText)); sl@0: sl@0: TCharFormat cf; sl@0: aFormat = cf; sl@0: if (aStartPos == LdDocumentLength()) sl@0: aView.Set(KEnd); sl@0: else sl@0: aView.Set(iDes->Mid(aStartPos)); sl@0: } sl@0: TInt GetPictureSizeInTwips(TSize& aSize, TInt aPos) const sl@0: { sl@0: if ((*iDes)[aPos] != KPictureCharacter) sl@0: return KErrNotFound; sl@0: aSize.iWidth = CPinkSquare::KWidth; sl@0: aSize.iHeight = CPinkSquare::KHeight; sl@0: return KErrNone; sl@0: } sl@0: CPicture* PictureHandleL(TInt aPos, TForcePictureLoad) const sl@0: { sl@0: if ((*iDes)[aPos] != KPictureCharacter) sl@0: return 0; sl@0: return new(ELeave) CPinkSquare; sl@0: } sl@0: TBool EnquirePageBreak(TInt aPos, TInt aLength)const sl@0: { sl@0: return iDes->Mid(aPos, aLength).Locate(0x000C) < 0? sl@0: EFalse : ETrue; sl@0: } sl@0: TBool SelectParagraphLabel(TInt) sl@0: { return EFalse; } sl@0: void CancelSelectLabel() sl@0: {} sl@0: private: sl@0: const TDesC* iDes; sl@0: CParaFormat* iParagraphFormat; sl@0: }; sl@0: } sl@0: using namespace LocalToTInlineText; sl@0: sl@0: class CTestTextView // slightly naughty sl@0: { sl@0: public: sl@0: static void SetContextForFlickerFreeRedraw(CTextView* aView, CBitmapContext* aContext) sl@0: { sl@0: aView->iOffScreenContext = aContext; sl@0: } sl@0: }; sl@0: sl@0: // Utility functions to show contents of test data using test.Printf sl@0: sl@0: _LIT(KAddressMarker, "> "); sl@0: _LIT(KSpace, " "); sl@0: _LIT(KLength, ", Length of Data = %d 16-bit words\r\n"); sl@0: _LIT(KSpaces, " "); sl@0: _LIT(KPeriod, "."); sl@0: _LIT(KSingleString, "%S\r\n"); sl@0: //_LIT(KDoubleString, "%s <%s>\r\n"); sl@0: //_LIT(KLinefeed, "\r\n"); sl@0: sl@0: void PrintTestData (const TDesC& aTitle , const TDesC16& aData) sl@0: { sl@0: sl@0: TInt i; sl@0: TInt j; sl@0: TInt end; sl@0: sl@0: TInt length = aData.Length(); sl@0: sl@0: TBuf<80> buffer; sl@0: sl@0: buffer.Zero(); sl@0: buffer.Append(aTitle); sl@0: buffer.Append(KLength); sl@0: sl@0: TBuf<256> buf; sl@0: buf.AppendFormat(buffer, length); sl@0: TESTPRINT(buf); sl@0: sl@0: for (i = 0 ; i < length ; i += 8) sl@0: { sl@0: buffer.Zero(); sl@0: buffer.AppendNumFixedWidth(i, EHex, 8); sl@0: buffer += KAddressMarker; sl@0: sl@0: end = ((length-i) >= 8) ? i+8 : length; sl@0: sl@0: for (j = i ; j < end ; ++j) sl@0: { sl@0: buffer.AppendNumFixedWidth(aData[j], EHex, 4); sl@0: buffer += KSpace; sl@0: } sl@0: buffer += TPtrC(KSpaces().Ptr(), ((8-(j-i))*5)+4); sl@0: sl@0: for (j = i ; j < end ; ++j) sl@0: { sl@0: if (aData[j] >= 32) sl@0: { sl@0: buffer.Append(aData[j]); sl@0: } sl@0: else sl@0: { sl@0: buffer += KPeriod; sl@0: } sl@0: } sl@0: buffer.ZeroTerminate(); sl@0: buf.Zero(); sl@0: buf.AppendFormat(KSingleString,buffer.Ptr()); sl@0: TESTPRINT(buf); sl@0: } sl@0: sl@0: } sl@0: sl@0: void PrintTestData(const TDesC& aTitle, const TText16* aDataBuffer, const TInt aSize) sl@0: { sl@0: PrintTestData(aTitle, TPtrC16(aDataBuffer, aSize)); sl@0: } sl@0: sl@0: class CTestInlineTextSource : public CBase, public MTmInlineTextSource sl@0: { sl@0: public: sl@0: static CTestInlineTextSource* NewL(TPtrC aText, TInt aNumChar); sl@0: ~CTestInlineTextSource(); sl@0: sl@0: public: // From MTmInlineTextSource sl@0: sl@0: /** sl@0: Reports the next position into which inline text should be inserted sl@0: @param aFrom sl@0: The document position and character edge to start from. sl@0: @param aMaxLength sl@0: The maximum length within which to report inline text. sl@0: It means that inline text at position X should be reported if sl@0: aFrom <= X && X < aFrom + aMaxLength. sl@0: Also report trailing inline text at position aFrom + aMaxLength sl@0: because it is really attached to the preceding character. sl@0: Always report only the first inline text position >= aFrom. sl@0: @param aNext sl@0: On exit the position of the next bit of inline text to be inserted. sl@0: N.B. The position of trailing text following position N and the sl@0: position of leading text preceding position N+1 are both sl@0: considered to be N+1 - and the trailing text comes first so if sl@0: aFrom specifies a leading edge do not report trailing edge sl@0: inline text unless its position is greater than aFrom. sl@0: A panic EBadReturnValue will result otherwise. sl@0: @return sl@0: KErrNone if a position is found within the specified range, sl@0: KErrNotFound otherwise. sl@0: @post sl@0: if KErrNone returned then aFrom <= aNext sl@0: && GetInlineText(aNext).Length() != 0 sl@0: && (GetInlineText(X).Length() == 0 for all sl@0: TTmDocPos X such that aFrom < X && X < aNext) sl@0: else if KErrNotFound returned sl@0: GetInlineText(X).Length() == 0 for all sl@0: TTmDocPos X such that aFrom <= X && X < aFrom + aMaxLength sl@0: */ sl@0: virtual TInt GetNextInlineTextPosition(const TTmDocPos& aFrom, TInt aMaxLength, TTmDocPos& aNext); sl@0: sl@0: /** sl@0: Gets a view of the text to be inserted at aAt. sl@0: @param aAt sl@0: Document position, including character edge, being queried. sl@0: @return sl@0: Any inline text that should be attached to the specified character edge at aAt. sl@0: */ sl@0: virtual TPtrC GetInlineText(const TTmDocPos& aAt); sl@0: sl@0: private: sl@0: CTestInlineTextSource(); sl@0: void Construct(TPtrC aText, TInt aNumChar); sl@0: TPtrC iNullText; sl@0: TPtrC iText; sl@0: TInt iNumChar; sl@0: }; sl@0: sl@0: CTestInlineTextSource::CTestInlineTextSource() sl@0: { sl@0: } sl@0: sl@0: CTestInlineTextSource* CTestInlineTextSource::NewL(TPtrC aText, TInt aNumChar) sl@0: { sl@0: CTestInlineTextSource* self= new(ELeave) CTestInlineTextSource(); sl@0: self->Construct(aText, aNumChar); sl@0: return self; sl@0: } sl@0: sl@0: CTestInlineTextSource::~CTestInlineTextSource() sl@0: { sl@0: } sl@0: sl@0: void CTestInlineTextSource::Construct(TPtrC aText, TInt aNumChar) sl@0: { sl@0: iText.Set(aText); sl@0: iNumChar = aNumChar; sl@0: } sl@0: sl@0: // This takes two inputs, each of which is either a real position, sl@0: // greater than or equal to 0, or KErrNotFound. If both are real sl@0: // positions then it should return the lower. If one is a real position sl@0: // then it should be returned. If neither are a real position then sl@0: // KErrNone is returned. It is all done with pointers to TInts so that sl@0: // when I get the result I can tell which one it is. sl@0: TInt* CustomMin(TInt* aPtrPos1, TInt* aPtrPos2) sl@0: { sl@0: if (*aPtrPos2 == KErrNotFound) sl@0: return aPtrPos1; sl@0: if (*aPtrPos1 == KErrNotFound) sl@0: return aPtrPos2; sl@0: if (*aPtrPos1 <= *aPtrPos2) sl@0: return aPtrPos1; sl@0: else sl@0: return aPtrPos2; sl@0: } sl@0: sl@0: TInt CTestInlineTextSource::GetNextInlineTextPosition(const TTmDocPos& aFrom, TInt aMaxLength, TTmDocPos& aNext) sl@0: { sl@0: if (iNumChar == 0) sl@0: return KErrNotFound; sl@0: _LIT(KSS1, "A"); sl@0: _LIT(KSS2, "B"); sl@0: _LIT(KSS3, "C"); sl@0: _LIT(KSS4, "\x05c0");//Hebrew character to test right-to-left text sl@0: TInt from = aFrom.iPos; sl@0: TInt from2 = from; sl@0: if ((from > 0) && (!aFrom.iLeadingEdge)) sl@0: from2--; // adjustment takes care of not returning trailing edge if at start pos sl@0: TInt pos1 = iText.Mid(from).Find(KSS1); sl@0: TInt pos2 = iText.Mid(from2).Find(KSS2); sl@0: TInt pos3 = iText.Mid(from).Find(KSS3); sl@0: TInt pos4 = iText.Mid(from2).Find(KSS3); sl@0: TInt pos5 = iText.Mid(from2).Find(KSS4); sl@0: if (pos1 >= 0 ) // adjustments so we compare like for like sl@0: pos1 += from - from2; sl@0: if (pos3 >= 0 ) sl@0: pos3 += from - from2; sl@0: // get the smallest real position, if any sl@0: TInt* ptrPos = CustomMin(CustomMin(&pos1, &pos3), CustomMin(CustomMin(&pos2, &pos4),&pos5)); sl@0: if (pos1 > 0 ) // now adjust back sl@0: pos1 -= from - from2; sl@0: if (pos3 > 0 ) sl@0: pos3 -= from - from2; sl@0: if (*ptrPos == KErrNotFound) sl@0: return KErrNotFound; sl@0: if ((ptrPos == &pos1) || (ptrPos == &pos3)) sl@0: { // it was an A or C with leading text sl@0: aNext.iPos = *ptrPos + from; sl@0: aNext.iLeadingEdge = ETrue; sl@0: } sl@0: else if ((ptrPos == &pos2) || (ptrPos == &pos4)) sl@0: { // it was an B oD with trailing text sl@0: aNext.iPos = *ptrPos + from2 + 1; sl@0: aNext.iLeadingEdge = EFalse; sl@0: } sl@0: else if (ptrPos == &pos5) sl@0: { // it was an Hebrew char with trailing text sl@0: aNext.iPos = *ptrPos + from2 + 1; sl@0: aNext.iLeadingEdge = EFalse; sl@0: } sl@0: else sl@0: { sl@0: // something has gone horribly wrong sl@0: return KErrNotFound; sl@0: } sl@0: if (aNext.iPos - aFrom.iPos > aMaxLength + (aNext.iLeadingEdge ? 0 : 1)) sl@0: return KErrNotFound; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TPtrC CTestInlineTextSource::GetInlineText(const TTmDocPos& aAt) sl@0: { sl@0: if (iNumChar == 0) sl@0: return iNullText; sl@0: if ((aAt.iPos == 0) && (!aAt.iLeadingEdge)) sl@0: return iNullText; sl@0: _LIT(KSS1, "A"); sl@0: _LIT(KSS2, "B"); sl@0: _LIT(KSS3, "C"); sl@0: _LIT(KSS4, "\x05c0");//Hebrew character to test right-to-left text sl@0: TInt at = aAt.iPos; sl@0: TInt at2 = at; sl@0: if ((at2 > 0) && (!aAt.iLeadingEdge)) sl@0: at2--; // adjustment takes care of not returning trailing edge if at start pos sl@0: sl@0: TInt pos1 = iText.Mid(at).Find(KSS1); sl@0: TInt pos2 = iText.Mid(at2).Find(KSS2); sl@0: TInt pos3 = iText.Mid(at).Find(KSS3); sl@0: TInt pos4 = iText.Mid(at2).Find(KSS3); sl@0: TInt pos5 = iText.Mid(at2).Find(KSS4); sl@0: if (pos1 == 0) sl@0: { sl@0: pos1 += at; sl@0: if ((pos1 == aAt.iPos) && aAt.iLeadingEdge) sl@0: { sl@0: TPtrC tPtrC; sl@0: if (iNumChar == 1) sl@0: { sl@0: _LIT(KIS11, "a"); sl@0: tPtrC.Set(KIS11); sl@0: } sl@0: else if (iNumChar == 2) sl@0: { sl@0: _LIT(KIS12, "aa"); sl@0: tPtrC.Set(KIS12); sl@0: } sl@0: return tPtrC; sl@0: } sl@0: } sl@0: if (pos2 == 0) sl@0: { sl@0: pos2 += at2; sl@0: if ((pos2 + 1 == aAt.iPos) && !aAt.iLeadingEdge) sl@0: { sl@0: TPtrC tPtrC; sl@0: if (iNumChar == 1) sl@0: { sl@0: _LIT(KIS21, "b"); sl@0: tPtrC.Set(KIS21); sl@0: } sl@0: else if (iNumChar == 2) sl@0: { sl@0: _LIT(KIS22, "bb"); sl@0: tPtrC.Set(KIS22); sl@0: } sl@0: return tPtrC; sl@0: } sl@0: } sl@0: if ((pos3 == 0) || (pos4 == 0)) sl@0: { sl@0: if (((pos3 + at == aAt.iPos) && aAt.iLeadingEdge) || ((pos4 + at2 + 1 == aAt.iPos) && !aAt.iLeadingEdge)) sl@0: { sl@0: TPtrC tPtrC; sl@0: if (iNumChar == 1) sl@0: { sl@0: _LIT(KIS31, "c"); sl@0: tPtrC.Set(KIS31); sl@0: } sl@0: else if (iNumChar == 2) sl@0: { sl@0: _LIT(KIS32, "cc"); sl@0: tPtrC.Set(KIS32); sl@0: } sl@0: return tPtrC; sl@0: } sl@0: } sl@0: if (pos5 == 0) sl@0: { sl@0: pos5 += at2; sl@0: if ((pos5 + 1 == aAt.iPos) && !aAt.iLeadingEdge) sl@0: { sl@0: TPtrC tPtrC; sl@0: if (iNumChar == 1) sl@0: { sl@0: _LIT(KIS41, "\05be"); sl@0: tPtrC.Set(KIS41); sl@0: } sl@0: else if (iNumChar == 2) sl@0: { sl@0: _LIT(KIS42, "\05be\05be"); sl@0: tPtrC.Set(KIS42); sl@0: } sl@0: return tPtrC; sl@0: } sl@0: } sl@0: return iNullText; sl@0: } sl@0: sl@0: class CTestFormExtendedInterfaceProvider: public CBase, public MFormCustomInterfaceProvider sl@0: { sl@0: public: sl@0: static CTestFormExtendedInterfaceProvider* NewL(TPtrC aText, TInt aNumChar); sl@0: ~CTestFormExtendedInterfaceProvider(); sl@0: TAny* GetExtendedInterface(const TUid& aInterfaceId); sl@0: sl@0: private: sl@0: CTestFormExtendedInterfaceProvider(); sl@0: void ConstructL(TPtrC aText, TInt aNumChar); sl@0: sl@0: private: sl@0: CTestInlineTextSource* iTestInlineTextSource; // Owned sl@0: }; sl@0: sl@0: sl@0: CTestFormExtendedInterfaceProvider::CTestFormExtendedInterfaceProvider() sl@0: { sl@0: } sl@0: sl@0: CTestFormExtendedInterfaceProvider* CTestFormExtendedInterfaceProvider::NewL(TPtrC aText, TInt aNumChar) sl@0: { sl@0: CTestFormExtendedInterfaceProvider* self= new(ELeave) CTestFormExtendedInterfaceProvider(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aText, aNumChar); sl@0: CleanupStack::Pop(); // self sl@0: return self; sl@0: } sl@0: sl@0: CTestFormExtendedInterfaceProvider::~CTestFormExtendedInterfaceProvider() sl@0: { sl@0: delete iTestInlineTextSource; sl@0: } sl@0: sl@0: void CTestFormExtendedInterfaceProvider::ConstructL(TPtrC aText, TInt aNumChar) sl@0: { sl@0: iTestInlineTextSource = CTestInlineTextSource::NewL(aText, aNumChar); sl@0: } sl@0: sl@0: TAny* CTestFormExtendedInterfaceProvider::GetExtendedInterface( const TUid& aInterfaceId ) sl@0: { sl@0: if (aInterfaceId == KInlineTextApiExtensionUid) sl@0: { sl@0: return static_cast(iTestInlineTextSource); sl@0: } sl@0: else sl@0: { sl@0: return NULL; sl@0: } sl@0: } sl@0: sl@0: // When referring to test cases the following shorthand is used: sl@0: // P Primary text that has inline text (leading and/or trailing) attached sl@0: // to it sl@0: // L Leading inline text attached to primary text sl@0: // T Trailing inline text attached to primary text sl@0: // X Secondary text that precedes primary text sl@0: // Y Secondary text that follows primary text sl@0: // S A special case of P where the primary text is a single character sl@0: // which has both leading and trailing inline text attached to it sl@0: // sl@0: // So, for example, X L-P will indicate some normal secondary text, sl@0: // followed by a , followed by some primary text which will get sl@0: // leading text added to the start of it. sl@0: // sl@0: // When defining a test string the following are significant characters: sl@0: // A An 'A' will get zero or more 'a's of leading text attached to it sl@0: // B A 'B' will get zero or more 'b's of trailing text attached to it sl@0: // C A 'C' will get zero or more 'c's of both leading and trailing text sl@0: // attached to it sl@0: // sl@0: // All other characters are used normally. sl@0: // N.B. Spaces have significance as potential line-breaking points. sl@0: // sl@0: // So the example X L-P could be implemented as "ij Axyz". The 'A' sl@0: // indicating that leading inline text should be attatched to it. sl@0: // sl@0: // All test are carried out 3 times, once with inline text set to add zero sl@0: // characters for each inline text (i.e. switched off), once with inline sl@0: // text set to add one character for each inline text and once with inline sl@0: // text set to add two characters for each inline text. sl@0: // sl@0: // All tests use a special test graphics device and test graphics context sl@0: // to enable us to catch the output and use a special "pseudo" test font sl@0: // where all characters are exactly 10 pixels wide and 10 pixels high (to sl@0: // make the calculations easier). sl@0: // sl@0: // General combination tests sl@0: // sl@0: // These are simple tests, which would take a single line of input on the sl@0: // display and produce a single line of output on the display (if we sl@0: // weren't using a special CTestGraphicsContext to catch the output). sl@0: // These tests check that, without the complications of line-breaking, sl@0: // inline text is inserted where we expect it to be. This is why a display sl@0: // that is capable of taking 20 chars on a line is used for these tests. sl@0: // sl@0: // Future extensions: sl@0: // These tests could be extended to do similar tests using Right-to-Left sl@0: // (RtoL) text. This would require the inline text mechanism to be sl@0: // extended to also use RtoL trigger characters (and inserts). The sl@0: // expected results would need to take account of the fact that the output sl@0: // would be in display order rather than buffer order. sl@0: // sl@0: // Specific tests sl@0: // sl@0: // These tests check specific cases that involve line-breaking. They sl@0: // produce more than one line of output, apart from some (not all) cases sl@0: // when inline text is switched off. To force the line-breaking these sl@0: // tests use a display that is obly capable of taking 10 chars on a line sl@0: // is used. Detailed info for each test is given in comments in the test sl@0: // data. sl@0: // sl@0: // Future extensions: sl@0: // These tests could be extended to check the behaviour of truncation and sl@0: // the insertion of an ellipsis. These tests could also be extended to sl@0: // include some RtoL examples. sl@0: sl@0: static const TInt KTestCases = 18; sl@0: static const TInt KInlineTextOptions = 3; sl@0: static const TInt KVariants = 6; sl@0: sl@0: static const TPtrC KTestStrings[KTestCases][KInlineTextOptions][KVariants] = sl@0: { // Start of General Combination tests sl@0: { // Test L-P sl@0: { sl@0: _S("Axyz"), sl@0: _S("Axyz"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("Axyz"), sl@0: _S("a"), sl@0: _S("Axyz"), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("Axyz"), sl@0: _S("aa"), sl@0: _S("Axyz"), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X L-P sl@0: { sl@0: _S("ij Axyz"), sl@0: _S("ij Axyz"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij Axyz"), sl@0: _S("ij "), sl@0: _S("a"), sl@0: _S("Axyz"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij Axyz"), sl@0: _S("ij "), sl@0: _S("aa"), sl@0: _S("Axyz"), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test P-T sl@0: { sl@0: _S("xyzB"), sl@0: _S("xyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("xyzB"), sl@0: _S("xyzB"), sl@0: _S("b"), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("xyzB"), sl@0: _S("xyzB"), sl@0: _S("bb"), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test P-T Y sl@0: { sl@0: _S("xyzB pq"), sl@0: _S("xyzB pq"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("xyzB pq"), sl@0: _S("xyzB"), sl@0: _S("b"), sl@0: _S(" pq"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("xyzB pq"), sl@0: _S("xyzB"), sl@0: _S("bb"), sl@0: _S(" pq"), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test L-P-T sl@0: { sl@0: _S("AxyzB"), sl@0: _S("AxyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("AxyzB"), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("AxyzB"), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb"), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test L-C-T sl@0: { sl@0: _S("C"), sl@0: _S("C"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("C"), sl@0: _S("c"), sl@0: _S("C"), sl@0: _S("c"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("C"), sl@0: _S("cc"), sl@0: _S("C"), sl@0: _S("cc"), sl@0: _S(""), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X L-P-T sl@0: { sl@0: _S("ij AxyzB"), sl@0: _S("ij AxyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij AxyzB"), sl@0: _S("ij "), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij AxyzB"), sl@0: _S("ij "), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X L-C-T sl@0: { sl@0: _S("ij C"), sl@0: _S("ij C"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij C"), sl@0: _S("ij "), sl@0: _S("c"), sl@0: _S("C"), sl@0: _S("c"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij C"), sl@0: _S("ij "), sl@0: _S("cc"), sl@0: _S("C"), sl@0: _S("cc"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test L-P-T Y sl@0: { sl@0: _S("AxyzB pq"), sl@0: _S("AxyzB pq"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("AxyzB pq"), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b"), sl@0: _S(" pq"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("AxyzB pq"), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb"), sl@0: _S(" pq"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test L-C-T Y sl@0: { sl@0: _S("C pq"), sl@0: _S("C pq"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("C pq"), sl@0: _S("c"), sl@0: _S("C"), sl@0: _S("c"), sl@0: _S(" pq"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("C pq"), sl@0: _S("cc"), sl@0: _S("C"), sl@0: _S("cc"), sl@0: _S(" pq"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X L-P-T Y sl@0: { sl@0: _S("ij AxyzB pq"), sl@0: _S("ij AxyzB pq"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij AxyzB pq"), sl@0: _S("ij "), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b"), sl@0: _S(" pq") sl@0: }, sl@0: { sl@0: _S("ij AxyzB pq"), sl@0: _S("ij "), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb"), sl@0: _S(" pq") sl@0: } sl@0: }, sl@0: { // Test X L-C-T Y sl@0: { sl@0: _S("ij C pq"), sl@0: _S("ij C pq"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij C pq"), sl@0: _S("ij "), sl@0: _S("c"), sl@0: _S("C"), sl@0: _S("c"), sl@0: _S(" pq") sl@0: }, sl@0: { sl@0: _S("ij C pq"), sl@0: _S("ij "), sl@0: _S("cc"), sl@0: _S("C"), sl@0: _S("cc"), sl@0: _S(" pq") sl@0: } sl@0: }, // End of General Combination tests sl@0: { // Start of Specific tests sl@0: { // Test P-T Y sl@0: // primary text with trailing inline text, secondary text secondary sl@0: // text won't fit on line sl@0: _S("wxyzB pqrstuv"), sl@0: _S("wxyzB"), sl@0: _S(" "), sl@0: _S("pqrstuv"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("wxyzB pqrstuv"), sl@0: _S("wxyzB"), sl@0: _S("b"), sl@0: _S(" "), sl@0: _S("pqrstuv"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("wxyzB pqrstuv"), sl@0: _S("wxyzB"), sl@0: _S("bb"), sl@0: _S(" "), sl@0: _S("pqrstuv"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X P-T one sl@0: // secondary text, primary text with trailing inline text trailing sl@0: // text won't fit and there is no line breaking point inside primary sl@0: // text and the primary text plus trailing text will fit on next line sl@0: { sl@0: _S("ijklm xyzB"), sl@0: _S("ijklm xyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijklm xyzB"), sl@0: _S("ijklm"), sl@0: _S(" "), sl@0: _S("xyzB"), sl@0: _S("b"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijklm xyzB"), sl@0: _S("ijklm"), sl@0: _S(" "), sl@0: _S("xyzB"), sl@0: _S("bb"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X P-T two sl@0: // secondary text, primary text with trailing inline text primary sl@0: // text won't fit and there is no line breaking point inside primary sl@0: // text and the primary text plus trailing text will fit on next line sl@0: { sl@0: _S("ijklm uvwxyzB"), sl@0: _S("ijklm"), sl@0: _S(" "), sl@0: _S("uvwxyzB"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijklm uvwxyzB"), sl@0: _S("ijklm"), sl@0: _S(" "), sl@0: _S("uvwxyzB"), sl@0: _S("b"), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijklm uvwxyzB"), sl@0: _S("ijklm"), sl@0: _S(" "), sl@0: _S("uvwxyzB"), sl@0: _S("bb"), sl@0: _S("") sl@0: } sl@0: }, sl@0: { // Test X L-P-T one sl@0: // secondary text, primary text with leading and trailing inline text trailing sl@0: // text won't fit and there is no line breaking point inside primary text and sl@0: // the leading text plus primary text plus trailing text will fit on the next line sl@0: { sl@0: _S("ij AwxyzB"), sl@0: _S("ij AwxyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ij AwxyzB"), sl@0: _S("ij"), sl@0: _S(" "), sl@0: _S("a"), sl@0: _S("AwxyzB"), sl@0: _S("b") sl@0: }, sl@0: { sl@0: _S("ij AwxyzB"), sl@0: _S("ij"), sl@0: _S(" "), sl@0: _S("aa"), sl@0: _S("AwxyzB"), sl@0: _S("bb") sl@0: } sl@0: }, sl@0: { // Test X L-P-T two sl@0: // secondary text, primary text with leading and trailing inline text primary sl@0: // text won't fit and there is no line breaking point inside primary text and sl@0: // the leading text plus primary text plus trailing text will fit on the next line sl@0: { sl@0: _S("ijkl AxyzB"), sl@0: _S("ijkl AxyzB"), sl@0: _S(""), sl@0: _S(""), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijkl AxyzB"), sl@0: _S("ijkl"), sl@0: _S(" "), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b") sl@0: }, sl@0: { sl@0: _S("ijkl AxyzB"), sl@0: _S("ijkl"), sl@0: _S(" "), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb"), sl@0: } sl@0: }, sl@0: { // Test X L-P-T three sl@0: //secondary text, primary text with leading and trailing inline text leading sl@0: // text won't fit and the leading text plus primary text plus trailing text sl@0: // will fit on the next line sl@0: { sl@0: _S("ijklmnop AxyzB"), sl@0: _S("ijklmnop"), sl@0: _S(" "), sl@0: _S("AxyzB"), sl@0: _S(""), sl@0: _S("") sl@0: }, sl@0: { sl@0: _S("ijklmnop AxyzB"), sl@0: _S("ijklmnop"), sl@0: _S(" "), sl@0: _S("a"), sl@0: _S("AxyzB"), sl@0: _S("b") sl@0: }, sl@0: { sl@0: _S("ijklmnop AxyzB"), sl@0: _S("ijklmnop"), sl@0: _S(" "), sl@0: _S("aa"), sl@0: _S("AxyzB"), sl@0: _S("bb") sl@0: } sl@0: } // End of Specific tests sl@0: }; sl@0: sl@0: static const TInt KTestCount[KTestCases][KInlineTextOptions] = sl@0: { sl@0: { // Start of General Combination tests sl@0: 1, // Test L-P sl@0: 2, sl@0: 2 sl@0: }, sl@0: { sl@0: 1, // Test X L-P sl@0: 3, sl@0: 3 sl@0: }, sl@0: { sl@0: 1, // Test P-T sl@0: 2, sl@0: 2 sl@0: }, sl@0: { sl@0: 1, // Test P-T Y sl@0: 3, sl@0: 3 sl@0: }, sl@0: { sl@0: 1, // Test L-P-T sl@0: 3, sl@0: 3 sl@0: }, sl@0: { sl@0: 1, // Test L-C-T sl@0: 3, sl@0: 3 sl@0: }, sl@0: { sl@0: 1, // Test X L-P-T sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test X L-C-T sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test L-P-T Y sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test L-C-T Y sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test X L-P-T Y sl@0: 5, sl@0: 5 sl@0: }, sl@0: { sl@0: 1, // Test X L-C-T Y sl@0: 5, sl@0: 5 sl@0: }, // End of General Combination tests sl@0: { // Start of Specific tests sl@0: 3, // Test P-T B sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test X P-T one sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 3, // Test X P-T two sl@0: 4, sl@0: 4 sl@0: }, sl@0: { sl@0: 1, // Test X L-P-T one sl@0: 5, sl@0: 5 sl@0: }, sl@0: { sl@0: 1, // Test X L-P-T two sl@0: 5, sl@0: 5 sl@0: }, sl@0: { sl@0: 3, // Test X L-P-T three sl@0: 5, sl@0: 5 sl@0: } // End of Specific tests sl@0: }; sl@0: sl@0: void DoLineTestL(TDes& aText, CTextLayout* aLayout, CTestGraphicsDevice* aDevice, CTextView* aView, TInt aNumChar, TInt aIndex) sl@0: { sl@0: aText = KTestStrings[aIndex][aNumChar][0]; sl@0: CTestFormExtendedInterfaceProvider* interfaceProvider = CTestFormExtendedInterfaceProvider::NewL(aText, aNumChar); // owned here sl@0: aLayout->SetInterfaceProvider(interfaceProvider); sl@0: CleanupStack::PushL(interfaceProvider); sl@0: aDevice->LineArray().ResetLineArray(); sl@0: aView->HandleGlobalChangeL(); sl@0: // now that we've redrawn the actual ooutput (what went through DrawText(), including sl@0: // any inline text) has been stored in the LineArray. So we#'ll have a look and see sl@0: // if it contains what we expect it to. sl@0: // Each line may produce one or more LineArray() entries as there is one created for sl@0: // each call to DrawText() sl@0: const TTestGCDisplayLine* line1 = 0; sl@0: const TTestGCDisplayLine* line2 = 0; sl@0: // Find out how many LineArray entries are expected for the output of this test sl@0: TInt count = KTestCount[aIndex][aNumChar]; sl@0: // And test them (in reverse order, because it's easier) sl@0: switch (count) sl@0: { sl@0: case 5: sl@0: line1 = &(aDevice->LineArray().Line(4)); sl@0: line2 = aDevice->LineArray().Find(KTestStrings[aIndex][aNumChar][5]); sl@0: TESTPOINT(0 != line1); sl@0: TESTPOINT(0 != line2); sl@0: TESTPOINT(line1->iLineData.Compare(line2->iLineData) == 0); sl@0: case 4: sl@0: line1 = &(aDevice->LineArray().Line(3)); sl@0: line2 = aDevice->LineArray().Find(KTestStrings[aIndex][aNumChar][4]); sl@0: TESTPOINT(0 != line1); sl@0: TESTPOINT(0 != line2); sl@0: TESTPOINT(line1->iLineData.Compare(line2->iLineData) == 0); sl@0: case 3: sl@0: line1 = &(aDevice->LineArray().Line(2)); sl@0: line2 = aDevice->LineArray().Find(KTestStrings[aIndex][aNumChar][3]); sl@0: TESTPOINT(0 != line1); sl@0: TESTPOINT(0 != line2); sl@0: TESTPOINT(line1->iLineData.Compare(line2->iLineData) == 0); sl@0: case 2: sl@0: line1 = &(aDevice->LineArray().Line(1)); sl@0: line2 = aDevice->LineArray().Find(KTestStrings[aIndex][aNumChar][2]); sl@0: TESTPOINT(0 != line1); sl@0: TESTPOINT(0 != line2); sl@0: TESTPOINT(line1->iLineData.Compare(line2->iLineData) == 0); sl@0: case 1: sl@0: line1 = &(aDevice->LineArray().Line(0)); sl@0: line2 = aDevice->LineArray().Find(KTestStrings[aIndex][aNumChar][1]); sl@0: TESTPOINT(0 != line1); sl@0: TESTPOINT(0 != line2); sl@0: // Can't always do a direct comparison of lines because same string sl@0: // may appear in more than one line, so compare contents sl@0: TESTPOINT(line1->iLineData.Compare(line2->iLineData) == 0); sl@0: } sl@0: aLayout->SetInterfaceProvider(NULL); sl@0: CleanupStack::PopAndDestroy(interfaceProvider); sl@0: } sl@0: sl@0: void GeneralCombinationTestsTextViewL(TDes& aText, CTextLayout* aLayout, CTestGraphicsDevice* aDevice, CTextView* aView, TInt aNumChar) sl@0: { sl@0: // For all tests carried out from here up to 20 chars will fit on a line sl@0: TESTPRINT(_L("Test L-P")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 0); sl@0: TESTPRINT(_L("Test X L-P")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 1); sl@0: TESTPRINT(_L("Test P-T")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 2); sl@0: TESTPRINT(_L("Test P-T Y")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 3); sl@0: TESTPRINT(_L("Test L-P-T")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 4); sl@0: TESTPRINT(_L("Test L-C-T")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 5); sl@0: TESTPRINT(_L("Test X L-P-T")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 6); sl@0: TESTPRINT(_L("Test X L-C-T")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 7); sl@0: TESTPRINT(_L("Test L-P-T Y")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 8); sl@0: TESTPRINT(_L("Test L-C-T Y")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 9); sl@0: TESTPRINT(_L("Test X L-P-T Y")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 10); sl@0: TESTPRINT(_L("Test X L-C-T Y")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 11); sl@0: } sl@0: sl@0: void SpecificTestsTextViewL(TDes& aText, CTextLayout* aLayout, CTestGraphicsDevice* aDevice, CTextView* aView, TInt aNumChar) sl@0: { sl@0: // For all tests carried out from here up to 10 chars will fit on a line sl@0: TESTPRINT(_L("Test P-T B")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 12); sl@0: TESTPRINT(_L("Test X P-T one")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 13); sl@0: TESTPRINT(_L("Test X P-T two")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 14); sl@0: TESTPRINT(_L("Test X L-P-T one")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 15); sl@0: TESTPRINT(_L("Test X L-P-T two")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 16); sl@0: TESTPRINT(_L("Test X L-P-T three")); sl@0: DoLineTestL(aText, aLayout, aDevice, aView, aNumChar, 17); sl@0: } sl@0: sl@0: void DoLineTestForINC141914L(TDes& aText, CTextLayout* aLayout, CTestGraphicsDevice* aDevice, CTextView* aView) sl@0: { sl@0: /* sl@0: * This case is to test whether or not inline text will find the correct format after changing the text content. sl@0: * In bytecode, there is one value to record the postion(iInlineTextFormat) to which inline text chunk attaches, sl@0: * INC141914 is raised because this value is not updated correctly after text change. sl@0: * The text string is as the following 3 lines: sl@0: * 111111; sl@0: * 222222; sl@0: * wxyBbz sl@0: * Where the 'b' is the inline text. sl@0: * sl@0: * 1st step: sl@0: * delete 5 leading '1's in the first line, sl@0: * 2nd step: sl@0: * delete 5 leading '2's in the second line. sl@0: * after the 2 steps, inline text is still able to use iInlineTextFormat to find its attached text string sl@0: */ sl@0: aText = _S("\x31\x31\x31\x31\x31\x31\x3B\x2029\x32\x32\x32\x32\x32\x32\x3B\x2029\x77\x78\x79\x42\x7A"); sl@0: CTestFormExtendedInterfaceProvider* interfaceProvider = CTestFormExtendedInterfaceProvider::NewL(aText, 1); // owned here sl@0: aLayout->SetInterfaceProvider(interfaceProvider); sl@0: CleanupStack::PushL(interfaceProvider); sl@0: aDevice->LineArray().ResetLineArray(); sl@0: aView->HandleGlobalChangeL(); sl@0: aText.Delete(0,5); sl@0: aView->HandleInsertDeleteL(TCursorSelection(0,0),5); sl@0: aText.Delete(3,5); sl@0: aView->HandleInsertDeleteL(TCursorSelection(3,3),5); sl@0: sl@0: aLayout->SetInterfaceProvider(NULL); sl@0: CleanupStack::PopAndDestroy(interfaceProvider); sl@0: } sl@0: sl@0: void DoLineTestForINC143086L(TDes& aText, CTextLayout* aLayout, CTestGraphicsDevice* aDevice, CTextView* aView) sl@0: { sl@0: /* sl@0: * This case is to test inline text behaviour for right-to-left text sl@0: * The text string is as the following characters: sl@0: * \x5e0\x5e1\x5e2\x5e3\x5e4\x5c0\x5e5; sl@0: * Where the '\x5c0' is the inline text. sl@0: */ sl@0: aText = _S("\x5e0\x5e1\x5e2\x5e3\x5e4\x5c0\x5e5"); sl@0: CTestFormExtendedInterfaceProvider* interfaceProvider = CTestFormExtendedInterfaceProvider::NewL(aText, 1); // owned here sl@0: aLayout->SetInterfaceProvider(interfaceProvider); sl@0: CleanupStack::PushL(interfaceProvider); sl@0: aDevice->LineArray().ResetLineArray(); sl@0: aView->HandleGlobalChangeL(); sl@0: sl@0: aLayout->SetInterfaceProvider(NULL); sl@0: CleanupStack::PopAndDestroy(interfaceProvider); sl@0: } sl@0: sl@0: // aNumChar determines what kind of inline text is in force sl@0: // 0 means no inline text, 1 means insert a single char for sl@0: // each possible inline text and 2 means insert two chars sl@0: void RunGeneralCombinationTestsL(TInt aNumChar) sl@0: { sl@0: CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; sl@0: CleanupStack::PushL(scheduler); sl@0: CActiveScheduler::Install(scheduler); sl@0: TBuf<100> text; sl@0: TDocModel docModel(text); sl@0: // This time make it capable of 20 chars + a couple of spare pixels sl@0: // so all of these tests should result in a single line of output sl@0: TRect displayRect(0, 0, KDisplayWidthWide, KDisplayHeight); sl@0: CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); sl@0: CleanupStack::PushL(layout); sl@0: CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); sl@0: CleanupStack::PushL(device); sl@0: CTextView* view = CTextView::NewL(layout, displayRect, device, device, 0, 0, 0); sl@0: CleanupStack::PushL(view); sl@0: // This is used to force the use of CTestGraphicsContext instead of a normal one sl@0: CWindowGc* offScreenContext; sl@0: User::LeaveIfError(device->CreateContext(offScreenContext)); sl@0: CleanupStack::PushL(offScreenContext); sl@0: CTestTextView::SetContextForFlickerFreeRedraw(view, offScreenContext); sl@0: sl@0: GeneralCombinationTestsTextViewL(text, layout, device, view, aNumChar); sl@0: sl@0: CleanupStack::PopAndDestroy(offScreenContext); sl@0: CleanupStack::PopAndDestroy(view); sl@0: CleanupStack::PopAndDestroy(device); sl@0: CleanupStack::PopAndDestroy(layout); sl@0: CleanupStack::PopAndDestroy(scheduler); sl@0: } sl@0: sl@0: // aNumChar determines what kind of inline text is in force sl@0: // 0 means no inline text, 1 means insert a single char for sl@0: // each possible inline text and 2 means insert two chars sl@0: void RunSpecificTestsL( TInt aNumChar) sl@0: { sl@0: // Note: If you need to move these heap checks any further "in" to focus sl@0: // on a specific test then you will have to move all the setup code in as sl@0: // well - and still preserve the two different display widths in use sl@0: __UHEAP_MARK; sl@0: CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; sl@0: CleanupStack::PushL(scheduler); sl@0: CActiveScheduler::Install(scheduler); sl@0: TBuf<100> text; sl@0: TDocModel docModel(text); sl@0: // This time make it capable of 10 chars + a couple of spare pixels sl@0: // so that line wrapping will occur sl@0: TRect displayRect(0, 0, KDisplayWidthThin, KDisplayHeight); sl@0: CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); sl@0: CleanupStack::PushL(layout); sl@0: CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); sl@0: CleanupStack::PushL(device); sl@0: CTextView* view = CTextView::NewL(layout, displayRect, device, device, 0, 0, 0); sl@0: CleanupStack::PushL(view); sl@0: // This is used to force the use of CTestGraphicsContext instead of a normal one sl@0: CWindowGc* offScreenContext; sl@0: User::LeaveIfError(device->CreateContext(offScreenContext)); sl@0: CleanupStack::PushL(offScreenContext); sl@0: CTestTextView::SetContextForFlickerFreeRedraw(view, offScreenContext); sl@0: sl@0: SpecificTestsTextViewL(text, layout, device, view, aNumChar); sl@0: sl@0: CleanupStack::PopAndDestroy(offScreenContext); sl@0: CleanupStack::PopAndDestroy(view); sl@0: CleanupStack::PopAndDestroy(device); sl@0: CleanupStack::PopAndDestroy(layout); sl@0: CleanupStack::PopAndDestroy(scheduler); sl@0: __UHEAP_MARKEND; sl@0: } sl@0: sl@0: sl@0: void RunTestsForINC141914L() sl@0: { sl@0: __UHEAP_MARK; sl@0: CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; sl@0: CleanupStack::PushL(scheduler); sl@0: CActiveScheduler::Install(scheduler); sl@0: TBuf<100> text; sl@0: TDocModel docModel(text); sl@0: // This time make it capable of 10 chars + a couple of spare pixels sl@0: // so that line wrapping will occur sl@0: TRect displayRect(0, 0, KDisplayWidthWide, KDisplayHeight); sl@0: CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); sl@0: CleanupStack::PushL(layout); sl@0: CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); sl@0: CleanupStack::PushL(device); sl@0: CTextView* view = CTextView::NewL(layout, displayRect, device, device, 0, 0, 0); sl@0: CleanupStack::PushL(view); sl@0: // This is used to force the use of CTestGraphicsContext instead of a normal one sl@0: CWindowGc* offScreenContext; sl@0: User::LeaveIfError(device->CreateContext(offScreenContext)); sl@0: CleanupStack::PushL(offScreenContext); sl@0: CTestTextView::SetContextForFlickerFreeRedraw(view, offScreenContext); sl@0: sl@0: DoLineTestForINC141914L(text, layout, device, view); sl@0: DoLineTestForINC143086L(text, layout, device, view); sl@0: sl@0: CleanupStack::PopAndDestroy(offScreenContext); sl@0: CleanupStack::PopAndDestroy(view); sl@0: CleanupStack::PopAndDestroy(device); sl@0: CleanupStack::PopAndDestroy(layout); sl@0: CleanupStack::PopAndDestroy(scheduler); sl@0: __UHEAP_MARKEND; sl@0: } sl@0: sl@0: TVerdict CTInLineTextStep::doTestStepL() sl@0: { sl@0: SetTestStepResult(EPass); sl@0: TestStep = this; sl@0: sl@0: __UHEAP_MARK; sl@0: TESTPRINT(KTInlineText); sl@0: TESTPRINT(_L(" @SYMTestCaseID:SYSLIB-FORM-LEGACY-INLINETEXT-0001 General combination tests - no inline text ")); sl@0: TInt error = RFbsSession::Connect(); sl@0: if (error == KErrNotFound) sl@0: { sl@0: FbsStartup(); sl@0: error = RFbsSession::Connect(); sl@0: } sl@0: TEST(error == KErrNone); sl@0: TRAP(error, RunGeneralCombinationTestsL(0)); sl@0: TEST(error == KErrNone); sl@0: TESTPRINT(_L("General combination tests - single char inline text")); sl@0: TRAP(error, RunGeneralCombinationTestsL(1)); sl@0: TEST(error == KErrNone); sl@0: TESTPRINT(_L("General combination tests - multi char inline text")); sl@0: TRAP(error, RunGeneralCombinationTestsL(2)); sl@0: TEST(error == KErrNone); sl@0: TESTPRINT(_L("Specific tests - no inline text")); sl@0: TRAP(error, RunSpecificTestsL(0)); sl@0: TEST(error == KErrNone); sl@0: TESTPRINT(_L("Specific tests - single char inline text")); sl@0: TRAP(error, RunSpecificTestsL(1)); sl@0: TEST(error == KErrNone); sl@0: TESTPRINT(_L("Specific tests - multi char inline text")); sl@0: TRAP(error, RunSpecificTestsL(2)); sl@0: TEST(error == KErrNone); sl@0: sl@0: TESTPRINT(_L("Defect tests - for INC141914")); sl@0: TRAP(error, RunTestsForINC141914L()); sl@0: TEST(error == KErrNone); sl@0: sl@0: RFbsSession::Disconnect(); sl@0: __UHEAP_MARKEND; sl@0: User::Heap().Check(); sl@0: return TestStepResult(); sl@0: }