diff -r 000000000000 -r 1fb32624e06b textrendering/textformatting/test/src/TTextView2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/textformatting/test/src/TTextView2.cpp Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,3699 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* @file +* @internalComponent +* +*/ + + +#include "TCustomWrap.h" +#include "TGraphicsContext.h" +#include "TBitmapDoc.h" +#include "TestPicture.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "TAGMA_INTERNAL.H" +#endif + +namespace LocalToFile { + +_LIT(KTTextView2, "TTextView2"); +const TInt KDisplayWidth = 100; +const TInt KDisplayHeight = 100; +const TInt KAleph = 0x5D0; +const TInt KPictureCharacter = 0xFFFC; +const TInt KRightToLeftMarker = 0x200F; +const TInt KZeroWidthNonJoiner = 0x200C; +RTest test(KTTextView2); + +/** Simple test picture. */ +class CPinkSquare : public CPicture + { +public: + // Size of square in twips. + // 600 is 15 pixels using the standard test graphics device at + // its default resolution. + enum { KWidth = 600, KHeight = 600 }; + CPinkSquare() {} + void Draw(CGraphicsContext& aGc, const TPoint& aTopLeft, + const TRect& aClipRect, MGraphicsDeviceMap* aMap) const + { + // This picture is a magenta square + TPoint size(KWidth, KHeight); + if (aMap) + size = aMap->TwipsToPixels(size); + TRect rect(aTopLeft, aTopLeft + size); + aGc.SetClippingRect(aClipRect); + aGc.SetDrawMode(CGraphicsContext::EDrawModePEN); + aGc.SetPenColor(KRgbMagenta); + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetBrushColor(KRgbMagenta); + aGc.DrawRect(rect); + } + void ExternalizeL(RWriteStream&) const {} + void GetOriginalSizeInTwips(TSize& a) const + { + a.iWidth = CPinkSquare::KWidth; + a.iHeight = CPinkSquare::KHeight; + } + }; + +_LIT(KEnd, "\x2029"); +/** Lightweight test document model. */ +class TDocModel : public MLayDoc + { +public: + TDocModel(const TDesC& aDes) + : iDes(&aDes), iParagraphFormat(0), iBreakPos(0) {} + void SetParagraphFormat(CParaFormat* a) + { + iParagraphFormat = a; + } + /** Sets the segmentation of the buffer to cut at this point. + aParam a 0 means no break at all. */ + void SetBreakPos(TInt a) + { + iBreakPos = a; + } + // From MLayDoc + TInt LdDocumentLength() const { return iDes->Length(); } + TInt LdToParagraphStart(TInt& a) const + { + TInt curr = a; + if (a < LdDocumentLength()) + { + a = iDes->Left(a).LocateReverse(0x2029); + a = a < 0? 0 : a + 1; + } + return curr - a; + } + void GetParagraphFormatL(CParaFormat* aFormat, TInt) const + { + if (iParagraphFormat) + { + aFormat->CopyL(*iParagraphFormat); + return; + } + aFormat->Reset(); + TTabStop tabStop; + tabStop.iTwipsPosition = 1000; + tabStop.iType = TTabStop::ELeftTab; + aFormat->StoreTabL(tabStop); + } + void GetChars(TPtrC& aView,TCharFormat& aFormat, TInt aStartPos)const + { + TCharFormat cf; + aFormat = cf; + TInt docLength = LdDocumentLength(); + if (aStartPos < iBreakPos && iBreakPos < docLength) + aView.Set(iDes->Mid(aStartPos, iBreakPos - aStartPos)); + else if (aStartPos == docLength) + aView.Set(KEnd); + else + aView.Set(iDes->Mid(aStartPos)); + } + TInt GetPictureSizeInTwips(TSize& aSize, TInt aPos) const + { + if ((*iDes)[aPos] != KPictureCharacter) + return KErrNotFound; + aSize.iWidth = CPinkSquare::KWidth; + aSize.iHeight = CPinkSquare::KHeight; + return KErrNone; + } + CPicture* PictureHandleL(TInt aPos, TForcePictureLoad) const + { + if ((*iDes)[aPos] != KPictureCharacter) + return 0; + return new(ELeave) CPinkSquare; + } + TBool EnquirePageBreak(TInt aPos, TInt aLength)const + { + return iDes->Mid(aPos, aLength).Locate(0x000C) < 0? + EFalse : ETrue; + } + TBool SelectParagraphLabel(TInt) { return EFalse; } + void CancelSelectLabel() {} +private: + const TDesC* iDes; + CParaFormat* iParagraphFormat; + TInt iBreakPos; + }; +} + +// Remaps whatever character is used in construction to the letter 'E' +class TTestCustomRemap : public MFormCustomInvisibleCharacterRemapper + { +public: + TTestCustomRemap(TUint aChar) + { + iChar = aChar; + } + TUint Remap(TUint aChar, const TNonPrintingCharVisibility aNonPrintingCharVisibility, + const TLayDocTextSource& aLayDoc) + { + if (aChar == iChar) + { + return 'E'; + } + else + { + return DefaultMapping(aChar, aNonPrintingCharVisibility, aLayDoc); + } + } +private: + TUint iChar; + }; + + +// Remaps all break characters to the letter 'E' +class TTestCustomRemapper : public MFormCustomInvisibleCharacterRemapper + { +public: + TUint Remap(TUint aChar, const TNonPrintingCharVisibility aNonPrintingCharVisibility, + const TLayDocTextSource& aLayDoc) + { + switch (aChar) + { + case CEditableText::ELineBreak: + case CEditableText::EParagraphDelimiter: + case CEditableText::EPageBreak: + return 'E'; + + default: + break; // do nothing + } + + return DefaultMapping(aChar, aNonPrintingCharVisibility, aLayDoc); + } + }; + +using namespace LocalToFile; + +class CTestTextView + { +public: + static void SetOffScreenContext(CTextView* aView, CBitmapContext* aContext) + { + aView->iOffScreenContext = aContext; + } + static TRect GetInvalidRect(CTextView* aView) + { + return aView->iDisplay.ClippingRect(); + } + static int GetFormattedHeight(CTextView* aView) + { + return aView->iFormattedUpTo; + } + static void TestMemberOffsetsL() + { + // The members of these classes must not move due to inline method offsets. + // Any of the following tests failing will indicate a BC break. + test(_FOFF(CTextView, iLayout)==64); + test(_FOFF(CTextView, iCursorPos)==192); + test(_FOFF(CTextView, iFlags)==240); + test(_FOFF(CTextView, iObserver)==264); + } + }; + +class CTestTextLayout + { +public: + static void TestMemberOffsetsL() + { + // The members of these classes must not move due to inline method offsets. + // Any of the following tests failing will indicate a BC break. + test(_FOFF(CTextLayout, iText)==4); + test(_FOFF(CTextLayout, iBandTop)==104); + test(_FOFF(CTextLayout, iScrollFlags)==116); + test(_FOFF(CTextLayout, iHighlightExtensions)==128); + } + }; + +// Test for TET-5D7MCV: Sound object focus indicators flickering +_LIT(KPicture, "\xFFFC"); +_LIT(KInitialText, "xy"); + +void SetViewRect1(CTextView *aView) + { + TRect view(0, 0, 100, 100); + aView->SetViewRect(view); + } + +void SetViewRect2(CTextView *aView) + { + TRect view(10, 15, 60, 65); + aView->SetViewRect(view); + } + +void TET_5D7MCV_L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView, + CTextLayout* aLayout) + { + // This is supposed to test flicker-free redraw, but that is very difficult + // to test properly, so we do what we can: + // 1) If flicker-free redraw is disabled and there is no off-screen context set, + // there should be drawing to the real device + // 2) If there is an off-screen context set, there should be drawing to the + // off-screen context, and not the real device + // 3) If flicker-free redraw is enabled and there is no off-screen context set, + // there should be no drawing to the real device. + // We are not testing that the correct thing is drawn to the internal off-screen + // bitmap when flicker-free redraw is enabled. This is bad, but I can't work + // out a good way round it. As the off-screen context uses much of the same + // machinery as flicker-free redraw, it tests maybe 80% of it. + SetViewRect1(aView); + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(aDevice->SizeInPixels(), 0); + CleanupStack::PushL(offScreenDevice); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + + CTestTextView::SetOffScreenContext(aView, 0); + aView->DisableFlickerFreeRedraw(); + + aText.Append(KInitialText); + aView->HandleInsertDeleteL(TCursorSelection(0,KInitialText().Length()), 0, EFalse); + aText.Insert(1, KPicture); + aView->HandleInsertDeleteL(TCursorSelection(1,2), 0, ETrue); + aView->SetCursorVisibilityL(TCursor::EFCursorVisible, TCursor::EFCursorVisible); + aView->SetSelectionVisibilityL(ETrue); + aView->EnablePictureFrameL(ETrue); + TRect* pictureRectPtr; + TInt frameEdges; + aView->SetXyPosL(TPoint(11, 1), EFalse, pictureRectPtr, frameEdges); + test(pictureRectPtr != 0); + aDevice->ClearAreaDrawnWithCondition(); + offScreenDevice->ClearAreaDrawnWithCondition(); + aView->DrawL(TRect(0, 0, CPinkSquare::KWidth, CPinkSquare::KHeight)); + test(!aDevice->AreaDrawnWithCondition().IsEmpty()); + test(offScreenDevice->AreaDrawnWithCondition().IsEmpty()); + aDevice->ClearAreaDrawnWithCondition(); + offScreenDevice->ClearAreaDrawnWithCondition(); + + CTestTextView::SetOffScreenContext(aView, offScreenContext); + aView->EnableFlickerFreeRedraw(); + + aView->DrawL(TRect(0, 0, CPinkSquare::KWidth, CPinkSquare::KHeight)); + test(aDevice->AreaDrawnWithCondition().IsEmpty()); + TRect xoredArea = offScreenDevice->AreaDrawnWithCondition(); + test(!xoredArea.IsEmpty()); + offScreenDevice->ClearAreaDrawnWithCondition(); + SetViewRect1(aView); + const TRect &viewRect = aView->ViewRect(); + aView->DrawL(viewRect); + test(aDevice->AreaDrawnWithCondition().IsEmpty()); + test(offScreenDevice->AreaDrawnWithCondition() == xoredArea); + + // We need a CFbsDevice -- this will supply fonts that can be drawn to the + // offscreen bitmap created by the flicker-free redraw code. + CFbsBitmap* bm = new CFbsBitmap; + CleanupStack::PushL(bm); + bm->Create(TSize(1,1), EGray2); + CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bm); + CleanupStack::PushL(bitmapDevice); + aLayout->SetImageDeviceMap(bitmapDevice); + CTestTextView::SetOffScreenContext(aView, 0); + aView->EnableFlickerFreeRedraw(); + + aView->DrawL(TRect(0, 0, CPinkSquare::KWidth, CPinkSquare::KHeight)); + test(aDevice->AreaDrawnWithCondition().IsEmpty()); + xoredArea = offScreenDevice->AreaDrawnWithCondition(); + test(!xoredArea.IsEmpty()); + offScreenDevice->ClearAreaDrawnWithCondition(); + SetViewRect1(aView); + aView->DrawL(viewRect); + test(aDevice->AreaDrawnWithCondition().IsEmpty()); + + aLayout->SetImageDeviceMap(aDevice); + CleanupStack::PopAndDestroy(bitmapDevice); + CleanupStack::PopAndDestroy(bm); + CTestTextView::SetOffScreenContext(aView, 0); + aView->DisableFlickerFreeRedraw(); + + aDevice->ClearAreaDrawnWithCondition(); + offScreenDevice->ClearAreaDrawnWithCondition(); + aView->DrawL(viewRect); + test(offScreenDevice->AreaDrawnWithCondition().IsEmpty()); + xoredArea.Move(viewRect.iTl); + test(aDevice->AreaDrawnWithCondition() == xoredArea); + + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + } +/** +@SYMTestCaseID SYSLIB-FORM-CT-4014 +@SYMTestCaseDesc Tests CTextView::IsPictureFrameSelected doesn't panic with EFNoPictureFrame +@SYMTestPriority High +@SYMTestActions +@SYMTestExpectedResults Resulting document position are where expected and frame drawn correctly. + In this case picture frame is not drawn as we set the selection visibility to "off" +@SYMDEF PDEF118831 +*/ +void RunPDEF118831TestL() + { + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 140, 185)); + + //create the picture to insert (this one is a red box) + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,400)); + + //add some text before the pictures + bitMap->AppendL(_L("A")); + + //Add 2 pictures + TInt pos = 0; + for (pos=0;pos<2;pos++) + bitMap->AppendL(pic); + + //add some text after the pictures + bitMap->AppendL(_L("A")); + bitMap->View()->HandleGlobalChangeL(); + + //As a result we have + // A+Pict+Pict+A + //with cursor pos: 01 1 2 2 3 4 + + //SetSelectionVisibility to false + bitMap->View()->SetSelectionVisibilityL(EFalse); + + // Place the cursor at the end of the last picture added and start moving the cursor left. + TCursorPosition::TMovementType type = TCursorPosition::EFLeft; + + // Docuemnt position is already at the end, but it is Trailing. Make it Leading and set it. + TTmDocPosSpec::TType docPosType = TTmDocPosSpec::ELeading; + + TTmDocPos thisPos; + TTmDocPosSpec docPos; + docPos.iPos = 4; + docPos.iType = docPosType; + TRect dummyRect; + TInt dummyPos; + TBool selectionIsPictureFrame; + + // Cursor on last letter "A" + bitMap->View()->SetDocPosL(docPos); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 4 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 0); + + // Move cursor left + // Cursor moved to first (from the right) picture but picture frame not selected + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 3 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 0); + + + // Move cursor left + // Cursor still on first picture and now picture frame has been selected + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 2 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 1); + + // Move cursor left + // Cursor on second picture and picture frame not selected + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 2 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 0); + + + // Move cursor left + // Cusror still on second picture and picture frame has been selected + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 1 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 1); + + // Move cursor left + // Cursor moved to second letter "A" + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 1 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 0); + + + //Move cursor left + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + selectionIsPictureFrame + = bitMap->View()->IsPictureFrameSelected(dummyRect, dummyPos); + test(thisPos.iPos == 0 && type == TCursorPosition::EFLeft); + test(selectionIsPictureFrame == 0); + + + CleanupStack::Pop(pic); + CleanupStack::PopAndDestroy(1); + } +/** +Test for defect INC020746: Visual cursor position update incorrect at end of +document +*/ +void INC020746_L(TDes& aText, CTextView* aView) + { + aText.Zero(); + aText.Append('A'); + aText.Append(0x5D0); // Aleph + SetViewRect1(aView); + aView->DisableFlickerFreeRedraw(); + aView->HandleGlobalChangeL(); + TTmDocPosSpec pos(2, TTmDocPosSpec::ELeading); + aView->SetDocPosL(pos); + TTmDocPos posOut; + aView->GetCursorPos(posOut); + test(posOut.iPos == 2); + test(posOut.iLeadingEdge); + pos.iType = TTmDocPosSpec::ETrailing; + aView->SetDocPosL(pos); + aView->GetCursorPos(posOut); + test(posOut.iPos == 2); + test(!posOut.iLeadingEdge); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-1653 +@SYMTestCaseDesc Test to make sure an ordinary hyphen is returned when a potential hyphen is inserted. +@SYMTestPriority Critical. +@SYMTestActions Insets a potential hyphen into some text and then check the output once it has passed + through MTmCustom::Map. +@SYMTestExpectedResults The test must not fail. +@SYMDEF INC080603: Soft Hyphen is not replaced by Ordinary Hyphen in Tagma +*/ + +// Test code had to be changed because of a problem in BullseyeCoverage, which does not like +// dealing with certain hexadecimal character combinations in string literals. +void INC080603L(TDes& aText, CTestGraphicsDevice* aDevice,CTextLayout* aLayout, CTextView* aView) + { + _LIT(KInputText, "ABCDEFABCDEF"); + const TUint16 Hyphen = 0x00ad; + + aDevice->LineArray().ResetLineArray(); + aDevice->LineArray().Enable(); + + aText.Zero(); + aText = KInputText; + aText.Insert(6, (TPtrC(&Hyphen,1))); + + SetViewRect1(aView); + aLayout->SetWrapWidth(aView->ViewRect().Width()); + aLayout->ForceNoWrapping(CTextLayout::EFParagraphsWrappedByDefault); + + aView->HandleGlobalChangeL(); + + TBuf<3> des2 (aDevice->LineArray().Line(1).LineData()); //Hyphen should be on this line + TInt pos = des2.Find(_L("-")); + test (pos != KErrNotFound); + + aDevice->LineArray().Disable(); + } + +/** +DEF035472 - Non-printable char detection api does not report correct result +*/ +void DEF035472_L(TDes& aText, CTextView* aView) + { + const TChar leftToRightMarker(0x200E); + aText.Zero(); + aText.Append(leftToRightMarker); + aText.Append(leftToRightMarker); + aText.Append(leftToRightMarker); + aText.Append('A'); + aText.Append(leftToRightMarker); + aText.Append(leftToRightMarker); + aText.Append(leftToRightMarker); + aView->HandleGlobalChangeL(); + TTmDocPosSpec position(3, TTmDocPosSpec::ELeading); + aView->SetDocPosL(position); + TCursorSelection selection = aView->GetBackwardDeletePositionL(); + test(selection.LowerPos() == 0); + test(selection.HigherPos() == 3); + position.iType = TTmDocPosSpec::ETrailing; + aView->SetDocPosL(position); + selection = aView->GetBackwardDeletePositionL(); + test(selection.LowerPos() == 0); + test(selection.HigherPos() == 3); + position.iPos = 4; + aView->SetDocPosL(position); + selection = aView->GetForwardDeletePositionL(); + test(selection.LowerPos() == 4); + test(selection.HigherPos() == 7); + position.iType = TTmDocPosSpec::ELeading; + aView->SetDocPosL(position); + selection = aView->GetForwardDeletePositionL(); + test(selection.LowerPos() == 4); + test(selection.HigherPos() == 7); + } + +/** +INC036005 - Word--difficult to place focus on an object in word. +This defect is caused by a defect in Form in which when finding a position +by x-y coordinate, the trailing edge is never found, always the leading edge. +This means that the trailing edge of the picture is incorrectly identified as +the leading edge of the following character and the picture is not highlighted. +This test tests that the trailing edge of characters is found correctly. +*/ +void INC036005_L(TDes& aText, CTextView* aView) + { + aText.Zero(); + aText.Append('A'); + aText.Append('B'); + aText.Append('C'); + SetViewRect2(aView); + aView->DisableFlickerFreeRedraw(); + aView->HandleGlobalChangeL(); + aView->SetLeftTextMargin(0); + aView->SetViewLineAtTopL(1); + TPoint pt(22, 20); + test(1 == aView->XyPosToDocPosL(pt)); + pt.SetXY(28, 20); + test(1 == aView->XyPosToDocPosL(pt)); + aText.Zero(); + aText.Append(0x5D0); + aText.Append(0x5D1); + aText.Append(0x5D2); + aView->HandleGlobalChangeL(); + aView->SetLeftTextMargin(0); + aView->SetViewLineAtTopL(1); + pt.SetXY(92, 20); + test(1 == aView->XyPosToDocPosL(pt)); + pt.SetXY(98, 20); + test(1 == aView->XyPosToDocPosL(pt)); + + // Test with real picture + aText.Zero(); + aText.Append('A'); + aText.Append(KPictureCharacter); + aText.Append('C'); + aView->HandleGlobalChangeL(); + aView->SetLeftTextMargin(0); + aView->SetViewLineAtTopL(1); + TInt edges; + TRect* rect; + pt.SetXY(22, 20); + aView->SetXyPosL(pt, EFalse, rect, edges); + TCursorSelection sel = aView->Selection(); + test(sel.LowerPos() == 1 && sel.HigherPos() == 2); + aView->SetDocPosL(0, EFalse); + pt.SetXY(32, 20); + aView->SetXyPosL(pt, EFalse, rect, edges); + sel = aView->Selection(); + test(sel.LowerPos() == 1 && sel.HigherPos() == 2); + + // Test with real picture and potentially confusing ambiguities + aText.Zero(); + aText.Append('A'); + aText.Append(KRightToLeftMarker); + aText.Append(KPictureCharacter); + aText.Append(KRightToLeftMarker); + aText.Append('C'); + aView->HandleGlobalChangeL(); + aView->SetLeftTextMargin(0); + aView->SetViewLineAtTopL(1); + pt.SetXY(22, 20); + aView->SetXyPosL(pt, EFalse, rect, edges); + sel = aView->Selection(); + test(sel.LowerPos() == 2 && sel.HigherPos() == 3); + aView->SetDocPosL(0, EFalse); + pt.SetXY(32, 20); + aView->SetXyPosL(pt, EFalse, rect, edges); + sel = aView->Selection(); + test(sel.LowerPos() == 2 && sel.HigherPos() == 3); + } + + +// INC085809: CSHelp - Scrolling doesn't work properly, length of the bar changes weirdly +// With the fix in PosRangeInBand, the output in this case will be one pixel larger than before +void INC085809_L(CTextLayout* aLayout, CTextView* aView) + { + TInt input; + TRect view(0, 0, 102, 26); + aView->SetViewRect(view); + TInt output = aLayout->PosRangeInBand(input); + test(output==11); + } + +// Utility functions to show contents of test data using test.Printf + +_LIT(KAddressMarker, "> "); +_LIT(KSpace, " "); +_LIT(KLength, ", Length of Data = %d 16-bit words\r\n"); +_LIT(KSpaces, " "); +_LIT(KPeriod, "."); +_LIT(KSingleString, "%s\r\n"); + + + void PrintTestData (const TDesC& aTitle , const TDesC16& aData) + { + + TInt i; + TInt j; + TInt end; + + TInt length = aData.Length(); + + TBuf<80> buffer; + + buffer.Zero(); + buffer.Append(aTitle); + buffer.Append(KLength); + + test.Printf(buffer, length); + + for (i = 0 ; i < length ; i += 8) + { + buffer.Zero(); + buffer.AppendNumFixedWidth(i, EHex, 8); + buffer += KAddressMarker; + + end = ((length-i) >= 8) ? i+8 : length; + + for (j = i ; j < end ; ++j) + { + buffer.AppendNumFixedWidth(aData[j], EHex, 4); + buffer += KSpace; + } + buffer += TPtrC(KSpaces().Ptr(), ((8-(j-i))*5)+4); + + for (j = i ; j < end ; ++j) + { + if (aData[j] >= 32) + { + buffer.Append(aData[j]); + } + else + { + buffer += KPeriod; + } + } + buffer.ZeroTerminate(); + test.Printf(KSingleString, buffer.Ptr()); + } + + } + +void PrintTestData(const TDesC& aTitle, const TText16* aDataBuffer, const TInt aSize) + { + PrintTestData(aTitle, TPtrC16(aDataBuffer, aSize)); + } + + + _LIT(KTavSequence, "\x05ea\x05ea\x05ea\x05ea\x05ea\x05ea\x05ea\x05ea\x05ea\x05ea"); + + _LIT(KMixedSequence, "\x05d1\x05d2\x05d3\x05d4\x05d5\x05d6\x05d7\x05d8\x05d9 JCDEFGHIJ " + L"\x05da\x05db\x05dc\x05dd\x05de\x05df\x05e0\x05e1\x05e2 KLMNOPQRS "); + +static const TInt KChunksPerTest = 9; +static const TInt KDirectionalityTests = 5; + +static const TPtrC16 KDirectionalityResults[KDirectionalityTests][KChunksPerTest] = + { + { + _S("\xffff\x0020\xffff"), + _S("\xffff\x05d9\x05d8\x05d7\x05d6\x05d5\x05d4\x05d3\x05d2\x05d1\x05d0\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004a\x0043\x0044\x0045\x0046\x0047\x0048\x0049\x004a\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x05e2\x05e1\x05e0\x05df\x05de\x05dd\x05dc\x05db\x05da\xffff"), + _S("\xffff\xffff\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004b\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053\xffff") + }, + { + _S("\xffff\x0020\xffff"), + _S("\xffff\x05d9\x05d8\x05d7\x05d6\x05d5\x05d4\x05d3\x05d2\x05d1\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004a\x0043\x0044\x0045\x0046\x0047\x0048\x0049\x004a\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x05e2\x05e1\x05e0\x05df\x05de\x05dd\x05dc\x05db\x05da\xffff"), + _S("\xffff\xffff\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004b\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053\xffff"), + }, + { + _S("\xffff\x0049\xffff"), + _S("\xffff\x05d9\x05d8\x05d7\x05d6\x05d5\x05d4\x05d3\x05d2\x05d1\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004a\x0043\x0044\x0045\x0046\x0047\x0048\x0049\x004a\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x05e2\x05e1\x05e0\x05df\x05de\x05dd\x05dc\x05db\x05da\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004b\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053\x0020\xffff\xffff"), + _S("\xffff\xffff\xffff"), + }, + { + _S("\xffff\x0020\xffff"), + _S("\xffff\x05d9\x05d8\x05d7\x05d6\x05d5\x05d4\x05d3\x05d2\x05d1\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004a\x0043\x0044\x0045\x0046\x0047\x0048\x0049\x004a\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x05e2\x05e1\x05e0\x05df\x05de\x05dd\x05dc\x05db\x05da\xffff"), + _S("\xffff\xffff\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004b\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053\xffff"), + }, + { + _S("\xffff\x0020\xffff"), + _S("\xffff\x05d9\x05d8\x05d7\x05d6\x05d5\x05d4\x05d3\x05d2\x05d1\x05d0\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004a\x0043\x0044\x0045\x0046\x0047\x0048\x0049\x004a\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x05e2\x05e1\x05e0\x05df\x05de\x05dd\x05dc\x05db\x05da\xffff"), + _S("\xffff\xffff\xffff"), + _S("\xffff\x0020\xffff"), + _S("\xffff\x004b\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053\xffff"), + } + }; + +_LIT(KTitle1, "Initial format (RtoL)"); +_LIT(KTitle2, "Deleting first character , still RtoL"); +_LIT(KTitle3, "Inserting a first character, now LtoR"); +_LIT(KTitle4, "Deleting first character , becoming RtoL"); +_LIT(KTitle5, "Inserting a first character, still RToL"); +_LIT(KPassed, "passed\r\n"); +_LIT(KFailed, "failed\r\n"); +_LIT(KExpected, "Expected"); +_LIT(KGot, "Got"); +_LIT(KCase, "Test case %d, testing chunk %d\r\n"); + + + +const TUint16 KUnicodeLetterA = 'I'; +const TUint16 KUnicodeLetterHebrewAlef = 0x05d0; + +TPtrC KLUnicodeLetterA(&KUnicodeLetterA,1); +TPtrC KLUnicodeLetterHebrewAlef(&KUnicodeLetterHebrewAlef,1); + +void DirectionalityTestL(TDes& aText, CTestGraphicsDevice* aDevice, CTextLayout* aLayout, CTextView* aView) + { + test.Next(_L("Testing paragraph directionality of editable text")); + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(aDevice->SizeInPixels(), 0); + CleanupStack::PushL(offScreenDevice); + offScreenDevice->SetLineArray(aDevice->LineArray()); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + CTestTextView::SetOffScreenContext(aView, offScreenContext); + aView->EnableFlickerFreeRedraw(); + TInt i; + TPtrC16 title; + TBool match; + TBool passed; + TBool allPassed = ETrue; + TInt chunksInThisTest; + for (TInt testCase = 0 ; testCase < KDirectionalityTests ; ++testCase) + { + test.Printf(_L("Directionality test case %d\r\n"), testCase+1); + passed = ETrue; + aDevice->LineArray().ResetLineArray(); + chunksInThisTest = KChunksPerTest; + switch(testCase) + { + case 0: + title.Set(KTitle1); + aLayout->SetAmountToFormat(CTextLayout::EFFormatAllText); + aText.Zero(); + aDevice->LineArray().ResetLineArray(); + aText.Append(KUnicodeLetterHebrewAlef); //first strong character is right-to-left + aText.Append(KMixedSequence); //rest of test data is constant + aView->HandleGlobalChangeL(); + aView->FinishBackgroundFormattingL(); + break; + case 1: + title.Set(KTitle2); + aView->SetDocPosL(0,EFalse); + aDevice->LineArray().ResetLineArray(); + aText.Delete(0,1); //delete the first character + aView->HandleGlobalChangeL(); + break; + case 2: + title.Set(KTitle3); + aView->SetDocPosL(0,EFalse); + aDevice->LineArray().ResetLineArray(); + aText.Insert(0,KLUnicodeLetterA); //replace first character with a left-to-right one + aView->HandleGlobalChangeL(); + chunksInThisTest = KChunksPerTest - 1; + break; + case 3: + title.Set(KTitle4); + aView->SetDocPosL(0,EFalse); + aDevice->LineArray().ResetLineArray(); + aText.Delete(0,1); //delete the first character + aView->HandleGlobalChangeL(); + break; + case 4: + title.Set(KTitle5); + aView->SetDocPosL(0,EFalse); + aDevice->LineArray().ResetLineArray(); + aText.Insert(0,KLUnicodeLetterHebrewAlef); //replace first character with a right-to-left one again + aView->HandleGlobalChangeL(); + break; + default: + test.Printf(_L("Directionality test %d undefined\r\n"), testCase); + break; + } + test.Printf(title); + for (i = 0; i < chunksInThisTest ; ++i) + { + const TDesC16& des1 = KDirectionalityResults[testCase][i]; + const TDesC16& des2 = aDevice->LineArray().Line(i).LineData(); + match = (des1.Compare(des2) == 0); + if (!match) + { + test.Printf(KCase, testCase, i); + PrintTestData(KExpected, KDirectionalityResults[testCase][i]); + PrintTestData(KGot, aDevice->LineArray().Line(i).LineData()); + } + passed = passed && match; + } + if (passed) + { + test.Printf(KPassed); + } + else + { + allPassed = EFalse; + test.Printf(KFailed); + } + } + test(allPassed); + CTestTextView::SetOffScreenContext(aView, 0); + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + } + +// Test for defect DEF021603: Visual cursor position update incorrect when insert a LTR char after +// a RTL string. +void DEF021603_L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView) + { + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(aDevice->SizeInPixels(), 0); + CleanupStack::PushL(offScreenDevice); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + CTestTextView::SetOffScreenContext(aView, offScreenContext); + + TTmDocPos posOut; + aText.Zero(); + aText.Append(KLUnicodeLetterHebrewAlef); + aText.Append(KLUnicodeLetterHebrewAlef); + aText.Append(KLUnicodeLetterA); + aView->HandleCharEditL(CTextLayout::EFCharacterInsert, EFalse); + aView->GetCursorPos(posOut); + test(!posOut.iLeadingEdge); // should be on trailing edge (rhs) + + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + } + + +_LIT(KText_022229, "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCABCDEFGHIJABCDEFGHIJABCDEFGHIJ"); + +/** +Test for defect DEF022229: Form: Cursor sent to 'home' position on Page up/down +movement in Word. +*/ +void DEF022229_L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView) + { + SetViewRect2(aView); + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(aDevice->SizeInPixels(), 0); + CleanupStack::PushL(offScreenDevice); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + CTestTextView::SetOffScreenContext(aView, offScreenContext); + + TTmDocPos cursorPos; + aText = KText_022229; + aView->SetDocPosL(0); + test(cursorPos.iPos==0); + + //LineDown + TCursorPosition::TMovementType lineDown = TCursorPosition::EFLineDown; + aView->MoveCursorL(lineDown, EFalse); + aView->GetCursorPos(cursorPos); + TInt compare = cursorPos.iPos; + + //PageDown + TCursorPosition::TMovementType pageDown = TCursorPosition::EFPageDown; + aView->MoveCursorL(pageDown, EFalse); + aView->GetCursorPos(cursorPos); + test(cursorPos.iPos!=0); + + //PageUp + TCursorPosition::TMovementType pageUp = TCursorPosition::EFPageUp; + aView->MoveCursorL(pageUp, EFalse); + aView->GetCursorPos(cursorPos); + test(cursorPos.iPos==compare); + + CTestTextView::SetOffScreenContext(aView, 0); + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + } + +/** +Tests that CTextView::XyPosToDocPosL returns the correct positions in the case +where the point passed in is beyond the horizontal bounds of the line. +*/ +void TestCTextView_XyPosToDocPosL_ReturnsCorrectLine( + TDes& aText, CTextView* aView) + { + aText = _L("abcdef ghijkl\x2029zyxwvu."); + aView->HandleGlobalChangeL(); + TPoint pt(-20, 24); + TInt pos = aView->XyPosToDocPosL(pt); + test(pos == 0); + pt.SetXY(200, 24); + pos = aView->XyPosToDocPosL(pt); + test(pos == 6 || pos == 5); + pt.SetXY(-20, 36); + pos = aView->XyPosToDocPosL(pt); + test(pos == 7); + pt.SetXY(200, 36); + pos = aView->XyPosToDocPosL(pt); + test(pos == 13); + pt.SetXY(-20, 48); + pos = aView->XyPosToDocPosL(pt); + test(pos == 14); + pt.SetXY(200, 48); + pos = aView->XyPosToDocPosL(pt); + test(pos == 20 || pos == 21); + } + +void INC036809_L(TDes& aText, CTextView* aView) + { + aText = _L("A\tB"); + aView->HandleGlobalChangeL(); + TTmPosInfo2 posInfo; + TTmDocPosSpec pos(1, TTmDocPosSpec::ELeading); + TBool result = aView->FindDocPosL(pos, posInfo); + test(result); + test(posInfo.iDocPos.iPos == 1); + test(posInfo.iDocPos.iLeadingEdge); + test(posInfo.iEdge.iX = 30); + pos.iPos = 2; + pos.iType = TTmDocPosSpec::ETrailing; + result = aView->FindDocPosL(pos, posInfo); + test(result); + test(posInfo.iDocPos.iPos == 2); + test(!posInfo.iDocPos.iLeadingEdge); + test(posInfo.iEdge.iX = 45); + pos.iType = TTmDocPosSpec::ELeading; + result = aView->FindDocPosL(pos, posInfo); + test(result); + test(posInfo.iDocPos.iPos == 2); + test(posInfo.iDocPos.iLeadingEdge); + test(posInfo.iEdge.iX = 45); + } + +void DEF037255_L(TDes& aText, CTextView* aView) + { + // 0x2004 = 3-per-em space: 3 pixels in the test font + // 0x2029 = Paragraph delimiter + // 0xFFFC = object replacement character + aText = _L("\x2004\x2004Y\x2029\xFFFC\x2029\x2004\x2004W"); + aView->EnablePictureFrameL(ETrue); + aView->HandleGlobalChangeL(); + TTmDocPos pos(1, EFalse); + aView->SetDocPosL(pos); + const TCursorPosition::TMovementType down = TCursorPosition::EFLineDown; + TCursorPosition::TMovementType m = down; + aView->MoveCursorL(m, EFalse); + TCursorSelection sel = aView->Selection(); + test(sel.LowerPos() == 4); + test(sel.HigherPos() == 5); + m = down; + aView->MoveCursorL(m, EFalse); + sel = aView->Selection(); + test(sel.LowerPos() == 7); + test(sel.HigherPos() == 7); + } + +/** Tests that the horizontal scroll position is within acceptable bounds. +*/ +void TestCursorPosition(const CTextView* aView) + { + TInt hsj = aView->HorizontalScrollJump(); + TInt width = aView->ViewRect().Width(); + TInt buffer = width / 10; + TInt left; + TInt right; + aView->Layout()->CalculateHorizontalExtremesL(left, right, ETrue, EFalse); + TInt minCursorX = 0; + TInt maxCursorX = width; + if (left < 0) + { + left -= hsj + buffer; + minCursorX = buffer; + } + if (width < right) + { + right += hsj + buffer; + maxCursorX = width - buffer; + } + TInt ltm = aView->LeftTextMargin(); + TTmDocPos docPos; + aView->GetCursorPos(docPos); + TTmPosInfo2 posInfo; + TTmLineInfo lineInfo; + TBool docPosFormatted = aView->Layout() + ->FindDocPos(docPos, posInfo, &lineInfo); + TBool cursorIsOutsideBounds = posInfo.iEdge.iX < lineInfo.iInnerRect.iTl.iX + || lineInfo.iInnerRect.iBr.iX <= posInfo.iEdge.iX? ETrue : EFalse; + TInt cursorX = posInfo.iEdge.iX - ltm; + test(docPosFormatted); + test((left <= ltm && ltm + width <= right) + || cursorIsOutsideBounds); + test((minCursorX <= cursorX && cursorX <= maxCursorX) + || cursorIsOutsideBounds); + } + +void INC037293_L(TDes& aText, CTextView* aView, CTextLayout* aLayout) + { + aView->EnablePictureFrameL(EFalse); + aLayout->ForceNoWrapping(CTextLayout::EFAllParagraphsNotWrapped); + aLayout->SetWrapWidth(aView->ViewRect().Width()); + aText.Zero(); + aView->HandleGlobalChangeL(); + TestCursorPosition(aView); + TCursorPosition::TMovementType move; + for (TInt i0 = 0; i0 != 20; ++i0) + { + aText.Append('a' + i0); + TCursorSelection sel(i0, i0 + 1); + aView->HandleInsertDeleteL(sel, 0, EFalse); + TestCursorPosition(aView); + } + move = TCursorPosition::EFLineBeg; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + move = TCursorPosition::EFLineEnd; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + for (TInt i1 = 0; i1 != 20; ++i1) + { + move = TCursorPosition::EFLeft; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + for (TInt i2 = 0; i2 != 20; ++i2) + { + move = TCursorPosition::EFRight; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + aText.Zero(); + aView->HandleGlobalChangeL(); + TestCursorPosition(aView); + for (TInt i3 = 0; i3 != 20; ++i3) + { + aText.Append(KAleph); + TCursorSelection sel(i3, i3 + 1); + aView->HandleInsertDeleteL(sel, 0, EFalse); + TestCursorPosition(aView); + } + move = TCursorPosition::EFLineBeg; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + move = TCursorPosition::EFLineEnd; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + for (TInt i4 = 0; i4 != 20; ++i4) + { + move = TCursorPosition::EFRight; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + for (TInt i5 = 0; i5 != 20; ++i5) + { + move = TCursorPosition::EFLeft; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + + aText.Zero(); + aLayout->ForceNoWrapping(CTextLayout::EFParagraphsWrappedByDefault); + aView->HandleGlobalChangeL(); + TestCursorPosition(aView); + for (TInt i6 = 0; i6 != 10; ++i6) + { + aText.Append('a' + i6); + aText.Append(' '); + TCursorSelection sel(i6 * 2, i6 * 2 + 2); + aView->HandleInsertDeleteL(sel, 0, EFalse); + TestCursorPosition(aView); + } + for (TInt i7 = 0; i7 != 30; ++i7) + { + move = TCursorPosition::EFLeft; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + for (TInt i8 = 0; i8 != 30; ++i8) + { + move = TCursorPosition::EFRight; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + + aText.Zero(); + aView->HandleGlobalChangeL(); + TestCursorPosition(aView); + for (TInt i9 = 0; i9 != 10; ++i9) + { + aText.Append(KAleph); + aText.Append(' '); + TCursorSelection sel(i9 * 2, i9 * 2 + 2); + aView->HandleInsertDeleteL(sel, 0, EFalse); + TestCursorPosition(aView); + } + for (TInt ia = 0; ia != 30; ++ia) + { + move = TCursorPosition::EFRight; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + for (TInt ib = 0; ib != 30; ++ib) + { + move = TCursorPosition::EFLeft; + aView->MoveCursorL(move, EFalse); + TestCursorPosition(aView); + } + } + +/** Tests that the text specified has been drawn by the device and returns +its x-coordinate. */ +TInt XCoordinateOfText(const TDesC& aText, CTestGraphicsDevice* aDevice) + { + const TTestGCDisplayLine* line = aDevice->LineArray().Find(aText); + test(line != 0); + return line->Position().iX; + } + +/** +INC038282 - Right-to-Left text in CSHLPCMP toolchain + Form is not formatted +correctly + +Tests that when the text directionality is resolved implicitly the indents, +margins and bullets are on the correct sides. +@internalComponent +*/ +void INC038282_L(TDes& aText, CTestGraphicsDevice* aDevice, + CTextLayout* aLayout, CTextView* aView, + CParaFormat* aParagraphFormat) + { + SetViewRect2(aView); + // Gentle first test: set margins, left-to-right text, no bullets, leading alignment. + aText = _L("F s."); + aParagraphFormat->iLeftMarginInTwips = 200; // 5 pixels + aParagraphFormat->iRightMarginInTwips = 600; // 15 pixels + aParagraphFormat->iIndentInTwips = 280; // 7 pixels + aParagraphFormat->iHorizontalAlignment = CParaFormat::ELeftAlign; + aLayout->SetWrapWidth(aView->ViewRect().Width()); + TCursorSelection selection(0, 0); + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + TInt x = XCoordinateOfText(_L("F"), aDevice); + test(x == 22); + x = XCoordinateOfText(_L("s."), aDevice); + test(x == 15); + // Now right aligned + aParagraphFormat->iHorizontalAlignment = CParaFormat::ERightAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("F"), aDevice); + test(x == 35); + x = XCoordinateOfText(_L("s."), aDevice); + test(x == 25); + // Now Hebrew left aligned (with ERightAlign set, because really + // that means "trailing") + aText = _L("\x5D0 \x5D1"); + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 25); + // Now right aligned (== leading == ELeftAlign). + aParagraphFormat->iHorizontalAlignment = CParaFormat::ELeftAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 38); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 45); + // Now with a bullet. + aParagraphFormat->iIndentInTwips = 440; // 11 pixels + aParagraphFormat->iBullet = new(ELeave) TBullet; + aParagraphFormat->iBullet->iHangingIndent = EFalse; + aParagraphFormat->iBullet->iCharacterCode = 0x2022; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 34); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 45); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(44 <= x); + // Trailing (left) align + aParagraphFormat->iHorizontalAlignment = CParaFormat::ERightAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(35 <= x); + // Latin text, right aligned. + aText = _L("F s."); + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("F"), aDevice); + test(x == 35); + x = XCoordinateOfText(_L("s."), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(x <= 25); + // left aligned + aParagraphFormat->iHorizontalAlignment = CParaFormat::ELeftAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("F"), aDevice); + test(x == 26); + x = XCoordinateOfText(_L("s"), aDevice); + test(x == 15); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(x <= 15); + // Now bullet with hanging indent (Latin text, leading alignment) + aParagraphFormat->iBullet->iHangingIndent = ETrue; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("F"), aDevice); + test(x == 26); + x = XCoordinateOfText(_L("s"), aDevice); + test(x == 26); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(x <= 15); + // Trailing alignment + aParagraphFormat->iHorizontalAlignment = CParaFormat::ERightAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("F"), aDevice); + test(x == 35); + x = XCoordinateOfText(_L("s"), aDevice); + test(x == 35); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(x <= 25); + // Hebrew, trailing, hanging indent + aText = _L("\x5D0 \x5D1"); + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 25); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(36 <= x); + // Leading alignment + aParagraphFormat->iHorizontalAlignment = CParaFormat::ELeftAlign; + aView->SetPendingSelection(selection); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + x = XCoordinateOfText(_L("\x5D0"), aDevice); + test(x == 34); + x = XCoordinateOfText(_L("\x5D1"), aDevice); + test(x == 34); + x = XCoordinateOfText(_L("\x2022"), aDevice); + test(44 <= x); + + aParagraphFormat->Reset(); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-1663 +@SYMTestCaseDesc Tests to make sure when non-solid border has been set for the paragraph more than 1 line, + there's no border been drawn between the lines in the paragraph. +@SYMTestPriority High +@SYMTestActions Insert a paragraph of text, which contains at least 3 lines. Draw non-solid borders + for the paragraph. Check the area between line 1 and line 2 to see if there's any border + been drawn incorrectly. +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF073913 +*/ +const TInt KBorderThicknessInTwips=40; + +void DEF073913L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView, CParaFormat* aParagraphFormat) + { + SetViewRect1(aView); + + aText = _L("abcdefghijklmnopqrstuvwxyz"); + + // set borders' attribute + TParaBorder top; + TParaBorder bottom; + TParaBorder left; + TParaBorder right; + top.iThickness=KBorderThicknessInTwips; + bottom.iThickness=KBorderThicknessInTwips; + left.iThickness=KBorderThicknessInTwips; + right.iThickness=KBorderThicknessInTwips; + + // make it non-solid for the defect testing + top.iLineStyle=TParaBorder::EDotted; + bottom.iLineStyle=TParaBorder::EDotted; + left.iLineStyle=TParaBorder::EDotted; + right.iLineStyle=TParaBorder::EDotted; + + TParaFormatMask aParaMask; + aParaMask.SetAttrib(EAttTopBorder); + aParaMask.SetAttrib(EAttBottomBorder); + aParaMask.SetAttrib(EAttLeftBorder); + aParaMask.SetAttrib(EAttRightBorder); + + aParagraphFormat->SetParaBorderL(CParaFormat::EParaBorderTop,top); + aParagraphFormat->SetParaBorderL(CParaFormat::EParaBorderBottom,bottom); + aParagraphFormat->SetParaBorderL(CParaFormat::EParaBorderLeft,left); + aParagraphFormat->SetParaBorderL(CParaFormat::EParaBorderRight,right); + + TCursorSelection selection(0, 0); + aView->SetPendingSelection(selection); + + // set testing area: border area between text line 1 and line 2 + TRect forbiddenArea(1, 13, 49, 13); + aDevice->SetTestingArea(forbiddenArea); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + + // check there have enough lines in the paragraph + TInt lines = aDevice->LineArray().LinesPresent(); + test(lines >= 3); + + // check the drawing result, + // expected: no line has been drawn on the testing area + test(aDevice->HasDrawnOnTestingArea() == EFalse); + + aParagraphFormat->Reset(); + } + +/** +INC039567 - Zero-width Non-joiner character does not work in editors + +Tests that Arabic letters separated by ZWNJ (U+200C) are either rendered in +separate calls or remain separated in their strings by ZWNJ. +@internalComponent +*/ +void INC039567_L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView) + { + aText = _L("\x628\x200C\x62D\x200C\x633"); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + for (TInt i = 0; i < aText.Length(); i += 2) + { + const TTestGCDisplayLine *line = aDevice->LineArray().Find( + aText.Mid(i, 1)); + // Check that the line actually was drawn + test(0 != line); + const TDesC& displayed = line->iLineData; + TInt pos = displayed.Locate(aText[i]); + // Check that the line contains the text we expect. Failure here indicates + // a failure of the test code. + test(0 <= pos); + // Check that the character is followed by a ZWNJ, if anything at all. + // 0xFFFF intervening is OK + for (TInt j = pos + 1; + j != displayed.Length() && displayed[j] != KZeroWidthNonJoiner; + ++j) + test(displayed[j] == 0xFFFF); + // Check that the character is preceded by a ZWNJ, if anything at all. + // 0xFFFF intervening is OK + for (TInt k = pos; + 0 != k && displayed[k - 1] != KZeroWidthNonJoiner; --k) + test(displayed[k - 1] == 0xFFFF); + } + } + +/** Erroneous Cursor movement on top two lines + +Tests that when the cursor is moved up to the top of the document and then up +one more to the start of the document, that the latent X position moves to the +start of the line as well. +@internalComponent +*/ +void DEF061143_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + SetViewRect1(aView); + aLayout->ForceNoWrapping(CTextLayout::EFParagraphsWrappedByDefault); + aLayout->SetWrapWidth(aView->ViewRect().Width()); + aText = _L("First Line Second."); + aView->HandleGlobalChangeL(); + TTmDocPos pos(15, ETrue); + aView->SetDocPosL(pos); + TCursorPosition::TMovementType move = TCursorPosition::EFLineUp; + aView->MoveCursorL(move, EFalse); + move = TCursorPosition::EFLineUp; + aView->MoveCursorL(move, EFalse); + aView->GetCursorPos(pos); + test(pos.iPos == 0); + move = TCursorPosition::EFLineDown; + aView->MoveCursorL(move, EFalse); + aView->GetCursorPos(pos); + test(pos.iPos == 11); + } + +/** Page Down from last line moves the cursor to the start of the line. */ +void DEF063340_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + SetViewRect1(aView); + aLayout->ForceNoWrapping(CTextLayout::EFParagraphsWrappedByDefault); + aLayout->SetWrapWidth(aView->ViewRect().Width()); + aText = _L("j"); + aView->HandleGlobalChangeL(); + TTmDocPos pos(1, EFalse); + aView->SetDocPosL(pos); + TCursorPosition::TMovementType move = TCursorPosition::EFPageDown; + aView->MoveCursorL(move, EFalse); + aView->GetCursorPos(pos); + test(pos.iPos == 1); + test(move == TCursorPosition::EFLineEnd); + } + +TBool LineIsEqual(CLineArray& aLineArray, TInt aLineNumber, + const TDesC& aCandidate) + { + TPtrC line; + line.Set( aLineArray.Line(aLineNumber).LineData() ); + while (1 < line.Length() && line[0] == 0xFFFF) + line.Set( line.Mid(1) ); + while (1 < line.Length() && line[line.Length() - 1] == 0xFFFF) + line.Set( line.Left(line.Length() - 1) ); + return 0 == aCandidate.Compare(line); + } + +_LIT(KClusterBreakTest1, "\xE01\xE33"); +_LIT(KClusterBreakTest2, "citta\x300"); +_LIT(KClusterBreakTest3, "\x928\x94d\x928"); +/** @SYMTestCaseID SYSLIB-FORM-UT-1533 +@SYMTestCaseDesc + Test that clusters are not broken by segmented storage. +@SYMTestPriority High +@SYMTestActions + Format some Devanagari with a text model that deliberately + refuses to supply Form with whole syllables. Check that whole + syllables are rendered. +@SYMTestExpectedResults No panics. +@SYMPREQ PREQ18 */ +void TestClusterBreaks(TDes& aText, CTestGraphicsDevice* aDevice, + CTextLayout* aLayout, CTextView* aView, TDocModel* aDocModel) + { + SetViewRect1(aView); + aLayout->ForceNoWrapping(CTextLayout::EFParagraphsWrappedByDefault); + aLayout->SetWrapWidth(aView->ViewRect().Width()); + aDevice->LineArray().Enable(); + TCharFormat dummy; + TPtrC text; + aText = KClusterBreakTest1(); + aDocModel->SetBreakPos(1); + // Check TDocModel is actually doing the test correctly + aDocModel->GetChars(text, dummy, 0); + test(text.Length() == 1); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + test(LineIsEqual(aDevice->LineArray(), 0, KClusterBreakTest1)); + + aText = KClusterBreakTest2(); + aDocModel->SetBreakPos(5); + aDocModel->GetChars(text, dummy, 0); + test(text.Length() == 5); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + test(LineIsEqual(aDevice->LineArray(), 0, KClusterBreakTest2)); + + aText = KClusterBreakTest3(); + aDocModel->SetBreakPos(2); + aDocModel->GetChars(text, dummy, 0); + test(text.Length() == 2); + aDevice->LineArray().ResetLineArray(); + aView->HandleGlobalChangeL(); + test(LineIsEqual(aDevice->LineArray(), 0, KClusterBreakTest3)); + + aDocModel->SetBreakPos(0); + } + +/** DEF065322: Inconsistent parameter values in MFormCustomDraw::DrawBackground() */ +const TInt KDEF065322_CharSize = 13; // height of char +const TInt KDEF065322_MaxCount = 3; +const TInt KDEF065322_RectSize = 100; // view is 100 by 100 + +class DEF065322_CustomDraw : public MFormCustomDraw + { +public: + void DrawBackground(const TParam &aParam, const TRgb &aBackground, TRect &aDrawn) const + { + TRgb ignore(aBackground); + aDrawn = aParam.iDrawRect; + + // Test that there are 3 calls to this method and that the expected results are returned. + test(count < KDEF065322_MaxCount); + + test(aDrawn.iTl.iX == 0); + test(aDrawn.iTl.iY == count*KDEF065322_CharSize); + test(aDrawn.iBr.iX == KDEF065322_RectSize); + + if(count < KDEF065322_MaxCount-1) + { + test(aDrawn.iBr.iY == (1+count)*KDEF065322_CharSize); + } + else + { + test(aDrawn.iBr.iY == KDEF065322_RectSize); + } + count++; + } + + static TInt count; + }; + +TInt DEF065322_CustomDraw::count = 0; + +void DEF065322_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + // This text results in 3 calls to the DEF065322_CustomDraw::DrawBackground() + // 1 call for each line of text (2) and 1 for remainder of the text view. + aText = _L("12345678901234567890"); + TRect displayRect(0, 0, 100, 100); + + // custom draw + DEF065322_CustomDraw customDraw; + aLayout->SetCustomDraw(&customDraw); + + // create screen context + CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); + CleanupStack::PushL(device); + CTestGraphicsDevice* screenDevice = CTestGraphicsDevice::NewL(device->SizeInPixels(), 0); + CleanupStack::PushL(screenDevice); + screenDevice->SetLineArray(device->LineArray()); + CWindowGc* screenContext; + User::LeaveIfError(screenDevice->CreateContext(screenContext)); + CleanupStack::PushL(screenContext); + CTestTextView::SetOffScreenContext(aView, screenContext); + + // enable flicker free redraw + aView->EnableFlickerFreeRedraw(); + + // Cause DEF065322_CustomDraw::DrawBackground() to be executed 3 times + aView->HandleGlobalChangeL(); + + // reset counter + DEF065322_CustomDraw::count = 0; + + // disable flicker free redraw + aView->DisableFlickerFreeRedraw(); + + // Cause DEF065322_CustomDraw::DrawBackground() to be executed 3 times + aView->HandleGlobalChangeL(); + + // remove custom draw + aLayout->SetCustomDraw(NULL); + + // tidy up + CTestTextView::SetOffScreenContext(aView, 0); + CleanupStack::PopAndDestroy(screenContext); + CleanupStack::PopAndDestroy(screenDevice); + CleanupStack::PopAndDestroy(device); + } + + // Side-bearings at the ends of chunks are now taken into account. + void INC078304_L(TDes& aText, CTextView* aView) + { + // W has side-bearings of 1 pixel extending on each side. + // Waw (U+0648) has a left side-bearing of -5 + // Therefore "WWW" has total width 1+10+10+10+1 == 32 + // WawWaw has total width 5+10+10 == 25 + SetViewRect1(aView); + aText = _L("WWW\x648\x648WWW\x2029\xff0f\xff0f\xff0f\x2029///"); + aView->HandleGlobalChangeL(); + TTmLineInfo line; + TTmPosInfo2 posInfo; + TTmDocPosSpec posSpec(1, TTmDocPosSpec::ETrailing); + aView->FindDocPosL(posSpec, posInfo, &line); + test(line.iInnerRect.iTl.iX == 0); + test(line.iInnerRect.iBr.iX == 89); + test(posInfo.iEdge.iX == 11); + posSpec.iPos = 2; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 21); + posSpec.iPos = 3; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 32); + posSpec.iType = TTmDocPosSpec::ELeading; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 57); + posSpec.iPos = 4; + posSpec.iType = TTmDocPosSpec::ETrailing; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 47); + posSpec.iPos = 5; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 32); + posSpec.iType = TTmDocPosSpec::ELeading; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 57); + posSpec.iPos = 6; + posSpec.iType = TTmDocPosSpec::ETrailing; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 68); + posSpec.iPos = 7; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 78); + posSpec.iPos = 8; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 89); + + // Test fullwidth solidus -- has a right side-bearing in our font + // It is best if this goes 10, 20, 31 + // but it is acceptable for it to go 11, 22, 33 + posSpec.iPos = 10; + aView->FindDocPosL(posSpec, posInfo, 0); + TInt x1 = posInfo.iEdge.iX; + test(x1 == 10 || x1 == 11); + posSpec.iPos = 11; + aView->FindDocPosL(posSpec, posInfo, 0); + TInt x2 = posInfo.iEdge.iX; + test(x2 - x1 == 10 || x2 - x1 == 11); + posSpec.iPos = 12; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX - x2 == 11); + + // Test "///" -- / has a left side-bearing in our font + // It is best if this goes 11, 21, 31 + // but it is acceptable for it to go 11, 22, 33 + posSpec.iPos = 14; + aView->FindDocPosL(posSpec, posInfo, 0); + test(posInfo.iEdge.iX == 11); + posSpec.iPos = 15; + aView->FindDocPosL(posSpec, posInfo, 0); + x1 = posInfo.iEdge.iX; + test(x1 == 21 || x1 == 22); + posSpec.iPos = 16; + aView->FindDocPosL(posSpec, posInfo, 0); + x2 = posInfo.iEdge.iX; + test(x2 - x1 == 10 || x2 - x1 == 11); + } + +// Pen position now taken into account in bounds calculation/check. +void INC086257_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + // Conditions setup to simulate the unwanted horiz scroll pre-fix + // Fix will cause line-break instead + { + // Left-to-right + aText = _L("DDDDDDDDDD"); + aView->HandleGlobalChangeL(); + TPoint cursorPoint; + aView->DocPosToXyPosL(aLayout->TagmaTextLayout().EndChar()-1,cursorPoint); + test(cursorPoint.iX==11); //break happened - cursor is one character from left margin + test(cursorPoint.iY==23); //and on the next line + // Right-to-left + aText = KTavSequence; // right-to-left characters + aView->HandleGlobalChangeL(); + aView->DocPosToXyPosL(aLayout->TagmaTextLayout().EndChar()-1,cursorPoint); + test(cursorPoint.iX==89); //break happened - cursor is one character from right margin + test(cursorPoint.iY==23); //and on the next line + } + +// Remapped linebreak characters now conditionally taken into account in bounds calculation/check. +void INC087637_test(TDes& aText, CTextLayout* aLayout, CTextView* aView, + TPoint& cursorPoint, TBool aLeft2Right, TUint aAppendChar=0) +// Set up conditions placed in subroutine to guarantee consistency + { + if(aLeft2Right) + { + aText = _L("DDDDDDDDDD"); + } + else + { + aText = KTavSequence; // right-to-left characters + } + if(aAppendChar) + { + aText.Append(aAppendChar); + aView->HandleGlobalChangeL(); + aView->DocPosToXyPosL(aLayout->TagmaTextLayout().EndChar()-2,cursorPoint); + } + else + { + aView->HandleGlobalChangeL(); + aView->DocPosToXyPosL(aLayout->TagmaTextLayout().EndChar()-1,cursorPoint); + } + }; +void INC087637_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + // Conditions setup to simulate the linebreak character overhanging margin + // Fix will cause wrap conditional upon flag set in layout object + { + TTestCustomRemap paradelim(CEditableText::EParagraphDelimiter); + TTestCustomRemap linebreak(CEditableText::ELineBreak); + TTestCustomRemap pagebreak(CEditableText::EPageBreak); + TTestCustomRemapper allbreaks; + TRect view(0, 0, 200, 200); + aView->SetViewRect(view); + aLayout->SetWrapWidth(102); // allow a couple of pixels to allow for linebreak char start + TPoint cursorPoint; + const TBool Left2Right = ETrue; + const TBool Right2Left = EFalse; + TTestCustomWrap customWrap; + + // Left-to-right + + // First test status quo to show difference + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + // Remap paragraph delimiter - still no difference because no custom wrap set + aLayout->SetCustomInvisibleCharacterRemapper(¶delim); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + // Set custom wrap - paragraph delimiter, and only paragraph delimiter breaks to a new line + aLayout->SetCustomWrap(&customWrap); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + // Remap linebreak character - linebreak character, and only linebreak character breaks to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&linebreak); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + // Remap pagebreak character - pagebreak character, and only pagebreak character breaks to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&pagebreak); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + // Remap all linebreak characters - all test break to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&allbreaks); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==0); //cursor is at left margin + test(cursorPoint.iY==23); //and on the second line + // With all linebreak characters remapped, reset custom wrap - no breaks occur + aLayout->SetCustomWrap(NULL); + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::ELineBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Left2Right,CEditableText::EPageBreak); + test(cursorPoint.iX==101); //cursor is near right margin + test(cursorPoint.iY==10); //and on the first line + + // Right-to-Left + + // First test status quo to show difference + aLayout->SetCustomInvisibleCharacterRemapper(NULL);// switch off character remapping + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + // Remap paragraph delimiter - still no difference because no custom wrap set + aLayout->SetCustomInvisibleCharacterRemapper(¶delim); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + // Set custom wrap - paragraph delimiter, and only paragraph delimiter breaks to a new line + aLayout->SetCustomWrap(&customWrap); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //and on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + // Remap linebreak character - linebreak character, and only linebreak character breaks to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&linebreak); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //but on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + // Remap pagebreak character - pagebreak character, and only pagebreak character breaks to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&pagebreak); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //but on the second line + // Remap all linebreak characters - all test break to a new line + aLayout->SetCustomInvisibleCharacterRemapper(&allbreaks); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //but on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //but on the second line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==102); //cursor is at right margin + test(cursorPoint.iY==23); //but on the second line + // With all linebreak characters remapped, reset custom wrap - no breaks occur + aLayout->SetCustomWrap(NULL); + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::ELineBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + INC087637_test(aText,aLayout,aView,cursorPoint,Right2Left,CEditableText::EPageBreak); + test(cursorPoint.iX==1); //cursor is near left margin + test(cursorPoint.iY==10); //and on the first line + + // reset for next test + aLayout->SetWrapWidth(100); + aLayout->SetCustomInvisibleCharacterRemapper(NULL); + } + +// No Memory mode entered twice on a certain leave unwinding +void DEF078967_L(TDes& aText, CTestGraphicsDevice* aDevice, CTextView* aView) + { + SetViewRect1(aView); + aText = _L("some text is bigger than others"); + aView->HandleGlobalChangeL(); + TSize size(100, 100); + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(size, 0); + CleanupStack::PushL(offScreenDevice); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + CTestTextView::SetOffScreenContext(aView, offScreenContext); + aView->EnableFlickerFreeRedraw(); + TRect rect(size); + CBitmapContext* bc; + User::LeaveIfError(aDevice->CreateBitmapContext(bc)); + CleanupStack::PushL(bc); + // Form can eat leaves, so we'll want a clear run of + // (say) three before we'll stop testing. + TInt ok = 0; + for (TInt i = 1; ok < 3; ++i) + { + __UHEAP_FAILNEXT(i); + TRAPD(error, aView->DrawL(rect, *bc)); + if (error == KErrNone) + ++ok; + else + ok = 0; + __UHEAP_RESET; + } + CleanupStack::PopAndDestroy(bc); + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + aView->DisableFlickerFreeRedraw(); + } + +void INC092568_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + //fill up text buffer/ view + aText = _L("1234567890123456789012345678901234567890123456789012"); + aText.Append(_L("34567890123456789012345678901234567890123456789")); + aView->HandleGlobalChangeL(); + + //set up test variable + TInt end = aText.Length(); + TPoint viewableWindowTopLeft(0,0); + TCursorSelection selectTop(0,0); + TCursorSelection selectBottom(end,end); + TTmPosInfo2 posInfo; + + //restrict viewable window so that scrolling is necessary + aLayout->SetBandHeight(70); + + //test scrolling *without* SetPendingSelection + aView->SetDocPosL(0); //scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); + aView->HandleInsertDeleteL(selectBottom,0,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up + aView->SetDocPosL(0); //scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); //text has scrolled down + aView->HandleRangeFormatChangeL(selectBottom,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up + + //test *no* scrolling with SetPendingSelection + //and selection reset by Handle.. methods + aView->SetDocPosL(0);//scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); + aView->SetPendingSelection(selectTop); + aView->HandleInsertDeleteL(selectBottom,0,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); //text has not scrolled + aView->HandleRangeFormatChangeL(selectBottom,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up due to reset + aView->SetDocPosL(0); //scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); + aView->SetPendingSelection(selectTop); + aView->HandleRangeFormatChangeL(selectBottom,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); //text has not scrolled + aView->HandleInsertDeleteL(selectBottom,0,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up due to reset + + //test *scrolling* with SetPendingSelection + aView->SetDocPosL(0);//scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); + aView->SetPendingSelection(selectBottom); + aView->HandleInsertDeleteL(selectTop,0,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up due to selectpending + aView->SetDocPosL(0); //scroll text down to top of document + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0); + aView->SetPendingSelection(selectBottom); + aView->HandleRangeFormatChangeL(selectTop,ETrue); + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 40); //text has scrolled up due to selectpending + + //reset for next test + aView->SetDocPosL(0); + } + +void INC092257L(TDes& aText,CTextView* aView) + { + aText.Zero(); + aView->HandleGlobalChangeL(); + aView->GetForwardDeletePositionL(); + aView->GetBackwardDeletePositionL(); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-3422 +@SYMTestCaseDesc "Scrolling works weirdly when replying to email". This was a particular + sequence of API calls under certain conditions that was causing an + unexpected downward line scroll. +@SYMTestPriority High +@SYMTestActions Recreate the defect's pre-conditions and then call the API sequence. +@SYMTestExpectedResults At the end of the sequence, no downward line scroll should have occurred. +@SYMDEF PDEF109450 +*/ +void PDEF109450_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + // Text buffer/ view should be filled up and should include + // a paragraph break after a few characters + aText = _L("12345"); + aText.Append(_L("\x2029")); // para delim + aText.Append(_L("6789012345678901234567890123456789012345678901")); + aText.Append(_L("2345678901234567890123456789012345678901234567")); + aView->HandleGlobalChangeL(); + + // Set up defect preconditions + TViewYPosQualifier viewYPosQualifier; + viewYPosQualifier.SetFillScreen(); + viewYPosQualifier.SetMakeLineFullyVisible(); + aLayout->SetBandHeight(50); //restrict viewable window so that scrolling is necessary + aLayout->SetAmountToFormat(CTextLayout::EFFormatBand);//set visible height to band height + aView->SetDocPosL(0);//scroll to top of document + TCursorPosition::TMovementType cursorMovement = TCursorPosition::EFLineDown; + aView->MoveCursorL(cursorMovement,0);//move the cursor down one line from the top + TTmDocPos docPos; + aView->GetCursorPos(docPos); + aText.Insert(docPos.iPos, _L("\x2029"));//insert a 2nd para break right after the 1st + + // Call the API sequence + aView->SetPendingSelection(TCursorSelection(docPos.iPos,docPos.iPos)); + aView->HandleInsertDeleteL(TCursorSelection(docPos.iPos+1,docPos.iPos),1); + aView->HandleGlobalChangeNoRedrawL(viewYPosQualifier); + aView->HandleCharEditL(CTextLayout::EFParagraphDelimiter); + + // Test to ensure no scroll has occurred + TPoint viewableWindowTopLeft(0,0); + TTmPosInfo2 posInfo; + aView->FindXyPosL(viewableWindowTopLeft, posInfo, NULL); + test(posInfo.iDocPos.iPos == 0);//viewableWindowTopLeft should still be at doc start + + //reset for next test + aView->SetDocPosL(0); + } + +void VerifyLineBreak(CTextView* aView,TInt aLines, TInt *aLineEnds) + { + CTextView::TTagmaForwarder forwarder; + forwarder.InitL(aView); + + //force reformatting of text + aView->HandleGlobalChangeL(); + + //get the number of lines in the text + TInt lines = forwarder.Lines(); + test(lines == aLines); + + //verify that the lines are broken in the correct places + TTmLineInfo info; + for(TInt index = 0;index < aLines;index++) + { + forwarder.LineNumberToLine(index,info); + test(info.iEnd == aLineEnds[index]); + } + } +/** +@SYMTestCaseID SYSLIB-FORM-CT-3478 +@SYMTestCaseDesc Tests to ensure the correct line breaking behaviour when wrapping tabs +@SYMTestPriority High +@SYMTestActions Formats a series of strings using a variety of custom wrapping rules and verifies that + strings with tabs are broken correctly +@SYMTestExpectedResults All strings should be broken as specified by the line breaking rules +@SYMDEF PDEF107440 +*/ +void PDEF107440_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + //This array defines the positions in the string where the lines should end + TInt lineEnds[2] = {10,17}; + + _LIT(KTestString1,"gggggg ggg\taaaaa"); + _LIT(KTestString2,"gggggggggg\taaaaa"); + _LIT(KTestString3,"gggggggggg\t aaaa"); + _LIT(KTestString4,"gggggggggg \taaaa"); + + //Set the text string - the length of this string (actually the position + //of the tab within the string) is set so that the tab character should not + //fit properly into a single line + aText = KTestString1; + + //This custom wrapper will allow breaking before the tab character + TTestCustomWrap2 customWrap2; + aLayout->SetCustomWrap(&customWrap2); + + //Check that the line is broken before the tab + VerifyLineBreak(aView, 2, lineEnds); + + //This custom wrapper will allow the tab to hang + TTestCustomWrap3 customWrap3; + aLayout->SetCustomWrap(&customWrap3); + + aText = KTestString1; + + //Check that the line is broken after the tab + lineEnds[0] = 11; + VerifyLineBreak(aView, 2, lineEnds); + + //This custom wrapper will treat the tab as a space line breaking class + TTestCustomWrap4 customWrap4; + aLayout->SetCustomWrap(&customWrap4); + + //Check that the line is broken after the tab + lineEnds[0] = 11; + VerifyLineBreak(aView, 2, lineEnds); + + //Now change the text so that the tab is followed by a space character + aText = KTestString3; + + //Verify that the line is broken after the space - as the space and tab are allowed to hang + lineEnds[0] = 12; + VerifyLineBreak(aView, 2, lineEnds); + + //Now change the text so that the tab follows a space character + aText = KTestString4; + + //Verify that the line is broken after the tab - as the space and tab are allowed to hang + VerifyLineBreak(aView, 2, lineEnds); + + //reset to the default wrapper - this will not allow breaking + //before the tab and will not allow the tab to hang + aLayout->SetCustomWrap(NULL); + + //Set back to the original string + aText = KTestString1; + + //Verify that the line is broken after the space as the string cannot + // be legally broken before or after the tab + lineEnds[0] = 7; + VerifyLineBreak(aView, 2, lineEnds); + + //Now change the text so that the line cannot be broken legally + //at the space character + aText = KTestString2; + + //Verify that the line is broken before the tab - this is a forced break + lineEnds[0] = 10; + VerifyLineBreak(aView, 2, lineEnds); + + //Now change the text so that the tab is followed by a space character + aText = KTestString3; + + //Verify that the line is broken before the tab as the tab is not allowed to hang + //this is a forced break + lineEnds[0] = 10; + VerifyLineBreak(aView, 2, lineEnds); + + //Now change the text so that the tab follows a space character + aText = KTestString4; + + //Verify that the line is broken before the tab as space is allowed to hang + lineEnds[0] = 11; + VerifyLineBreak(aView, 2, lineEnds); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-3521 +@SYMTestCaseDesc Testing the fix for INC108075: Marathi Input : Fallback rendered characters appears suddenly when we are insert +@SYMTestPriority Medium +@SYMTestActions Check that cverlapping characters in the text do not affect the line breaking +@SYMTestExpectedResults Lines should be broken at correct positions with ZWJ. +@SYMDEF INC108075 +*/ +void INC108075_L(TDes& aText, CTextLayout* aLayout, CTextView* aView) + { + // Ra+Virama(Halant)+ZWJ = Eyelash Ra + _LIT(KTestString1,"\x0930\x094D\x200D Hello, 12 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); + // Same as above, but replacing a space with Arabic letter Feh, this should cause an overlap of chunks + // at the ZWJ + _LIT(KTestString2,"\x0930\x094D\x200D\x0641Hello, 12 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); + aLayout->SetWrapWidth(533); + aText = KTestString1; + //This array defines the positions in the string where the lines should end + TInt lineEnds[2] = {14,67}; + //Verify that the line is broken in the correct places + VerifyLineBreak(aView, 2, lineEnds); + aText = KTestString2; + //Verify that the line is broken in the correct places + VerifyLineBreak(aView, 2, lineEnds); + } + +void TestTextViewL(TDes& aText, CTestGraphicsDevice* aDevice, + CTextLayout* aLayout, CTextView* aView, TDocModel* aDocModel) + { + test.Start(_L("Test fix for defect TET_5D7MCV")); + TET_5D7MCV_L(aText, aDevice, aView, aLayout); + test.Next(_L("Test fix for defect INC020746")); + INC020746_L(aText, aView); + test.Next(_L("Test fix for defect DEF021603")); + DEF021603_L(aText, aDevice, aView); + test.Next(_L("Test fix for defect DEF022229")); + DEF022229_L(aText, aDevice, aView); + test.Next(_L("Test fix for defect DEF035472")); + DEF035472_L(aText, aView); + test.Next(_L("Test fix for defect INC036005")); + INC036005_L(aText, aView); + test.Next(_L("Test XyPosToDocPosL outside horizontal bounds")); + TestCTextView_XyPosToDocPosL_ReturnsCorrectLine(aText, aView); + test.Next(_L("Test fix for defect INC036809")); + INC036809_L(aText, aView); + test.Next(_L("Test fix for defect DEF037255")); + DEF037255_L(aText, aView); + test.Next(_L("Test fix for defect INC037293")); + INC037293_L(aText, aView, aLayout); + test.Next(_L("Test fix for defect INC039567")); + INC039567_L(aText, aDevice, aView); + test.Next(_L("Test fix for defect DEF061143")); + DEF061143_L(aText, aLayout, aView); + test.Next(_L("Test fix for defect DEF063340")); + DEF063340_L(aText, aLayout, aView); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1533 Test clusters are not broken ")); + TestClusterBreaks(aText, aDevice, aLayout, aView, aDocModel); + test.Next(_L("Test fix for defect DEF065322")); + DEF065322_L(aText, aLayout, aView); + test.Next(_L("Test fix for defect DEF078967")); + DEF078967_L(aText, aDevice, aView); + test.Next(_L("Test fix for defect INC078304")); + INC078304_L(aText, aView); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1653 Test fix for defect INC080603 ")); + INC080603L(aText, aDevice, aLayout, aView); + test.Next(_L("Test fix for defect INC086257")); + INC086257_L(aText, aLayout, aView); + test.Next(_L("Test fix for defect INC085809")); + INC085809_L(aLayout, aView); + test.Next(_L("Test fix for defect INC092568")); + INC092568_L(aText, aLayout, aView); + test.Next(_L("Test fix for defect INC087637")); + INC087637_L(aText, aLayout, aView); + test.Next(_L("Test fix for defect INC092557/DEF094709")); + INC092257L(aText,aView); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-3422 Test fix for defect PDEF109450 ")); + PDEF109450_L(aText, aLayout, aView); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-3478 Test fix for defect PDEF107440 ")); + PDEF107440_L(aText, aLayout, aView); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3521 Test fix for defect INC108075 ")); + INC108075_L(aText, aLayout, aView); + test.End(); + } + +void DEF047281L(TDes& aText,CTextLayout* aLayout) + { + _LIT(KText, "ThisIsTheTestForDEF047281"); + aText.Zero(); + aText = KText; + + TSize aSize; + TInt KHeight=0xD; + aLayout->GetMinimumSizeL(200, aSize); + test(aSize.iHeight == KHeight); // height of 1 line + aLayout->GetMinimumSizeL(200, ETrue, aSize); + test(aSize.iHeight == KHeight); // height of 1 line + aLayout->GetMinimumSizeL(200, EFalse, aSize); + test(aSize.iHeight == KHeight*2); // height of 2 lines + } + + +void TestTextViewParagraphL(TDes& aText, CTestGraphicsDevice* aDevice, + CTextLayout* aLayout, CTextView* aView, CParaFormat* aParagraphFormat) + { + test.Start(_L("Test fix for defect INC038282")); + INC038282_L(aText, aDevice, aLayout, aView, aParagraphFormat); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1663 Test fix for defect DEF073913 ")); + DEF073913L(aText, aDevice, aView, aParagraphFormat); + test.Next(_L("Test fix for defect DEF047281")); + DEF047281L(aText, aLayout); + + test.End(); + } + +void RunTestTextViewL() + { + TBuf<100> text; + TDocModel docModel(text); + TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight); + CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); + CleanupStack::PushL(layout); + CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); + CleanupStack::PushL(device); + CTextView* view = CTextView::NewL(layout, displayRect, + device, device, 0, 0, 0); + CleanupStack::PushL(view); + TestTextViewL(text, device, layout, view, &docModel); + CParaFormat* paragraph = CParaFormat::NewLC(); + docModel.SetParagraphFormat(paragraph); + TestTextViewParagraphL(text, device, layout, view, paragraph); + CleanupStack::PopAndDestroy(paragraph); + CleanupStack::PopAndDestroy(view); + CleanupStack::PopAndDestroy(device); + CleanupStack::PopAndDestroy(layout); + } + +void RunDirectionalityTestL() + { + TBuf<100> text; + TDocModel docModel(text); + TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight); + CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); + CleanupStack::PushL(layout); + CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); + CleanupStack::PushL(device); + CTextView* view = CTextView::NewL(layout, displayRect, + device, device, 0, 0, 0); + CleanupStack::PushL(view); + DirectionalityTestL(text, device, layout, view); + CleanupStack::PopAndDestroy(view); + CleanupStack::PopAndDestroy(device); + CleanupStack::PopAndDestroy(layout); + } + +_LIT(KText_020329, "ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABC\x2029 ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ \x2029 ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ \x2029 ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ \x2029"); + +void INC020329TestL(TDes& aText, CTestGraphicsDevice* /*aDevice*/, CTextLayout* aLayout, CTextView* aView) + { + TSize smallSize(100, 40); + CTestGraphicsDevice* offScreenDevice = CTestGraphicsDevice::NewL(smallSize, 0); + CleanupStack::PushL(offScreenDevice); + CWindowGc* offScreenContext; + User::LeaveIfError(offScreenDevice->CreateContext(offScreenContext)); + CleanupStack::PushL(offScreenContext); + CTestTextView::SetOffScreenContext(aView, offScreenContext); + aView->EnableFlickerFreeRedraw(); + + // This test procedure checks for the presence of defect INC020329. + // To do this we need a small view (100x40) and two paragraphs where + // the first is 3.5 lines long. The defect results in the cursor + // being unable to move down a line to the second paragraph from + // the last half line of paragraph one. The cursor first jumps to end + // of paragraph (end of line 4) and then no further. This defect occurs + // when band formatting is configured. + + TTestCustomWrap wrapAnywhere; + TCursorPosition::TMovementType moveDown = TCursorPosition::EFLineDown; + TPoint scrollBy; + TTmDocPos cursorPos; + + // Setup view/layout state appropriate for the 1st part of test. + // Insert text, setup wrapping on any character + // Cursor doc pos is 0, formatting is EFFormatAllText not band + + aText = KText_020329; + aLayout->SetCustomWrap(&wrapAnywhere); + aLayout->DiscardFormat(); + aView->HandleGlobalChangeL(); + + // TEST: Cursor movement with WHOLE text formatting + + scrollBy = aView->SetDocPosL(0); // =(0,10) + + scrollBy = aView->SetDocPosL(22); // =(0,0) + + scrollBy = aView->MoveCursorL(moveDown, EFalse); // =(0,-12), EFLineDown + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // (32,1) + test(cursorPos.iPos==32); + + scrollBy = aView->MoveCursorL(moveDown, EFalse); // =(0,-13), EFLineDown + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // (39,1) + test(cursorPos.iPos==39); + + scrollBy = aView->MoveCursorL(moveDown, EFalse); // =(0,-13), EFLineDown + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // (49,1) + test(cursorPos.iPos==49); + + // Setup view/layout state appropriate for the 2nd part of test. + // Loose all formatting data from previous test + // Cursor doc pos is 0, formatting is EFFormatBand only + + aLayout->DiscardFormat(); + aLayout->SetAmountToFormat(CTextLayout::EFFormatBand); + test(aLayout->IsFormattingBand()); + aView->HandleGlobalChangeL(); + + // TEST: Same cursor movement above BUT with Band formatting + + scrollBy = aView->SetDocPosL(0); + + scrollBy = aView->SetDocPosL(22); + + scrollBy = aView->MoveCursorL(moveDown, EFalse); + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // (32,1) + test(cursorPos.iPos==32); + + scrollBy = aView->MoveCursorL(moveDown, EFalse); // Defect: =(0,0), EFLineEnd! + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // Defect: (36,1) + test(cursorPos.iPos==39); + + scrollBy = aView->MoveCursorL(moveDown, EFalse); // Defect: =(0,0), EFNoMovement! + test(moveDown==TCursorPosition::EFLineDown); + aView->GetCursorPos(cursorPos); // Defect: (36,1) + test(cursorPos.iPos==49); + + // Cleanup + aLayout->SetCustomWrap(0); + aText.Delete(0, aText.Length()); + + CTestTextView::SetOffScreenContext(aView, 0); + CleanupStack::PopAndDestroy(offScreenContext); + CleanupStack::PopAndDestroy(offScreenDevice); + } + +void RunTestINC020329L() + { + TBuf<200> text; + TDocModel docModel(text); + TRect displayRect(0, 0, 100, 40); + CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); + CleanupStack::PushL(layout); + CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); + CleanupStack::PushL(device); + CTextView* view = CTextView::NewL(layout, displayRect, + device, device, 0, 0, 0); + CleanupStack::PushL(view); + + INC020329TestL(text, device, layout, view); + + CleanupStack::PopAndDestroy(view); + CleanupStack::PopAndDestroy(device); + CleanupStack::PopAndDestroy(layout); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-1861 +@SYMTestCaseDesc Tests to ensure the correct operation of highlight extensions. +@SYMTestPriority High +@SYMTestActions Insert a paragraph of text, which contains at least 3 lines. Highlight different + sections with different highlight extension settings and compare resulting + screen with pre-defined bitmaps. +@SYMTestExpectedResults Screen and bitmaps should match +@SYMDEF PDEF085280 +*/ +void RunTestPDEF085280L() + { + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 360, 94)); + + //open the zipfile containing the comparison bitmaps + CTestBitmapZipFileExtractor* extract = CTestBitmapZipFileExtractor::NewLC( + _L("Z:\\test\\app-framework\\form\\input\\bitmaps.zip")); + + //add some text + bitMap->AppendL(_L("the quick brown fox jumped over the lazy dog. 1234567890?!*")); + bitMap->View()->HandleGlobalChangeL(); + + /********************************************************* + Note:- The commented "SaveFileL" code below was used to originally + generate the baseline test data. It has been left in and commented + so that if the data needs to be changed in the future, it will just + be case of temporarily moving the commenter from the "SaveFileL" + to the "test". + *********************************************************/ + + //Base-line test - no highlight extensions + bitMap->View()->SetDocPosL(27); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(0,0,0,0).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(0,0,0,0).bmp")))); + + //Shift highlight north-west + bitMap->View()->SetDocPosL(27); + bitMap->View()->SetHighlightExtensions(25,-25,12,-12); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(25,-25,12,-12).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(25,-25,12,-12).bmp")))); + + //Shift highlight south-east + bitMap->View()->SetDocPosL(27); + bitMap->View()->SetHighlightExtensions(-25,25,-12,12); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(-25,25,-12,12).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(-25,25,-12,12).bmp")))); + + //Shift highlight north-east + bitMap->View()->SetDocPosL(27); + bitMap->View()->SetHighlightExtensions(-25,25,12,-12); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(-25,25,12,-12).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(-25,25,12,-12).bmp")))); + + //Shift highlight south-west + bitMap->View()->SetDocPosL(27); + bitMap->View()->SetHighlightExtensions(25,-25,-12,12); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(25,-25,-12,12).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(25,-25,-12,12).bmp")))); + + //Make extensions huge and highlight one character - highlight blobs over nearly whole screen + bitMap->View()->SetDocPosL(29); + bitMap->View()->SetHighlightExtensions(120,100,15,15); + bitMap->View()->SetDocPosL(30,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(120,100,15,15).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(120,100,15,15).bmp")))); + + //Precursor to highlight overlap - skinny highlight through text + bitMap->View()->SetDocPosL(8); + bitMap->View()->SetHighlightExtensions(0,0,-5,-5); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(0,0,-5,-5).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(0,0,-5,-5).bmp")))); + + //Highlight overlap - extension top and bottom overlaps between lines + bitMap->View()->SetDocPosL(8); + bitMap->View()->SetHighlightExtensions(0,0,10,10); + bitMap->View()->SetDocPosL(31,ETrue); +// bitMap->SaveFileL(_L("c:\\SetHighlightExtensions(0,0,10,10).bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("SetHighlightExtensions(0,0,10,10).bmp")))); + + CleanupStack::PopAndDestroy(2,bitMap); + } + +void PDEF097387TestL(CRichText* aRichText, CTextView* aTextView) + { + _LIT(KTest,"0123456789"); + TPtrC text1(KTest().Ptr(), KTest().Length()); + CTextLayout* layout = const_cast(aTextView->Layout()); + aRichText->Reset(); + aRichText->InsertL(0, text1); + + // set line ascent and descent so baseline will be outside line rect + aTextView->SetExcessHeightRequired(3); + layout->SetMinimumLineDescent(0); + aTextView->FormatTextL(); + + // scroll through the document and test that the cursor goes to the right position + // none of these tests should fail. + TTmDocPos pos(9, ETrue); + aTextView->SetDocPosL(pos); + TCursorPosition::TMovementType move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 8); + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 7); + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 6); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 5); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 4); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 3); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 2); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 1); + move = TCursorPosition::EFLeft; + aTextView->MoveCursorL(move, EFalse); + aTextView->GetCursorPos(pos); + test(pos.iPos == 0); + } + + +void RunPDEF097387TestL(CFbsScreenDevice* aDevice) + { + CParaFormat* paraFormat = CParaFormat::NewLC(); + TParaFormatMask paraFormatMask; + // set up paragraph propeties + paraFormat->iHorizontalAlignment=CParaFormat::ELeftAlign; + paraFormatMask.SetAttrib(EAttAlignment); + paraFormat->iLineSpacingInTwips=21; + paraFormatMask.SetAttrib(EAttLineSpacing); + paraFormat->iLineSpacingControl=CParaFormat::ELineSpacingExactlyInPixels; + paraFormatMask.SetAttrib(EAttLineSpacingControl); + CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL(paraFormat,paraFormatMask); + CleanupStack::PushL(paraFormatLayer); + CCharFormatLayer* charFormat = CCharFormatLayer::NewL(); + CleanupStack::PushL(charFormat); + CRichText* text = CRichText::NewL(paraFormatLayer, charFormat); + CleanupStack::PushL(text); + TRect displayRect(0, 0, 70, 42); + CTextLayout* layout = CTextLayout::NewL(text, displayRect.Width()); + CleanupStack::PushL(layout); + CTextView* view = CTextView::NewL(layout, displayRect, + aDevice, aDevice, 0, 0, 0); + CleanupStack::PushL(view); + //Run test + PDEF097387TestL(text, view); + CleanupStack::PopAndDestroy(view); + CleanupStack::PopAndDestroy(layout); + CleanupStack::PopAndDestroy(text); + CleanupStack::PopAndDestroy(charFormat); + CleanupStack::PopAndDestroy(paraFormatLayer); + CleanupStack::PopAndDestroy(paraFormat); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-3162 +@SYMTestCaseDesc Tests to ensure the correct cursor position is maintained when scrolling through a document +@SYMTestPriority High +@SYMTestActions Creates a view and layout whose will have baselines outside the rect. of the line. + It then tests that when scrolling through the document that the correct cursor position is maintained +@SYMTestExpectedResults Cursor position should be maintained correctly when scrolling through document. +@SYMDEF PDEF097387 +*/ +_LIT(KTestFont, "ClearlyU"); +void SetupAndRunPDEF097387TestL() + { + TInt error; + CFbsScreenDevice* screenDevice = 0; + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16M)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MA)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MU)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor64K)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor4K)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor256)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray256)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray16)); + if (error == KErrNotSupported) + TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray4)); + if (error == KErrNotSupported) + screenDevice = CFbsScreenDevice::NewL(0,EGray2); + + CleanupStack::PushL(screenDevice); + screenDevice->ChangeScreenDevice(0); + screenDevice->SetAutoUpdate(ETrue); + CGraphicsContext* gc; + User::LeaveIfError(screenDevice->CreateContext(gc)); + CleanupStack::PushL(gc); + TFontSpec fs(KTestFont, 20); + CFont* font; + User::LeaveIfError(screenDevice->GetNearestFontInPixels(font, fs)); + TFontSpec fontSpec = font->FontSpecInTwips(); + if(0 != fontSpec.iTypeface.iName.Compare(KTestFont)) + { + // Test font not found. + User::Leave(KErrNotFound); + } + TRAP(error, RunPDEF097387TestL(screenDevice)); + CleanupStack::PopAndDestroy(gc); + CleanupStack::PopAndDestroy(screenDevice); + User::LeaveIfError(error); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-3241 +@SYMTestCaseDesc Test to ensure that invalid rectangle of the text view is being set + correctly after removing of a line of text +@SYMTestPriority High +@SYMTestActions Creates a text document and view and layout objects for it. + Then appends text to the document one character at a + time until text starts to wrap to the second line. At this point + the last character is being deleted, so that the text fits into + one line once again. Then we get the invalid rectangle of the view + and check that this rectangle includes the area where the second line + used to be. +@SYMTestExpectedResults The location of the second line of text should be included into + invalid area. +@SYMDEF PDEF098569 +*/ +void RunPDEF098569TestL() + { + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(); + + bitMap->AppendL(_L("a")); //insert first character to calculate first line's height + bitMap->View()->HandleCharEditL(); + TInt FirstLineBottom = CTestTextView::GetFormattedHeight(bitMap->View()); + //perform appending loop + do + { + bitMap->AppendL(_L("a")); + bitMap->View()->HandleCharEditL(); + } + while (CTestTextView::GetFormattedHeight(bitMap->View())==FirstLineBottom ); + TInt SecondLineBottom = CTestTextView::GetFormattedHeight(bitMap->View()); + + //delete last character + TInt last = bitMap->Layout()->DocumentLength() - 1; + TCursorSelection selection=TCursorSelection(last,last); + bitMap->DocModel()->DelSetInsertCharFormatL(selection.LowerPos(),1); + bitMap->View()->HandleCharEditL(CTextLayout::EFLeftDelete,EFalse); + + //get the invalid area of the view object + TRect invalid_rect = CTestTextView::GetInvalidRect(bitMap->View()); + //check that entire rectangle of the second line lies within the invalid area + test(invalid_rect.iTl.iY<=FirstLineBottom && invalid_rect.iBr.iY>=SecondLineBottom); + + CleanupStack::PopAndDestroy(bitMap); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-3345 +@SYMTestCaseDesc Test to ensure that implicit redraw is disabled until an external + draw is performed. +@SYMTestPriority High +@SYMTestActions Create a view and layout object. + Check BeginDraw() and EndDraw() are disabled. + Do external draw. + Check BeginDraw() and EndDraw() are enabled. +@SYMTestExpectedResults Implicit redraw should be disabled until external draw + is performed. +@SYMDEF INC099424 +*/ +void RunINC099424TestL() + { + TBuf<100> text; + TDocModel docModel(text); + TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight); + CTextLayout* layout = CTextLayout::NewL(&docModel, displayRect.Width()); + CleanupStack::PushL(layout); + CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect.Size(), 0); + CleanupStack::PushL(device); + CTextView* view = CTextView::NewL(layout, displayRect, + device, device, 0, 0, 0); + CleanupStack::PushL(view); + + // This test uses CTextLayout::BeginRedrawCalled() to determine whether or not + // CTextLayout::BeginRedraw() and CTextLayout::EndRedraw() are enabled. + // CTextLayout::BeginRedrawCalled() returns ETrue if CTextLayout::iBeginRedrawCount + // is greater than 0. Otherwise EFalse. + // CTextLayout::BeginRedraw() and CTextLayout::EndRedraw() increments or + // decrements iBeginRedrawCount respectively if they are enabled. + + TRect rect(0,0,0,0); + + // Check iBeginRedrawCount is 0 initially. + // If next line is successful then iBeginRedrawCount must be 0 + // because it is initialised to this on construction. + test(layout->BeginRedrawCalled() == EFalse); + + // Check begin and end functions are disabled + layout->BeginRedraw(rect); + test(layout->BeginRedrawCalled() == EFalse); + // Doing this many times in case enabled and the CTextLayout::iBeginRedrawCount + // was already negative. + for(TInt i = 0; i < 20; i++) + layout->EndRedraw(); + test(layout->BeginRedrawCalled() == EFalse); + + // Enable begin and end functions with external draw. + // BeginRedrawCalled returns EFalse because DrawL call both begin and end + // which increments then decrements iBeginRedrawCount + view->DrawL(rect); + test(layout->BeginRedrawCalled() == EFalse); + + // Test begin and end functions are enabled individually + layout->BeginRedraw(rect); + test(layout->BeginRedrawCalled() != EFalse); + layout->EndRedraw(); + test(layout->BeginRedrawCalled() == EFalse); + + // tidy up + CleanupStack::PopAndDestroy(view); + CleanupStack::PopAndDestroy(device); + CleanupStack::PopAndDestroy(layout); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-3754 +@SYMTestCaseDesc A further test to ensure the correct operation of highlight extensions. +@SYMTestPriority High +@SYMTestActions Fill viewable area with multiple short lines of text. The next line + to scroll into view should be a longer line of text followed by more + short lines. Ensure highlighting and band formatting are on. Select + the text from the beginning of the document until after the short line + directly following the long line. +@SYMTestExpectedResults Screen and bitmaps should match - the whole of the long line should be + highlighted. +@SYMDEF INC109995 +*/ +void RunINC109995TestL() + { + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(); + + //open the zipfile containing the comparison bitmaps + CTestBitmapZipFileExtractor* extract = CTestBitmapZipFileExtractor::NewLC( + _L("Z:\\test\\app-framework\\form\\input\\bitmaps.zip")); + + //set up test conditions + bitMap->Layout()->SetAmountToFormat(); + bitMap->Layout()->SetHighlightExtensions(0,0,-1,-1); + + // the offscreen bitmap. This looks like an unexpected feature in its' own right. The visual + // effect, in this case, is that out of the three visible lines, only the + // second line gets updated when scrolling with highlighting on. + bitMap->View()->DisableFlickerFreeRedraw(); + + //insert some text + bitMap->AppendL(_L("11111\x2029")); + bitMap->AppendL(_L("22222\x2029")); + bitMap->AppendL(_L("33333\x2029")); + bitMap->AppendL(_L("aaaaaaaaaaaaaaaaa\x2029")); + bitMap->AppendL(_L("44444\x2029")); + bitMap->AppendL(_L("55555\x2029")); + bitMap->View()->HandleGlobalChangeL(); + + //highlight the text + TCursorPosition::TMovementType lineDown = TCursorPosition::EFLineDown; + bitMap->View()->SetDocPosL(0); + bitMap->View()->MoveCursorL(lineDown,ETrue); + bitMap->View()->MoveCursorL(lineDown,ETrue); + bitMap->View()->MoveCursorL(lineDown,ETrue); + bitMap->View()->MoveCursorL(lineDown,ETrue); + bitMap->View()->MoveCursorL(lineDown,ETrue); + +// bitMap->SaveFileL(_L("c:\\ScrolledHighlight.bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("ScrolledHighlight.bmp")))); + + CleanupStack::PopAndDestroy(2,bitMap); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4003 +@SYMTestCaseDesc Test to ensure correct cursor movement between 2 lines containing a pictures. +@SYMTestPriority High +@SYMTestActions Inserts pictures until the line breaks, then moves the cursor leftwards for + LTR text, and rightwards for RTL text, starting from the end of the 2nd line, + testing the MovementType that has taken place and the position of the cursor + after the movement, especially when the cursor moves to the first line. +@SYMTestExpectedResults Resulting document position are where expected. +@SYMDEF PDEF112004 +*/ +void RunPDEF112004TestL() + { + + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 140, 185)); + + //create the picture to insert (this one is a red box) + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,400)); + + //Add lots of pictures until we get a line break, and then format the view + // Just to be sure, add one picture after we get a line break. + TInt numLines = 0; + TInt pos = 0; + for (;;) + { + if (numLines > 1) + break; + bitMap->AppendL(pic); + numLines = bitMap->View()->Layout()->NumFormattedLines(); + pos++; + } + bitMap->View()->HandleGlobalChangeL(); + + // Place the cursor at the end of the last picture added and start moving the cursor left. + TTmDocPos thisPos; + bitMap->View()->GetCursorPos(thisPos); + TCursorPosition::TMovementType type = TCursorPosition::EFLeft; + + // Docuemnt position is already at the end, but it is Trailing. Make it Leading and set it. + TTmDocPosSpec::TType docPosType = TTmDocPosSpec::ELeading; + TTmDocPosSpec docPos; + docPos.iPos = pos;//thisPos.iPos; + docPos.iType = docPosType; + + bitMap->View()->SetDocPosL(docPos); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 4); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 3 && type == TCursorPosition::EFLeft); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 3 && type == TCursorPosition::EFLeft); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 2 && type == TCursorPosition::EFLeft); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 1 && type == TCursorPosition::EFLeft); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 1 && type == TCursorPosition::EFLeft); + + /** Now test the same for pictures in a RTL paragraph. + Put some RTL text so that the paragraph changes to a RTL paragraph. + Then move the cursor right, through the pictures */ + bitMap->AppendL(_L("\x630")); + bitMap->View()->HandleGlobalChangeL(); + + docPos.iPos = bitMap->View()->Layout()->DocumentLength(); + docPos.iType = TTmDocPosSpec::ELeading; + bitMap->View()->SetDocPosL(docPos); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == 5); + + type = TCursorPosition::EFRight; + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 4 && type == TCursorPosition::EFRight); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 3 && type == TCursorPosition::EFRight); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 3 && type == TCursorPosition::EFRight); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 2 && type == TCursorPosition::EFRight); + // Move the cursor and test if it has moved + bitMap->View()->MoveCursorL(type, EFalse); + bitMap->View()->GetCursorPos(thisPos); + + test(thisPos.iPos == 1 && type == TCursorPosition::EFRight); + + CleanupStack::Pop(pic); + CleanupStack::PopAndDestroy(1); + } + + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4001 +@SYMTestCaseDesc Test to ensure correct picture selection and cursor movement in + line of text containing a picture. +@SYMTestPriority High +@SYMTestActions Writes text wrapping to five lines and inserts pictures in the + middle three lines and sets picture text alignment other than + baseline, then tests that various cursor movements result in the + correct doc positions. Also checks that a frame is drawn around the + centre picture when expected. +@SYMTestExpectedResults Resulting document position are where expected; frame drawn correctly +@SYMDEF INC112423 +*/ +void RunINC112423TestVariantsL(const TDesC& aComparisonFileName, const TDesC& aText, + TFontPresentation::TAlignment aAlignment, TCursorPosition::TMovementType aMove) + { + //open the zipfile containing the comparison bitmaps + CTestBitmapZipFileExtractor* extract = CTestBitmapZipFileExtractor::NewLC( + _L("Z:\\test\\app-framework\\form\\input\\bitmaps.zip")); + + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 160, 185), TCharFormat(_L("ClearlyU"),1)); + + //create the picture to insert (this one is a red box) + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,400)); //pic needs to be higher than text height to catch all aligments + + //insert mixture of text and pictures + bitMap->AppendL(aText); + bitMap->AppendL(aText); + bitMap->AppendL(aText); + TInt firstPicPos = bitMap->DocModel()->DocumentLength(); //get cursor pos of first picture + bitMap->AppendL(pic); + bitMap->View()->HandleGlobalChangeL(); + + //change picture alignment + TInt docLength = bitMap->DocModel()->DocumentLength(); + TCursorSelection selection(docLength, docLength-1); + bitMap->View()->SetSelectionL(selection); + TCharFormat format; + format.iFontPresentation.iPictureAlignment = aAlignment; + TCharFormatMask mask; + mask.SetAttrib(EAttFontPictureAlignment); + bitMap->DocModel()->ApplyCharFormatL(format, mask, selection.LowerPos(), 1); + bitMap->View()->HandleRangeFormatChangeL(selection,EFalse); + bitMap->View()->CancelSelectionL(); + + //insert more text and pictures + bitMap->AppendL(aText); + bitMap->AppendL(aText); + TInt secondPicPos = bitMap->DocModel()->DocumentLength(); //get cursor pos of second picture + bitMap->AppendL(pic); + bitMap->AppendL(aText); + bitMap->AppendL(aText); + TInt thirdPicPos = bitMap->DocModel()->DocumentLength(); //get cursor pos of third picture + bitMap->AppendL(pic); + bitMap->AppendL(aText); + bitMap->AppendL(aText); + bitMap->AppendL(aText); + bitMap->View()->HandleGlobalChangeL(); + + //now move cursor over each picture and test for correct selection + TTmDocPos thisPos; + bitMap->View()->SetDocPosL(firstPicPos); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == firstPicPos); //cursor should be over the first picture + bitMap->View()->SetDocPosL(secondPicPos); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == secondPicPos); //cursor should be over the second picture +// bitMap->SaveFileL(aComparisonFileName); //and a frame should be drawn over it + test(bitMap->CompareL(extract->BitmapFileL(aComparisonFileName))); + bitMap->View()->SetDocPosL(thirdPicPos); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == thirdPicPos); //cursor should be over the third picture + + //Test up/down cursor movement + TTmDocPos lastPos; + TBool leadingEdge = aMove == TCursorPosition::EFRight; + TCursorPosition::TMovementType move = TCursorPosition::EFLineDown; + bitMap->View()->SetDocPosL(0); //go to top of document + bitMap->View()->GetCursorPos(thisPos); + lastPos = thisPos; + TTmDocPos firstLineHome(thisPos.iPos, leadingEdge); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos > lastPos.iPos); //cursor should have moved down + TTmDocPos secondLineHome = lastPos = thisPos; + TTmDocPos firstLineEnd(secondLineHome.iPos - 1, leadingEdge); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos > lastPos.iPos); //cursor should have moved down again + TTmDocPos thirdLineHome = lastPos = thisPos; + TTmDocPos secondLineEnd(thirdLineHome.iPos - 1, leadingEdge); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos > lastPos.iPos); //cursor should have moved down again + TTmDocPos fourthLineHome = lastPos = thisPos; + TTmDocPos thirdLineEnd(fourthLineHome.iPos - 1, leadingEdge); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos > lastPos.iPos); //cursor should have moved down again + TTmDocPos fifthLineHome = lastPos = thisPos; + TTmDocPos fourthLineEnd(fifthLineHome.iPos - 1, leadingEdge); + bitMap->View()->SetDocPosL(bitMap->DocModel()->DocumentLength()); //go to end of document + bitMap->View()->GetCursorPos(thisPos); + lastPos = thisPos; + TTmDocPos fifthLineEnd(thisPos.iPos, leadingEdge); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineUp, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos < lastPos.iPos); //cursor should have moved up + lastPos = thisPos; + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos < lastPos.iPos); //cursor should have moved up again + lastPos = thisPos; + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos < lastPos.iPos); //cursor should have moved up again + lastPos = thisPos; + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos < lastPos.iPos); //cursor should have moved up again + + //Test home/end cursor movement + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineBeg, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == firstLineHome); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineEnd, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == firstLineEnd); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineDown, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineBeg, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == secondLineHome); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineEnd, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == secondLineEnd); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineDown, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineBeg, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == thirdLineHome); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineEnd, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == thirdLineEnd); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineDown, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineBeg, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fourthLineHome); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineEnd, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fourthLineEnd); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineDown, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineBeg, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fifthLineHome); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFLineEnd, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fifthLineEnd); + + //Test at line extremes cursor movement left/right wraps to next/previous line + move = aMove == TCursorPosition::EFRight? TCursorPosition::EFLeft : TCursorPosition::EFRight; + bitMap->View()->SetDocPosL(firstLineEnd); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == secondLineHome); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == firstLineEnd); + bitMap->View()->SetDocPosL(secondLineEnd); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == thirdLineHome); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == secondLineEnd); + bitMap->View()->SetDocPosL(thirdLineEnd); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fourthLineHome); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == thirdLineEnd); + bitMap->View()->SetDocPosL(fourthLineEnd); + bitMap->View()->MoveCursorL(aMove, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fifthLineHome); + bitMap->View()->MoveCursorL(move, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos == fourthLineEnd); + + //Test pageup/pagedown + bitMap->View()->MoveCursorL(move = TCursorPosition::EFPageUp, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFPageUp, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == firstLineHome.iPos); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFPageDown, EFalse); + bitMap->View()->MoveCursorL(move = TCursorPosition::EFPageDown, EFalse); + bitMap->View()->GetCursorPos(thisPos); + test(thisPos.iPos == fifthLineEnd.iPos); + + CleanupStack::Pop(pic); + CleanupStack::PopAndDestroy(2, extract); + } +void RunINC112423TestL() + { + RunINC112423TestVariantsL(_L("alignArabicBot.bmp"), _L("\x630\x630\x630\x630\x630\x630\x630\x630 "), + TFontPresentation::EAlignBottom, TCursorPosition::EFLeft); + RunINC112423TestVariantsL(_L("alignArabicCen.bmp"), _L("\x630\x630\x630\x630\x630\x630\x630\x630 "), + TFontPresentation::EAlignCentered, TCursorPosition::EFLeft); + RunINC112423TestVariantsL(_L("alignArabicTop.bmp"), _L("\x630\x630\x630\x630\x630\x630\x630\x630 "), + TFontPresentation::EAlignTop, TCursorPosition::EFLeft); + RunINC112423TestVariantsL(_L("alignLatinBot.bmp"), _L("aaaaaaaa "), + TFontPresentation::EAlignBottom, TCursorPosition::EFRight); + RunINC112423TestVariantsL(_L("alignLatinCen.bmp"), _L("aaaaaaaa "), + TFontPresentation::EAlignCentered, TCursorPosition::EFRight); + RunINC112423TestVariantsL(_L("alignLatinTop.bmp"), _L("aaaaaaaa "), + TFontPresentation::EAlignTop, TCursorPosition::EFRight); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4005 +@SYMTestCaseDesc Given the usecase condition, test to ensure there is no highlighted + character following CTextView::CancelSelectionL(); +@SYMTestPriority High +@SYMTestActions Create an empty document and append one character to it. Select this + character in the document and then cancel the selection. +@SYMTestExpectedResults Screen and bitmap should match - the character should not be highlighted. +@SYMDEF PDEF114862 +*/ +void RunPDEF114862TestL() + { + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(); + + //open the zipfile containing the comparison bitmaps + CTestBitmapZipFileExtractor* extract = CTestBitmapZipFileExtractor::NewLC( + _L("Z:\\test\\app-framework\\form\\input\\bitmaps.zip")); + + //set up test conditions + bitMap->AppendL(_L("@")); + bitMap->View()->SetSelectionL(TCursorSelection(1,0)); + bitMap->View()->CancelSelectionL(); + +// bitMap->SaveFileL(_L("c:\\MailboxWizard.bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("MailboxWizard.bmp")))); + + CleanupStack::PopAndDestroy(2, bitMap); + } + + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4008 +@SYMTestCaseDesc Make sure any highlighting is properly canceled when moving + the cursor without drag. +@SYMTestPriority High +@SYMTestActions Write some text to an empty document, highlight part of the text + and then move the cursor without selecting text. +@SYMTestExpectedResults No text should be highlighted following cursor move. +@SYMDEF INC116681 +*/ +void RunINC116681TestL() + { + //open the zipfile containing the comparison bitmaps + CTestBitmapZipFileExtractor* extract = CTestBitmapZipFileExtractor::NewLC( + _L("Z:\\test\\app-framework\\form\\input\\bitmaps.zip")); + + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(); + + //setup test conditions + bitMap->AppendL(_L("SomeText")); // enter some text + bitMap->View()->SetSelectionL(TCursorSelection(5,1)); //highlight some of it + TCursorPosition::TMovementType moveRight = TCursorPosition::EFRight; + bitMap->View()->MoveCursorL(moveRight, EFalse); //move cursor with drag off +// bitMap->SaveFileL(_L("c:\\INC116681.bmp")); + test(bitMap->CompareL(extract->BitmapFileL(_L("INC116681.bmp")))); + + CleanupStack::PopAndDestroy(2); + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-4018 +@SYMTestCaseDesc Performance test for formatting document with many pictures and test. +@SYMTestPriority Medium +@SYMTestActions Add a lot pictures separated by commas and time the operation. +@SYMTestExpectedResults The formatting should not take longer than the specified timeout. +@SYMDEF PDEF123018 +*/ +void RunPDEF123018TestL() + { + // define a time unit for the performance test timeout + const TInt KOneSecond = 1000000; + //create editor/bitmap + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 140, 185)); + + //create any old picture to insert + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,400)); + + // Add some text and pictures, and time it. + // Appending a picture will invoke the formatting. + // Many calls should cause a lot of reformatting which will show the performance. + TTime startTime; + startTime.HomeTime(); + for (TInt i = 0; i < 50; i++) + { + bitMap->AppendL(pic); + bitMap->AppendL(_L(",")); + } + TTime endTime; + endTime.HomeTime(); + TTimeIntervalMicroSeconds diff = endTime.MicroSecondsFrom(startTime); + + // Different performance timeouts for emulator / hardware. + TBuf<100> buf; + #if defined __WINS__ || defined __WINSCW__ + buf.Format( _L("Testing on emulator: Timeout = 3 seconds; finished in %d microseconds"), diff.Int64() ); + RDebug::Print( buf ); + test(diff < 3*KOneSecond); + #elif defined __ARMCC__ + // for naviengine SMP, the timeout should be 150% time needed compare with H4, 25m for H4, 38m for naviengine + buf.Format( _L("Testing on hardware: Timeout = 38 seconds; finished in %d microseconds"), diff.Int64() ); + RDebug::Print( buf ); + test(diff < 38*KOneSecond); + #endif + + // Cleanup. + CleanupStack::Pop(pic); + CleanupStack::PopAndDestroy(1); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4019 +@SYMTestCaseDesc When a line in a document is filled with nothing but pictures + and the picture alignment is set to anything other than baseline + then the cursor should be correctly placed on that line. +@SYMTestPriority Medium +@SYMTestActions Fill a line up with pictures so that it wraps, place the cursor + at the beginning of that line and measure the line metrics. +@SYMTestExpectedResults The line metrics should be correct in order to place the cursor + in the expected position. +@SYMDEF DEF122198 +*/ +void RunDEF122198_1TestL() //picture is taller than font height + { + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 160, 80)); + + //create the picture to insert (this one is a red box) + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,400)); + + //insert line of pictures + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->View()->HandleGlobalChangeL(); + + //change picture alignment + TCursorSelection selection(0, bitMap->DocModel()->DocumentLength()); + bitMap->View()->SetSelectionL(selection); + TCharFormat format; + format.iFontPresentation.iPictureAlignment = TFontPresentation::EAlignBottom; + TCharFormatMask mask; + mask.SetAttrib(EAttFontPictureAlignment); + bitMap->DocModel()->ApplyCharFormatL(format, mask, selection.LowerPos(), selection.Length()); + bitMap->View()->HandleRangeFormatChangeL(selection,EFalse); + bitMap->View()->CancelSelectionL(); + + // I could find no way of getting a bitmap screenshot which showed the cursor. + // All attempts - including rewriting bitmapDoc to use Wserv - failed. + // Therefore, the best I can do is test the resulting line information against + // which the position of the cursor is drawn. + TTmPosInfo2 posInfo; + TTmLineInfo currentLineInfo; + TTmDocPos docPos; + bitMap->View()->SetDocPosL(0,EFalse); + bitMap->View()->GetCursorPos(docPos); + bitMap->Layout()->FindDocPos(docPos, posInfo, ¤tLineInfo); + + test(posInfo.iEdge.iY==33); + test(currentLineInfo.iBaseline==33); + + //change picture alignment and test again + format.iFontPresentation.iPictureAlignment = TFontPresentation::EAlignCentered; + bitMap->View()->SetSelectionL(selection); + bitMap->DocModel()->ApplyCharFormatL(format, mask, selection.LowerPos(), selection.Length()); + bitMap->View()->HandleRangeFormatChangeL(selection,EFalse); + bitMap->View()->CancelSelectionL(); + bitMap->Layout()->FindDocPos(docPos, posInfo, ¤tLineInfo); + + test(posInfo.iEdge.iY==29); + test(currentLineInfo.iBaseline==29); + + //change picture alignment and test again + format.iFontPresentation.iPictureAlignment = TFontPresentation::EAlignTop; + bitMap->View()->SetSelectionL(selection); + bitMap->DocModel()->ApplyCharFormatL(format, mask, selection.LowerPos(), selection.Length()); + bitMap->View()->HandleRangeFormatChangeL(selection,EFalse); + bitMap->View()->CancelSelectionL(); + bitMap->Layout()->FindDocPos(docPos, posInfo, ¤tLineInfo); + + test(posInfo.iEdge.iY==25); + test(currentLineInfo.iBaseline==25); + + CleanupStack::PopAndDestroy(2); + } + +void RunDEF122198_2TestL() //picture is shorter than font height + { + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(TRect(0, 0, 160, 80)); + + //create the picture to insert (this one is a red box) + CTestPicture* pic = new(ELeave)CTestPicture(); + CleanupStack::PushL(pic); + pic->SetSizeInTwips(TSize(400,200)); + + //insert line of pictures + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->AppendL(pic); + bitMap->View()->HandleGlobalChangeL(); + + //change picture alignment + TCursorSelection selection(0, bitMap->DocModel()->DocumentLength()); + bitMap->View()->SetSelectionL(selection); + TCharFormat format; + format.iFontPresentation.iPictureAlignment = TFontPresentation::EAlignBottom; + TCharFormatMask mask; + mask.SetAttrib(EAttFontPictureAlignment); + bitMap->DocModel()->ApplyCharFormatL(format, mask, selection.LowerPos(), selection.Length()); + bitMap->View()->HandleRangeFormatChangeL(selection,EFalse); + bitMap->View()->CancelSelectionL(); + + // I could find no way of getting a bitmap screenshot which showed the cursor. + // All attempts - including rewriting bitmapDoc to use Wserv - failed. + // Therefore, the best I can do is test the resulting line information against + // which the position of the cursor is drawn. + TTmPosInfo2 posInfo; + TTmLineInfo currentLineInfo; + TTmDocPos docPos; + bitMap->View()->SetDocPosL(0,EFalse); + bitMap->View()->GetCursorPos(docPos); + bitMap->Layout()->FindDocPos(docPos, posInfo, ¤tLineInfo); + test(posInfo.iEdge.iY==25); + test(currentLineInfo.iBaseline==25); + + CleanupStack::PopAndDestroy(2); + } + +/** +@SYMTestCaseID SYSLIB-FORM-CT-4020 +@SYMTestCaseDesc When a zero-width character precedes the current doc position, + pressing backspace should not delete everything back to the + beginning of the document. +@SYMTestPriority Medium +@SYMTestActions Recreate the reported usecase and test for the correct action, + then perform a similar test for every zero-width character. +@SYMTestExpectedResults The selection anchor point should be at the correct position + in each case. +@SYMDEF INC123427 +*/ +void RunINC123427TestL() + { + // *** First test actual defect usecase *** + CTestBitmapFile* bitMap = CTestBitmapFile::NewLC(); + bitMap->AppendL(_L("a meeting\x2029")); + bitMap->AppendL(_L("\x200E\x0038:00 am - 8:00 am 18/06/2008\x2029")); + bitMap->AppendL(_L("\x200Ehere\x2029")); + bitMap->AppendL(_L("\x2029")); + bitMap->AppendL(_L("\x200ERepeats daily:\x2029")); + bitMap->AppendL(_L("\x200E\x0046rom 17/06/2008\x2029")); + bitMap->View()->HandleGlobalChangeL(); + + bitMap->View()->SetDocPosL(48); + TCursorSelection selection = bitMap->View()->GetBackwardDeletePositionL(); + test(selection.iAnchorPos==46); + + // *** Now reset the doc and test for all zero-width characters *** + bitMap->DocModel()->Reset(); + bitMap->AppendL(_L("->")); //something valid to start + TText charVal; + TUint stringIndex=0; + TText string[70]; + + // create a continuous line containing every zero width character: + // add C0, C1 controls + for (charVal=0x1; charVal<0x9; charVal++) + { + string[stringIndex++] = charVal; + } + string[stringIndex++] = 0xB; + for (charVal=0xD; charVal<0x20; charVal++) + { + string[stringIndex++] = charVal; + } + string[stringIndex++] = 0x7F; + string[stringIndex++] = 0x81; + string[stringIndex++] = 0x8F; + string[stringIndex++] = 0x90; + + // add layout controls & invisible operators + for (charVal=0x200B; charVal<0x2010; charVal++) + { + string[stringIndex++] = charVal; + } + // U+205F is not zero width + for (charVal=0x2060; charVal<0x2065; charVal++) + { + string[stringIndex++] = charVal; + } + for (charVal=0x206A; charVal<0x2070; charVal++) + { + string[stringIndex++] = charVal; + } + + // add specials + for (charVal=0xFFF9; charVal<0xFFFD; charVal++) + { + string[stringIndex++] = charVal; + } + + string[stringIndex] = 0; // zero terminate + + TPtrC temp; + TTmCharFormat temp2; + bitMap->AppendL(TBuf<70>(string)); + bitMap->AppendL(_L("<")); + bitMap->View()->HandleGlobalChangeL(); + + // cycle through the doc at each zerowidth char and test correct backward + // delete position. This test would have passed without the fix + TUint startpos=2; + for (TUint i=startpos; iView()->SetDocPosL(i); + selection = bitMap->View()->GetBackwardDeletePositionL(); + test(selection.iAnchorPos==1); + } + + // same test again but with no valid characters at the start. + // This test would have passed without the fix + bitMap->DocModel()->Reset(); + bitMap->AppendL(TBuf<70>(string)); + bitMap->View()->HandleGlobalChangeL(); + for (TUint i=0; iView()->SetDocPosL(i); + selection = bitMap->View()->GetBackwardDeletePositionL(); + test(selection.iAnchorPos==0); + } + + // same test again but with a complete line of visible characters before the + // line of invisible ones. This test would *not* have passed without the fix + bitMap->DocModel()->Reset(); + bitMap->AppendL(_L("0123456789\x2029")); + bitMap->AppendL(_L("0123456789\x2029")); + bitMap->AppendL(TBuf<70>(string)); + bitMap->View()->HandleGlobalChangeL(); + startpos=23; + for (TUint i=startpos; iView()->SetDocPosL(i); + selection = bitMap->View()->GetBackwardDeletePositionL(); + test(selection.iAnchorPos==21); + } + + CleanupStack::PopAndDestroy(); + } + +TInt E32Main() + { + test.Title(); + static CTrapCleanup* TrapCleanup = CTrapCleanup::New(); + TInt error = RFbsSession::Connect(); + if (error == KErrNotFound) + { + FbsStartup(); + error = RFbsSession::Connect(); + } + CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; + CActiveScheduler::Install(scheduler); + test(error == KErrNone); + test.Start(_L("CTextView tests")); + TRAP(error, RunTestTextViewL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4014 RunPDEF118831TestL ")); + TRAP(error, RunPDEF118831TestL()); + test(error == KErrNone); + test.Next(_L("Directionality tests")); + TRAP(error, RunDirectionalityTestL()); + test(error == KErrNone); + test.Next(_L("Inline offsets test")); + TRAP(error, CTestTextView::TestMemberOffsetsL()); + test(error == KErrNone); + TRAP(error, CTestTextLayout::TestMemberOffsetsL()); + test(error == KErrNone); + test.Next(_L("Test fix for defect INC020329")); + TRAP(error, RunTestINC020329L()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-1861 Test fix for defect PDEF085280 ")); + TRAP(error, RunTestPDEF085280L()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3162 Test fix for defect PDEF097387 ")); + TRAP(error, SetupAndRunPDEF097387TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3241 Test fix for defect PDEF098569 ")); + TRAP(error, RunPDEF098569TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3345 Test fix for defect INC099424 ")); + TRAP(error, RunINC099424TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-3754 Test fix for defect INC109995 & DEF118277 ")); + TRAP(error, RunINC109995TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4003 Test fix for defect PDEF112004 ")); + TRAP(error, RunPDEF112004TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4001 Test fix for defect INC112423 ")); + TRAP(error, RunINC112423TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4005 Test fix for defect PDEF114862 ")); + TRAP(error, RunPDEF114862TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4008 Test fix for defect INC116681 ")); + TRAP(error, RunINC116681TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4019 Test fix for defect DEF122198 ")); + TRAP(error, RunDEF122198_1TestL()); + test(error == KErrNone); + TRAP(error, RunDEF122198_2TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-CT-4020 Test fix for defect INC123427 ")); + TRAP(error, RunINC123427TestL()); + test(error == KErrNone); + test.Next(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-4018 Test fix for defect PDEF123018")); + TRAP(error, RunPDEF123018TestL()); + test(error == KErrNone); + + RFbsSession::Disconnect(); + delete scheduler; + delete TrapCleanup; + test.End(); + test.Close(); + return error; + }