diff -r 000000000000 -r 1fb32624e06b textrendering/textformatting/tbox/LAYEMU.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/textformatting/tbox/LAYEMU.CPP Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,4463 @@ +/* +* Copyright (c) 2003-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: +* CTextLayout implementation using the TAGMA text formatting system. +* +*/ + + +#include +#include "FRMTLAY.H" +#include "FRMCONST.H" +#include "FORMUTIL.H" + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "FRMCONST_INTERNAL.H" +#include "FRMCONST_PARTNER.H" +#include "TAGMA_INTERNAL.H" +#include "FRMTLAY_INTERNAL.H" +#endif + +const TInt KMaxExtraLines = 10; // maximum number of lines to format after the current and following lines + // before using background formatting +// during page down/up, the number of lines that should remain visible after +// the scroll, counting from the first line that is not completely visible. +// i.e. setting this to 0 means always scroll KMaxProportionOfScreenToScroll. +// setting it to 1 means make sure that no lines are ever both partially off the +// top/bottom before the scroll and partially visible off the bottom/top after +// the scroll. +// setting it to any number higher means keep that number -1 lines completely +// visible before and after the scroll. +const TInt KNumberOfLinesToKeepVisibleDuringScroll = 2; +/** maximum scroll proportions in thousandths. This overrides + the KNumberOfLinesToKeepVisibleDuringScroll constant.*/ +const TInt KMaxProportionOfScreenToScroll = 1000; +/** minimum scroll proportions in thousandths. This overrides + the KNumberOfLinesToKeepVisibleDuringScroll constant.*/ +const TInt KMinProportionOfScreenToScroll = 600; + +/** +Tests for a high surrogate. +@param a UTF16 value. +@return ETrue if argument is a high surrogate. +@internalComponent +*/ +inline TBool IsHighSurrogate(TText a) { return 0xD800 == (a & 0xFC00); } +/** +Tests for a low surrogate. +@param a UTF16 value. +@return ETrue if argument is a high surrogate. +@internalComponent +*/ +inline TBool IsLowSurrogate(TText a) { return 0xDC00 == (a & 0xFC00); } +/** +Adds a high surrogate to a low surrogate to create a supplementary character. +@param aHigh UTF16 high surrogate. +@param aLow UTF16 low surrogate. +@return Supplementary character represented by the pair . +@pre aHigh is a high surrogate and aLow is a low surrogate. +@internalComponent +*/ +inline TChar PairSurrogates(TText aHigh, TText aLow) + { + return ((aHigh - 0xd7f7) << 10) + aLow; + } + +/** +Constructs an iterator over the text referenced by aSource. +@param aSource The source of the text to be iterated over. +*/ +CTextLayout::TUtf32SourceCache::TUtf32SourceCache(const MTmSource& aSource) + : iSource(&aSource), iCurrentViewIndex(-1) + { + } + +/** +Constructs an iterator over the text formatted by aLayout. +@param aLayout The formatter of the text to be iterated over. +*/ +CTextLayout::TUtf32SourceCache::TUtf32SourceCache(const CTextLayout& aLayout) + : iSource(aLayout.iSource), iCurrentViewIndex(-1) + { + } + +/** +Gets the specified character without uniting surrogate pairs. +@param aIndex The document position to retrieve. +@pre 0 <= aIndex && aIndex < {document length} +*/ +TText CTextLayout::TUtf32SourceCache::GetUtf16(TInt aIndex) + { + TTmCharFormat dummy; + if (aIndex < iCurrentViewIndex) + { + iCurrentViewIndex = 0; + iSource->GetText(iCurrentViewIndex, iCurrentView, dummy); + } + TInt currentViewEnd = iCurrentViewIndex + iCurrentView.Length(); + while (currentViewEnd <= aIndex) + { + TInt difference = aIndex - iCurrentViewIndex; + TInt newIndex = aIndex - (difference >> 1); + iCurrentViewIndex = newIndex < currentViewEnd? + currentViewEnd : newIndex; + iSource->GetText(iCurrentViewIndex, iCurrentView, dummy); + currentViewEnd = iCurrentViewIndex + iCurrentView.Length(); + } + return iCurrentView[aIndex - iCurrentViewIndex]; + } + +/** +Gets the specified character, uniting surrogate pairs if appropriate. +@param aIndex + The document position to retrive. +@return + The character at position aIndex. If aIndex is at the first code of a + surrogate pair, the full character is returned. If it is the second of a + valid surrogate pair or an unpaired surrogate, the surrogate is returned. +*/ +TChar CTextLayout::TUtf32SourceCache::GetUtf32(TInt aIndex) + { + TText code = GetUtf16(aIndex); + if (IsHighSurrogate(code) && iSource->DocumentLength() < aIndex + 1) + { + TText code2 = GetUtf16(aIndex + 1); + if (IsLowSurrogate(code2)) + return PairSurrogates(code, code2); + } + return code; + } + +/** Allocates and constructs a CTextLayout object. By default, the formatting +is set to the entire document (EFFormatAllText). + +The text needs to be reformatted after a call to this function. + +@param aDoc Pointer to the MLayDoc implementation that is the source of the +text and formatting information. Must not be NULL or a panic occurs. +@param aWrapWidth The wrapping width in pixels. +@return Pointer to the new CTextLayout object. */ +EXPORT_C CTextLayout *CTextLayout::NewL(MLayDoc *aLayDoc,TInt aWrapWidth) + { + CTextLayout* t = new(ELeave) CTextLayout; + CleanupStack::PushL(t); + t->ConstructL(aLayDoc,aWrapWidth); + CleanupStack::Pop(); + return t; + } + +EXPORT_C CTextLayout::CTextLayout(): + iText(NULL), + iExcessHeightRequired(0), + iWnd(NULL), + iBeginRedrawCount(0), + iRedrawRect(), + iTextViewCursorPos(NULL), + iIsWndInExternalRedraw(EFalse), + iUnformattedStart(KMaxTInt), + iHighlightExtensions(NULL), + iSource(NULL) + { + } + +/** Constructs an object with a text source of aLayDoc and a wrap width of +aWrapWidth, with wrapping turned on. +*/ +EXPORT_C void CTextLayout::ConstructL(MLayDoc *aLayDoc,TInt aWrapWidth) + { + iHighlightExtensions = new(ELeave) TTmHighlightExtensions; + CleanupStack::PushL(iHighlightExtensions); + iHighlightExtensions->SetAll(0); + + iText = new(ELeave) CTmTextLayout; + CleanupStack::PushL(iHighlightExtensions); + + iSource = new(ELeave) TLayDocTextSource; + iSource->iLayDoc = aLayDoc; + SetWrapWidth(aWrapWidth); + SetAmountToFormat(EFFormatAllText); + + CleanupStack::Pop(2); + } + +EXPORT_C CTextLayout::~CTextLayout() + { + delete iHighlightExtensions; + iHighlightExtensions = NULL; + delete iText; + iText = NULL; + delete iSource; + iSource = NULL; + } + +void CTextLayout::SetWindow(RWindow* aWnd) + { + iWnd = aWnd; + } + +void CTextLayout::SetReadyToRedraw() + { + iReadyToRedraw = ETrue; + } + +void CTextLayout::BeginRedraw(const TRect& aRect) + { + if(!iReadyToRedraw) + return; + + if (0 == iBeginRedrawCount++) + { + iRedrawRect = aRect; + if (NULL != iWnd) + { + if (iWnd->GetDrawRect() == TRect::EUninitialized) + { + iWnd->Invalidate(aRect); + iWnd->BeginRedraw(aRect); + } + else + iIsWndInExternalRedraw = ETrue; + } + } + } + +void CTextLayout::EndRedraw() + { + if(!iReadyToRedraw) + return; + + __ASSERT_ALWAYS(iBeginRedrawCount > 0, Panic(EInvalidRedraw)); + + if (0 == --iBeginRedrawCount) + { + if (NULL != iWnd) + { + if (!iIsWndInExternalRedraw) + { + iWnd->EndRedraw(); + iRedrawRect = TRect(); + } + else + iIsWndInExternalRedraw = EFalse; + } + } + } + +void CTextLayout::SetExternalDraw(const TRect& aRect) + { + __ASSERT_ALWAYS(0 == iBeginRedrawCount, Panic(EInvalidRedraw)); + iBeginRedrawCount++; + iRedrawRect = aRect; + } + +void CTextLayout::ResetExternalDraw() + { + __ASSERT_ALWAYS(1 == iBeginRedrawCount, Panic(EInvalidRedraw)); + + iBeginRedrawCount--; + iRedrawRect = TRect(); + } + +TBool CTextLayout::BeginRedrawCalled() const + { + return iBeginRedrawCount > 0; + } + + +/** Discards all formatting information. This function is used by the CTextView +and the printing classes, but should be called by higher-level classes that +need to clean up after any CTextLayout function has caused an out-of-memory +exception. */ +EXPORT_C void CTextLayout::DiscardFormat() + { + iText->Clear(); + iBandTop = 0; + } + +TInt CTextLayout::SetBandTop() + { + TInt originalBandTop = iBandTop; + if (iScrollFlags & EFScrollOnlyToTopsOfLines) + { + TTmLineInfo line; + if (iText->YPosToLine(iBandTop, line)) + iBandTop = line.iOuterRect.iTl.iY; + } + return originalBandTop - iBandTop; + } + +/** Sets the layout object's source text to aDoc. + +The text needs to be reformatted after a call to this function. + +@param aDoc Pointer to the MLayDoc implementation that is the source of the +text and formatting information. Must not be NULL or a panic occurs. */ +EXPORT_C void CTextLayout::SetLayDoc(MLayDoc *aLayDoc) + { + iSource->iLayDoc = aLayDoc; + } + +/** Sets the wrap width. If the current format mode is screen mode +(CLayoutData::EFScreenMode) aWrapWidth is in pixels, otherwise it is in twips. + +The text needs to be reformatted after a call to this function. + +Note: + +A valid wrap width (>0) must be supplied or the expected amount of formatting will +not take place. This could lead to panics when trying to retrieve formatting +information that does not exist. + +@param aWrapWidth The wrap width in pixels or twips. */ +EXPORT_C void CTextLayout::SetWrapWidth(TInt aWrapWidth) + { + if (iSource->iFormatMode == CLayoutData::EFScreenMode) + iSource->iWidth = aWrapWidth; + else + iSource->iWidth = iSource->iFormatDevice->HorizontalTwipsToPixels(aWrapWidth); + } + +/** Sets the height of the band in pixels or twips. This is the height of the +visible text, or the view window, and it is also the page height for the +purposes of scrolling up and down by page. If the current mode is screen mode +(CLayoutData::EFScreenMode) or what-you-see-is-what-you-get mode +(CLayoutData::EFWysiwygMode), aHeight is in pixels, otherwise it is in twips. + +The text needs to be reformatted after a call to this function. + +Note: + +A valid band height (>0) must be supplied or the expected amount of formatting will +not take place. This could lead to panics when trying to retrieve formatting +information that does not exist. + +@param aHeight The band height in pixels or twips. */ +EXPORT_C void CTextLayout::SetBandHeight(TInt aHeight) + { + iVisibleHeight = aHeight; + if (iBandHeight != CLayoutData::EFHeightForFormattingAllText || aHeight < 1) + iBandHeight = aHeight; + } + +/** Gets the height of the band in pixels or twips. +@return The height of the band in pixels or twips. */ +EXPORT_C TInt CTextLayout::BandHeight() const + { + return VisibleHeightInPixels(); + } + +/** Sets the device map used for drawing and formatting. This device map is +also used for formatting and drawing paragraph labels unless a separate label +device map has been set (see SetLabelsDeviceMap()). + +The text needs to be reformatted after a call to this function. + +Note: + +Although the name of the function suggests that only the image device is set, +the formatting device is also set. + +@param aGd The device map used for drawing and formatting. */ +EXPORT_C void CTextLayout::SetImageDeviceMap(MGraphicsDeviceMap *aDeviceMap) + { + iSource->iImageDevice = aDeviceMap; + iSource->iFormatDevice = aDeviceMap; + } + +/** Sets the device map used for formatting and drawing paragraph labels. If +not set, the device map used for labels will be the same as that used for the +text. + +The text needs to be reformatted after a call to this function. + +@param aDeviceMap The device map used for formatting and drawing paragraph +labels. */ +EXPORT_C void CTextLayout::SetLabelsDeviceMap(MGraphicsDeviceMap *aDeviceMap) + { + iSource->iLabelsDevice = aDeviceMap; + } + +/** Sets whether to format all the text (if aAmountOfFormat is +EFFormatAllText), or just the visible band (if aAmountOfFormat is +EFFormatBand). If band formatting is selected, enough text is formatted to fill +the visible height. + +The text needs to be reformatted after a call to this function. + +@param aAmountOfFormat CTextLayout::EFFormatBand (the default) to format the +visible text only. CTextLayout::EFFormatAllText to format all the text in the +document. */ +EXPORT_C void CTextLayout::SetAmountToFormat(TAmountFormatted aAmountOfFormat) + { + if (aAmountOfFormat == EFFormatBand) + iBandHeight = iVisibleHeight; + else + iBandHeight = CLayoutData::EFHeightForFormattingAllText; + } + +/** Tests whether band formatting is on, as set by +CTextLayout::SetAmountToFormat(). +@return ETrue if band formatting is on, EFalse if not. */ +EXPORT_C TBool CTextLayout::IsFormattingBand() const + { + return iBandHeight != CLayoutData::EFHeightForFormattingAllText; + } + +/** Sets the format mode and wrap width and (for certain format modes only) +sets the formatting device. + +The text needs to be reformatted after a call to this function. + +Notes: + +If aFormatMode is CLayoutData::EFWysiwygMode or +CLayoutData::EFPrintPreviewMode, the format device is set to aFormatDevice, +which must not be NULL. + +If aFormatMode is CLayoutData::EFScreenMode or CLayoutData::EFPrintMode, +aFormatDevice is ignored and should be NULL; the format device is set to the +image device. + +The wrap width is set in either twips or pixels using the same rule as for +SetWrapWidth(). + +@param aFormatMode The format mode. +@param aWrapWidth The wrap width in pixels or twips. +@param aFormatDevice The formatting device or NULL, depending on the format +mode. */ +EXPORT_C void CTextLayout::SetFormatMode(CLayoutData::TFormatMode aFormatMode,TInt aWrapWidth, + MGraphicsDeviceMap* aFormatDevice) + { + if (aFormatMode == CLayoutData::EFWysiwygMode || aFormatMode == CLayoutData::EFPrintPreviewMode) + { + __ASSERT_ALWAYS(aFormatDevice != NULL,Panic(EFormatDeviceNotSet)); + iSource->iFormatDevice = aFormatDevice; + } + else + iSource->iFormatDevice = iSource->iImageDevice; + iSource->iFormatMode = aFormatMode; + SetWrapWidth(aWrapWidth); + } + +/** Turns wrapping on (if aNoWrapping is EFParagraphsWrappedByDefault) or off +(if aNoWrapping is EFAllParagraphsNotWrapped). Overrides the paragraph format +when wrapping is turned off -paragraphs are not broken into lines even if the +iWrap member of CParaFormat is ETrue. If wrapping is turned on, +CParaFormat::iWrap is honoured. + +The text needs to be reformatted after a call to this function. + +@param aNoWrapping EFAllParagraphsNotWrapped (the default) to turn wrapping +off, EFParagraphsWrappedByDefault to turn wrapping on. */ +EXPORT_C void CTextLayout::ForceNoWrapping(TBool aNoWrapping) + { + if (aNoWrapping) + iSource->iFlags &= ~TLayDocTextSource::EWrap; + else + iSource->iFlags |= TLayDocTextSource::EWrap; + } + +/** Tests whether wrapping is on or off. +@return ETrue if wrapping is on, EFalse if off. */ +EXPORT_C TBool CTextLayout::IsWrapping() const + { + return (iSource->iFlags & TLayDocTextSource::EWrap) != 0; + } + +/** Sets the truncation mode. If truncation is on, lines that exceed the wrap +width, either because they have no legal line break, or because wrapping is +off, are truncated, and an ellipsis is inserted. + +@param aOn If ETrue, lines which extend beyond the wrap width are truncated +with an ellipsis character. If EFalse, no ellipsis is used. */ +EXPORT_C void CTextLayout::SetTruncating(TBool aOn) + { + if (aOn) + iSource->iFlags |= TLayDocTextSource::ETruncateWithEllipsis; + else + iSource->iFlags &= ~TLayDocTextSource::ETruncateWithEllipsis; + } + +/** Tests whether truncation is on (as set by SetTruncating()). +@return ETrue if truncation is on, EFalse if not. */ +EXPORT_C TBool CTextLayout::Truncating() const + { + return (iSource->iFlags & TLayDocTextSource::ETruncateWithEllipsis) != 0; + } + +/** Sets the ellipsis character to be used if truncation is on. Specify the +value 0xFFFF (the illegal Unicode character) if no ellipsis character should +be used. By default, the ellipsis character is 0x2026, the ordinary horizontal +ellipsis. + +@param aEllipsis The Unicode value of the truncating ellipsis character. */ +EXPORT_C void CTextLayout::SetTruncatingEllipsis(TChar aEllipsis) + { + iSource->iEllipsis = aEllipsis; + } + +/** Returns the ellipsis character used when truncation is on. The value 0xFFFF +(the illegal Unicode character) means that no ellipsis character is appended to +truncated text. + +@return The Unicode value of the truncating ellipsis character. */ +EXPORT_C TChar CTextLayout::TruncatingEllipsis() const + { + return iSource->iEllipsis; + } + +/** Sets the width in pixels of the margin in which labels are drawn. + +The text needs to be reformatted after a call to this function. + +@param aWidth The width in pixels of the labels margin. */ +EXPORT_C void CTextLayout::SetLabelsMarginWidth(TInt aWidth) + { + iSource->iLabelsWidth = aWidth; + } + +/** Specifies which non-printing characters (e.g. space, paragraph break, etc.) +are to be drawn using symbols. + +The text needs to be reformatted after a call to this function.(because +non-printing characters may differ in width from their visible +representations). + +@param aVisibility Indicates which non-printing characters are drawn using +symbols. */ +EXPORT_C void CTextLayout::SetNonPrintingCharsVisibility(TNonPrintingCharVisibility aVisibility) + { + iSource->iNonPrintingCharVisibility = aVisibility; + } + +/** Returns which non-printing characters are drawn using symbols. +@return Indicates which non-printing characters are drawn using symbols. */ +EXPORT_C TNonPrintingCharVisibility CTextLayout::NonPrintingCharsVisibility() const + { + return iSource->iNonPrintingCharVisibility; + } + +/** Tests whether background formatting is currently taking place. Background +formatting is managed by CTextView, using an active object, when the +CTextLayout object is owned by a CTextView object. + +Not generally useful. + +@return ETrue if background formatting is currently taking place. EFalse if not. +*/ +EXPORT_C TBool CTextLayout::IsBackgroundFormatting() const + { + return iUnformattedStart < KMaxTInt; + } + +/** CTextView calls this function when background formatting has ended. It +allows the CTextLayout object to discard information used only during +background formatting. + +Not generally useful. */ +EXPORT_C void CTextLayout::NotifyTerminateBackgroundFormatting() + { + iUnformattedStart = KMaxTInt; + } + + +/** Specifies whether partially displayed lines (at the top and bottom of +the view) are to be prevented from being drawn, and whether the top of +the display is to be aligned to the nearest line. + +This function takes effect only when the text is next formatted or +scrolled.Note:This function was designed for non-editable text in the +Agenda application, and there is an important restriction: +CTextView functions that reformat the text after editing must not be used +while partial lines are excluded; these functions are +CTextView::HandleCharEditL(), +CTextView::HandleInsertDeleteL() and +CTextView::HandleRangeFormatChangeL(). + +@param aExcludePartialLines ETrue (the default) to exclude partially +displayed lines from the view. EFalse to include them. +@deprecated 7.0 */ +//It did not work, and it was not what the customer wanted. A more comprehensive +//solution is being considered. +EXPORT_C void CTextLayout::SetExcludePartialLines(TBool) {} + +/** Tests whether partial lines at the top and bottom of the view are +currently excluded. + +@return ETrue if partial lines are excluded, EFalse if they are displayed. +@deprecated 7.0 */ +EXPORT_C TBool CTextLayout::ExcludingPartialLines() const + { + return EFalse; + } + +/** Sets the percentage by which font heights are increased in order to provide +automatic extra spacing (leading) between lines. This amount is set to +CLayoutData::EFFontHeightIncreaseFactor, which is 7, when a CTextLayout object +is created. + +The text needs to be reformatted after a call to this function. + +@param aPercentage Factor by which to increase font heights. */ +EXPORT_C void CTextLayout::SetFontHeightIncreaseFactor(TInt aPercentage) + { + iSource->iFontHeightIncreaseFactor = aPercentage; + } + +/** Returns the font height increase factor as a percentage (i.e. a return +value of 7 means that font heights are increased by 7% to provide automatic +extra spacing between lines). + +@return Factor by which font heights are increased. */ +EXPORT_C TInt CTextLayout::FontHeightIncreaseFactor() const + { + return iSource->iFontHeightIncreaseFactor; + } + +/** Sets the minimum line descent in pixels. This amount is set to +CLayoutData::EFMinimumLineDescent, which is 3, when a CTextLayout object is +created. + +The text needs to be reformatted after a call to this function. + +@param aPixels The minimum line descent in pixels. */ +EXPORT_C void CTextLayout::SetMinimumLineDescent(TInt aPixels) + { + iSource->iMinimumLineDescent = aPixels; + } + +/** Returns the minimum line descent in pixels. +@return The minimum line descent in pixels. */ +EXPORT_C TInt CTextLayout::MinimumLineDescent() const + { + return iSource->iMinimumLineDescent; + } + +/** Returns the document length in characters, including all the text, not just +the formatted portion, but not including the final paragraph delimiter (the +"end-of-text character") if any. Thus the length of an empty document is zero. + +@return The number of characters in the document */ +EXPORT_C TInt CTextLayout::DocumentLength() const + { + return iSource->DocumentLength(); + } + +/** Sets aDocPos to the paragraph start and returns the amount by which aDocPos +has changed, as a non-negative number. + +@param aDocPos A document position. On return, contains the document position +of the first character in the paragraph. +@return The number of characters skipped in moving to the new document +position. */ +EXPORT_C TInt CTextLayout::ToParagraphStart(TInt& aDocPos) const + { + TInt old_pos = aDocPos; + aDocPos = iSource->ParagraphStart(aDocPos); + return old_pos - aDocPos; + } + +/** Returns the height in pixels of any formatted text above the visible +region. +@return The height in pixels of any formatted text above the visible region. */ +EXPORT_C TInt CTextLayout::PixelsAboveBand() const + { + return iBandTop; + } + +/** Returns the y coordinate of the bottom of the last formatted line, relative +to the top of the visible region. + +@return The y coordinate of the bottom of the last formatted line. */ +EXPORT_C TInt CTextLayout::YBottomLastFormattedLine() const + { + return iText->LayoutHeight() - iBandTop; + } + +/** Returns the height in pixels of the formatted text. + +@return The height in pixels of all the formatted text. */ +EXPORT_C TInt CTextLayout::FormattedHeightInPixels() const + { + return iText->LayoutHeight(); + } + +/** Returns the number of fully or partially visible characters in the visible +band. + +@param aDocPos On return, contains the document position of the first fully or +partially visible character in the band. +@return The total number of characters in the band. */ +EXPORT_C TInt CTextLayout::PosRangeInBand(TInt& aDocPos) const + { + TTmLineInfo info; + if (!iText->YPosToLine(iBandTop,info)) + { + aDocPos = 0; + return 0; + } + aDocPos = info.iStart; + int end = iSource->DocumentLength(); + //INC085809 - less 1 pixel. Rect edge is actually outside bounds + if (iText->YPosToLine(iBandTop + VisibleHeightInPixels() - 1,info)) + end = info.iEnd; + return end - aDocPos; + } + +/** Tests whether the document position aDocPos is fully or partially visible. +If it is, puts the y coordinate of the left-hand end of the baseline of the +line containing aDocPos into aXyPos. + +@param aDocPos The document position of interest. +@param aXyPos On return, contains the y coordinate of the left-hand end of the +baseline of the line containing aDocPos. +@return ETrue if the position is visible. EFalse if the position is not visible. +*/ +EXPORT_C TBool CTextLayout::PosInBand(TInt aDocPos,TPoint& aXyPos) const + { + TTmLineInfo info; + TTmDocPos pos(aDocPos, ETrue); + TBool result = PosInBand(pos,&info); + aXyPos.iX = 0; + aXyPos.iY = info.iBaseline; + return result; + } + +/** Tests whether the document position aDocPos is fully or partially visible. +If it is, puts the y coordinate of the left-hand end of the baseline of the +line containing aDocPos into aXyPos. + +@param aDocPos The document position of interest. +@param aXyPos On return, contains the y coordinate of the left-hand end of the +baseline of the line containing aDocPos. +@return ETrue if the position is visible. EFalse if the position is not visible. +*/ +EXPORT_C TBool CTextLayout::PosInBand(TTmDocPos aDocPos,TPoint& aXyPos) const + { + TTmLineInfo info; + TBool result = PosInBand(aDocPos,&info); + aXyPos.iX = 0; + aXyPos.iY = info.iBaseline; + return result; + } + +/** Tests whether the document position aDocPos is fully or partially visible. +If it is, puts the baseline of the line containing aDocPos into aLineInfo. + +@param aDocPos The document position of interest. +@param aLineInfo On return, contains the baseline of the line containing +aDocPos. + +@return ETrue if the document position aDocPos is fully or partially visible. If +so, and if aLineInfo is non-NULL, puts information about the line in aLineInfo. +Otherwise, EFalse */ +EXPORT_C TBool CTextLayout::PosInBand(const TTmDocPos& aDocPos,TTmLineInfo* aLineInfo) const + { + TTmLineInfo dummy; + TTmLineInfo* info_ptr = aLineInfo ? aLineInfo : &dummy; + TTagmaForwarder forwarder(*this); + if (!forwarder.DocPosToLine(aDocPos,*info_ptr)) + return FALSE; + return info_ptr->iOuterRect.iBr.iY > 0 && info_ptr->iOuterRect.iTl.iY < VisibleHeightInPixels(); + } + +/** Tests whether the character aDocPos is formatted. + +Note: + +If a section of text contains characters p to q, it contains document positions +p to q + 1; but this function returns ETrue for positions p to q only, so it +refers to characters, not positions. However, it will return ETrue for q if q is +the end of the document. + +@param aDocPos The document position of interest. +@return ETrue if the character at the document position specified is formatted. +EFalse if not. */ +EXPORT_C TBool CTextLayout::PosIsFormatted(TInt aDocPos) const + { + if (aDocPos < iText->StartChar()) + return FALSE; + if (aDocPos >= iText->StartChar() + FormattedLength()) + return FALSE; + return TRUE; + } + +/** Gets the document position of the first character in the specified line, +counting the first line as line one (not zero) in the band. If the line is +after the band, returns the last character position of the band. If there is no +formatted text, returns CTextLayout::EFNoCurrentFormat. + +@param aLineNo Line number in formatted text, counting the first line as line +one. +@return The document position of the first character on the line. */ +EXPORT_C TInt CTextLayout::FirstCharOnLine(TInt aLineNo) const + { + __ASSERT_DEBUG(aLineNo > 0,Panic(EInvalidLineNumber)); + if (iText->StartChar() == iText->EndChar()) + return EFNoCurrentFormat; + aLineNo--; + TTmLineInfo info; + if (!iText->LineNumberToLine(aLineNo,info)) + return Min(iText->EndChar(),iSource->DocumentLength()); + return info.iStart; + } + +/** Returns the number of formatted characters. This will be one more than +expected if the formatted text runs to the end of the document, because it will +include the end-of-text character. + +@return The number of formatted characters in the document. */ +EXPORT_C TInt CTextLayout::FormattedLength() const + { + return iText->EndChar() - iText->StartChar(); + } + +/** Returns the document position of the first formatted character. + +@return The document position of the first formatted character. */ +EXPORT_C TInt CTextLayout::FirstFormattedPos() const + { + return iText->StartChar(); + } + +/** Gets the number of formatted lines. + +@return The number of formatted lines in the document. */ +EXPORT_C TInt CTextLayout::NumFormattedLines() const + { + return iText->Lines(); + } + +/** Returns the line number, counting from 0, of the first fully visible line. + +@return The line number of the first fully visible line. */ +EXPORT_C TInt CTextLayout::FirstLineInBand() const + { + TTmLineInfo info; + if (!iText->YPosToLine(iBandTop,info)) + return 0; + int line = info.iLineNumber; + if (info.iOuterRect.iTl.iY < iBandTop) + line++; + return line; + } + +/** Gets the rectangle enclosing the formatted line that contains or is closest +to y coordinate aYPos. If aYPos is above the first formatted line, the +rectangle returned is that of the first formatted line. If aYPos is below the +last formatted line the rectangle returned is that of the last formatted line. +If there is no formatted text, returns CTextLayout::EFNoCurrentFormat. + +@param aYPos The y coordinate of the line of interest. +@param aLine On return, contains the rectangle which encloses the line at +aYPos. + +@return The line width in pixels. */ +EXPORT_C TInt CTextLayout::GetLineRect(TInt aYPos,TRect& aRect) const + { + int y = iBandTop + aYPos; + + // Snap to formatted area. + if (y >= iText->LayoutHeight()) + y = iText->LayoutHeight() - 1; + if (y < 0) + y = 0; + + TTmLineInfo info; + TBool found = iText->YPosToLine(y,info); + if (!found) + { + aRect.SetSize(TSize(0,0)); + return EFNoCurrentFormat; + } + + aRect = info.iOuterRect; + aRect.iTl.iX = info.iInnerRect.iTl.iX; + aRect.iBr.iX = info.iInnerRect.iBr.iX; + aRect.Move(0,-iBandTop); + return aRect.Width(); + } + +/** Returns the height of the paragraph containing aDocPos. If the paragraph is +not formatted, returns zero. If the paragraph is partially formatted, returns +the height of the formatted part. + +@param aDocPos A document position within the paragraph of interest. +@return The height in pixels of the paragraph. Zero if the paragraph is not +formatted. */ +EXPORT_C TInt CTextLayout::ParagraphHeight(TInt aDocPos) const + { + TRect r; + GetParagraphRect(TTmDocPos(aDocPos, ETrue), r); + return r.Height(); + } + +/** Returns the rectangle enclosing the paragraph containing aDocPos. If the +paragraph is not formatted, returns an empty rectangle. If the paragraph is +partially formatted, returns the rectangle enclosing the formatted part. + +@param aDocPos A document position within the paragraph. +@return The rectangle which encloses the paragraph containing aDocPos. */ +EXPORT_C TRect CTextLayout::ParagraphRectL(TInt aDocPos) const + { + TRect r; + GetParagraphRect(TTmDocPos(aDocPos, ETrue), r); + return r; + } + +/** Returns the left and right extremes, in layout coordinates, of the +formatted text. + +@param aLeftX On return, contains the x coordinate of the leftmost point of the +formatted text. +@param aRightX On return, contains the x coordinate of the rightmost point of +the formatted text. +@param aOnlyVisibleLines If ETrue, only scans partially or fully visible lines. +If EFalse, scans all the formatted text. +@param aIgnoreWrapCharacters If ETrue, does not include wrap characters in the +measurement (paragraph delimiters, forced line breaks, etc.). If EFalse, +includes them. +@return EFalse if there is no formatted text, otherwise ETrue. */ +EXPORT_C TBool CTextLayout::CalculateHorizontalExtremesL(TInt& aLeftX,TInt& aRightX, + TBool aOnlyVisibleLines, + TBool /*aIgnoreWrapCharacters*/) const + { + return CalculateHorizontalExtremes(aLeftX,aRightX,aOnlyVisibleLines); + //+ implement aIgnoreWrapCharacters? not until clearly specified + } + +TBool CTextLayout::CalculateHorizontalExtremes(TInt& aLeftX,TInt& aRightX, + TBool aOnlyVisibleLines) const + { + int top = 0; + int bottom = KMaxTInt; + if (aOnlyVisibleLines) + { + top = iBandTop; + bottom = iBandTop + VisibleHeightInPixels(); + } + iText->HorizontalExtremes(aLeftX, aRightX, top, bottom); + if (0 < aLeftX) + aLeftX = 0; + if (aRightX < iSource->iWidth) + aRightX = iSource->iWidth; + return iText->StartChar() < iText->EndChar(); + } + +TInt CTextLayout::WrapWidth() const + { + return iSource->iWidth; + } + +TBool CTextLayout::GetCursor(const TTmDocPos& aDocPos,TTmCursorPlacement aPlacement, + TRect& aLineRect,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const + { + TTmLineInfo info; + TBool result = iText->GetCursor(aDocPos,aPlacement,info,aOrigin,aWidth,aAscent,aDescent); + if (result) + { + aOrigin.iY -= iBandTop; + aLineRect = info.iOuterRect; + aLineRect.iTl.iX = info.iInnerRect.iTl.iX; + aLineRect.iBr.iX = info.iInnerRect.iBr.iX; + aLineRect.Move(0,-iBandTop); + } + return result; + } + +/** Gets the height (ascent + descent) and ascent of the font of the character +at aDocPos, as created using the graphics device map used for drawing (the +"image device") and returns them in aHeight and aAscent, after increasing +aHeight by the font height increase factor (see SetFontHeightIncreaseFactor()). + +@param aDocPos A document position. +@param aHeight On return contains the height in pixels of the character at +aDocPos. +@param aAscent On return, contains the ascent in pixels of the character at +aDocPos. */ +EXPORT_C void CTextLayout::GetCharacterHeightAndAscentL(TInt aDocPos,TInt& aHeight,TInt& aAscent) const + { + TPtrC text; + TTmCharFormat format; + iSource->GetText(aDocPos,text,format); + TFontSpec fs; + format.iFontSpec.GetTFontSpec(fs); + GetFontHeightAndAscentL(fs,aHeight,aAscent); + } + +/** Gets the height (ascent + descent) and ascent of the font specified by +aFontSpec, as created using the graphics device map used for drawing (the +"image device") and puts them into aHeight and aAscent, after increasing +aHeight by the font height increase factor (see SetFontHeightIncreaseFactor()). + +@param aFontSpec Font specification. +@param aHeight On return, contains the height in pixels of the font. +@param aAscent On return, contains the ascent in pixels of the font. */ +EXPORT_C void CTextLayout::GetFontHeightAndAscentL(const TFontSpec& aFontSpec,TInt& aHeight,TInt& aAscent) const + { + CFont* font; + MGraphicsDeviceMap& device = iSource->InterpretDevice(); + User::LeaveIfError(device.GetNearestFontInTwips(font,aFontSpec)); + aHeight = font->HeightInPixels(); + int increase = (iSource->iFontHeightIncreaseFactor * aHeight) / 100; + aHeight += increase; + aAscent = font->AscentInPixels() + increase; + device.ReleaseFont(font); + } + +/** Returns the index of the nearest character in the document to the window +coordinates specified. Sets aPos to the actual position of the intersection +of the line's baseline with the character's edge. If aPos is before the start +of the formatted area, returns the first formatted character; if it is after +the end of the formatted area, returns the position after the last formatted +character, or the end of the document, whichever is less. + +This function is deprecated in v7.0s. Use the more powerful FindXYPos() instead. + +@param aPos Contains coordinates to convert to a document position. On return, +contains the exact coordinates of the intersection of the line's baseline with +the character edge at the document position. +@param aFlags Three possible values: 0 is the default, and performs the task at +full accuracy (the function returns the document position of the character edge +nearest to the coordinates). CLayoutData::EFWholeLinesOnly examines lines only +and returns the position at the right end of the line if aPos.iX > 0, otherwise +the position at the left end. +@return The document position of the nearest character to the coordinates, or +of the start or end of the line, depending on the value of aFlags. */ +EXPORT_C TInt CTextLayout::XyPosToDocPosL(TPoint &aXyPos,TUint) const + { + if (aXyPos.iY < -iBandTop) + return iText->StartChar(); + else if (aXyPos.iY >= iText->LayoutHeight() - iBandTop) + return Min(iText->EndChar(),iSource->DocumentLength()); + TTmPosInfo2 pos_info; + TTmLineInfo lineInfo; + FindXyPos(aXyPos,pos_info, &lineInfo); + aXyPos = pos_info.iEdge; + TInt r = pos_info.iDocPos.iPos; + if (!pos_info.iDocPos.iLeadingEdge && lineInfo.iStart != r) + { + r -= 1; + + // surrogate support + if ( r > 0 ) + { + TPtrC text; + TTmCharFormat format; + + iSource->GetText( r - 1, text, format ); + if ( text.Length() > 1 ) + { + TUint highSurrogate = text[0]; + TUint lowSurrogate = text[1]; + if ( IsHighSurrogate( highSurrogate ) && + IsLowSurrogate( lowSurrogate ) ) + --r; + } + } + } + + return r; + } + +/** Finds the document position nearest to aXyPos. If aXyPos is in the +formatted text returns ETrue, otherwise returns EFalse. If ETrue is returned, +places information about the document position in aPosInfo and information +about the line containing the document position in aLineInfo if it is non-NULL. + +@param aXyPos Contains coordinates to convert to a document position. +@param aPosInfo Buffer to store information about the document position if the +specified coordinates are located in the formatted text. +@param aLineInfo Buffer to store information about the line if the specified +coordinates are located in the formatted text. +@return ETrue if aXyPos is a formatted position, otherwise EFalse. */ +EXPORT_C TBool CTextLayout::FindXyPos(const TPoint& aXyPos,TTmPosInfo2& aPosInfo,TTmLineInfo* aLineInfo) const + { + TTagmaForwarder forwarder(*this); + TTmLineInfo line_info; + TBool result = forwarder.FindXyPos(aXyPos,aPosInfo,line_info); + if (aLineInfo && result) + *aLineInfo = line_info; + return result; + } + +/** Returns the x-y coordinates of the document position aDocPos in aPos. The +return value is ETrue if the position is formatted, or EFalse if it is not, in +which case aPos is undefined. + +Deprecated - use the more powerful FindDocPos() instead + +@param aDocPos The document position. +@param aPos On return, contains the x-y coordinates of aDocPos. +@param aFlags Two possible values: 0 is the default, and performs the task at +full accuracy, and CLayoutData::EFWholeLinesOnly, which examines lines only and +sets aXyPos.iY only, and cannot leave. +@return ETrue if the document position is formatted, EFalse if not. */ +EXPORT_C TBool CTextLayout::DocPosToXyPosL(TInt aDocPos,TPoint& aXyPos,TUint /*aFlags*/) const + { + TTmDocPos doc_pos(aDocPos, ETrue); + TTmPosInfo2 pos_info; + TBool result = FindDocPos(doc_pos,pos_info); + aXyPos = pos_info.iEdge; + return result; + } + +/** Finds the x-y position of the document position aDocPos. + +If ETrue is returned, places information about the document position in aPosInfo +and information about the line containing the document position in aLineInfo if +it is non-NULL. + +@param aDocPos Contains the document position to check. +@param aPosInfo On return, stores information about the document position if +the position is formatted. +@param aLineInfo Buffer to store the line information if the document position +is formatted. +@return ETrue if aDocPos is in the formatted text, otherwise EFalse. */ +EXPORT_C TBool CTextLayout::FindDocPos(const TTmDocPosSpec& aDocPos,TTmPosInfo2& aPosInfo,TTmLineInfo* aLineInfo) const + { + TTagmaForwarder forwarder(*this); + TTmLineInfo line_info; + TBool result = forwarder.FindDocPos(aDocPos,aPosInfo,line_info); + if (aLineInfo && result) + *aLineInfo = line_info; + return result; + } + +/** Finds the next cursor position to aDocPos in the visually ordered line. + +@param aDocPos Contains the document position to check. +@param aPosInfo On return, stores information about the document position of +the next cursor position, if ETrue is returned. +@param aToLeft ETrue if the position to the left is to be found, or EFalse if +the position to the right is to be found. +@return EFalse if there is no formatting, or the position is at the end of the +line already. ETrue otherwise. */ +EXPORT_C TBool CTextLayout::GetNextVisualCursorPos( + const TTmDocPosSpec& aDocPos, TTmPosInfo2& aPosInfo, TBool aToLeft) const + { + TTagmaForwarder forwarder(*this); + return forwarder.GetNextVisualCursorPos(aDocPos, aPosInfo, aToLeft); + } + +/** Gets a rectangle enclosing two formatted document positions on the same +line. If the second position is less than the first, or on a different line, it +is taken to indicate the end of the line. This function panics if either +position is unformatted. + +Note: + +CTextLayout must have been set with a valid wrap width and band height before +calling this function, otherwise no formatting will take place and the function +will panic. Wrap width and band height values must be > 0 to be valid. + +@param aDocPos1 The first document position on the line. +@param aDocPos2 The second document position on the line. +@return The minimal rectangle, which bounds both positions. +@see SetBandHeight +@see SetWrapWidth */ +EXPORT_C TRect CTextLayout::GetLineRectL(TInt aDocPos1,TInt aDocPos2) const + { + TRect rect; + TPoint point; + TInt xCoords[4]; + + if (iText->LayoutHeight() == 0) + return TRect(0,0,0,0); + + __ASSERT_ALWAYS(PosIsFormatted(aDocPos1),Panic(ECharacterNotFormatted)); + __ASSERT_DEBUG(PosIsFormatted(aDocPos2),Panic(ECharacterNotFormatted)); + + TTmDocPosSpec docSpec(aDocPos1, TTmDocPosSpec::ELeading); + TTmPosInfo2 pos_info; + + // Finding the leading edge of aDocPos1 + FindDocPos(docSpec,pos_info); + point = pos_info.iEdge; + xCoords[0] = point.iX; + + // Getthe Line rectangle + GetLineRect(point.iY,rect); + + __ASSERT_DEBUG(rect.iTl.iY <= point.iY && rect.iBr.iY >= point.iY,Panic(EPixelNotInFormattedLine)); + + // Finding the leading edge of aDocPos2 + docSpec.iPos = aDocPos2; + TBool isformatted = FindDocPos(docSpec, pos_info); + point = pos_info.iEdge; + + // Checks if the aDocPos2 is contained in the same line of the aDocPos1 + // Can't use TRect::Contains() here, because TRect::Contains() considers a point located on the right + // hand side or bottom as outside the rectangle, which will has problem when work with RTL text that + // is at the right hand end of a line. + TBool isContained = (point.iX>=rect.iTl.iX && point.iX<=rect.iBr.iX + && point.iY>=rect.iTl.iY && point.iY<=rect.iBr.iY); + + RTmParFormat parFormat; + iSource->GetParagraphFormatL(aDocPos1, parFormat); + + // The special cases (as indicated in the description): + // When the aDocPos2 is less than the aDocPos1, or not formatted, or on a different line from which the + // aDocPos1 is in, then the function will return the rectangle starting from docPos1's leading edge and + // ending at the end of the line (which is determined by paragraph directionality). + if (aDocPos2 < aDocPos1 || !isformatted || !isContained) + { + if (parFormat.RightToLeft()) + rect.iBr.iX = xCoords[0]; + else + rect.iTl.iX = xCoords[0]; + + parFormat.Close(); + return rect; + } + + xCoords[1] = point.iX; + + // Finding the Trailing edge of (aDocPos1 + 1) + docSpec.iType = TTmDocPosSpec::ETrailing; + docSpec.iPos = aDocPos1 + 1; + FindDocPos(docSpec, pos_info); + xCoords[2] = pos_info.iEdge.iX; + + // Finding the Trailing edge of (aDocPos2 + 1) + docSpec.iPos = aDocPos2 + 1; + FindDocPos(docSpec, pos_info); + xCoords[3] = pos_info.iEdge.iX; + + rect.iBr.iX = xCoords[0]; + rect.iTl.iX = xCoords[0]; + + // The returned rectangle is generated by (when is not a special case) + // 1) Find the Line rectangle + // 2) Find the: + // - leading edge of docPos1 + // - leading edge of docPos2 + // - trailing edge of docPos1+1 + // - trailing edge of docPos2+1 + // 3) Cut the line rectangle at the smallest edge and the largest edge among + // the four edges found in step 2. + for (TInt i = 1; i<4; i++ ) + { + if (rect.iBr.iX < xCoords[i]) + rect.iBr.iX = xCoords[i]; + if (rect.iTl.iX > xCoords[i]) + rect.iTl.iX = xCoords[i]; + } + + parFormat.Close(); + return rect; + } + +/** Gets the bounding rectangle of the picture, if any, located at the document +position or coordinates specified, and returns it in aPictureRect. + +If aCanScaleOrCrop is non-null, sets aCanScaleOrCrop to indicate +whether the picture can be scaled or cropped. +Returns ETrue if the operation was successful. Returns EFalse otherwise; +that is, if there is no picture at the position, or if the position is unformatted. + +@param aDocPos The document position of interest. +@param aXyPos The layout coordinates of interest. +@param aPictureRect On return, contains the rectangle which encloses the +picture located at the position specified. +@param aCanScaleOrCrop If non-NULL and the function returns ETrue, on return, +indicates whether the picture can be scaled or cropped. By default, NULL. +@return ETrue if the operation was successful, (i.e. there is a +picture character at the position, it has been loaded into +memory, and the position is formatted). EFalse if any of these +conditions are not met. */ +EXPORT_C TBool CTextLayout::PictureRectangleL(TInt aDocPos,TRect& aPictureRect,TBool* aCanScaleOrCrop) const + { + if (aDocPos < iText->StartChar() || aDocPos >= iText->EndChar() - 1) + return FALSE; + + aPictureRect.SetRect(0,0,0,0); + TSize size; + if (iSource->GetPictureSizeInTwipsL(aDocPos,size) != KErrNone) + return FALSE; + + TRect rect; + TTmDocPos pos(aDocPos, ETrue); + TTmPosInfo2 pos_info; + TTmLineInfo info; + TInt subscript; + if (!iText->FindDocPos(pos,pos_info,info,subscript)) + return FALSE; + + MGraphicsDeviceMap& device = iSource->InterpretDevice(); + size.iWidth = device.HorizontalTwipsToPixels(size.iWidth); + size.iHeight = device.VerticalTwipsToPixels(size.iHeight); + rect.iBr.iY = pos_info.iEdge.iY - iBandTop + subscript; + rect.iTl.iY = rect.iBr.iY - size.iHeight; + if (pos_info.iRightToLeft) + { + rect.iBr.iX = pos_info.iEdge.iX; + rect.iTl.iX = rect.iBr.iX - size.iWidth; + } + else + { + rect.iTl.iX = pos_info.iEdge.iX; + rect.iBr.iX = rect.iTl.iX + size.iWidth; + } +/* rect.iTl = pos_info.iEdge; + rect.Move(0,-iBandTop); + rect.iTl.iY -= size.iHeight; + rect.iBr = rect.iTl + size;*/ + CPicture* picture = iSource->PictureL(aDocPos); + if (!picture) + return FALSE; + + if (aCanScaleOrCrop) + *aCanScaleOrCrop = picture->Capability().iScalingType != TPictureCapability::ENotScaleable || + picture->Capability().iIsCroppable; + aPictureRect = rect; + return TRUE; + } + +/** Finds if there is a picture at the position under the point aXyPos. +If there is, returns the document position of it, sets the rectangle +occupied in aPictureRect, and whether the picture allows scaling +in aCanScaleOrCrop, if non-null. Note that aXyPos may be outside +the picture found. +@return The document position of the picture found, or KErrNotFound if there +is none. */ +TInt CTextLayout::PictureRectangleAndPosL(const TPoint& aXyPos, TRect& aPictureRect, + TBool* aCanScaleOrCrop) const + { + TTmPosInfo2 posInfo; + if (!FindXyPos(aXyPos, posInfo)) + return KErrNotFound; + TInt doc_pos = posInfo.iDocPos.iPos - (posInfo.iDocPos.iLeadingEdge? 0 : 1); + if (PictureRectangleL(doc_pos, aPictureRect, aCanScaleOrCrop)) + return doc_pos; + return KErrNotFound; + } + +/** Gets the bounding rectangle of the picture (if any) at aXyPos and puts it +in aPictureRect. If aCanScaleOrCrop is non-null sets *aCanScaleOrCrop to +indicate whether the picture can be scaled or cropped. Note that aXyPos +may be outside aPictureRect on a successful return, if the picture does +not occupy the whole of the section of the line it is in. +@return ETrue if the position is formatted and there is a picture there. */ +EXPORT_C TBool CTextLayout::PictureRectangleL(const TPoint& aXyPos, + TRect& aPictureRect, TBool* aCanScaleOrCrop) const + { + return 0 <= PictureRectangleAndPosL(aXyPos, aPictureRect, aCanScaleOrCrop)? + ETrue : EFalse; + } + +/** Gets the first document position in a line that starts at or below the top +of the visible area. If there is no such line, returns the position after the +last formatted character. + +@return The document position of the first character in a line within the +visible area. */ +EXPORT_C TInt CTextLayout::FirstDocPosFullyInBand() const + { + TTmLineInfo info; + if (!iText->YPosToLine(iBandTop,info)) + return iText->EndChar(); + if (info.iOuterRect.iTl.iY < iBandTop) + return info.iEnd; + else + return info.iStart; + } + + + + +/** This interface is deprecated, and is made available in version 7.0s solely +to provide binary compatibility with Symbian OS v6.1. Developers are strongly +advised not to make use of this API in new applications. In particular, use the +other overload of this function if you need to distinguish between leading and +trailing edge positions. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aDocPos A valid document position. +@param aYPos The y coordinate at which to display the character at aDocPos. On +return, contains the actual vertical position of the specified part of the +line. +@param aYPosQualifier Controls which part of the line is set to appear at +aYPos. +@param aDiscardFormat If ETrue (EFViewDiscardAllFormat), the text is reformatted +to include aDocPos, otherwise text is formatted only as necessary when bringing +new lines into the visible area. +@return The number of pixels the text was scrolled, may be positive or +negative. A value of CTextLayout::EFScrollRedrawWholeScreen indicates that the +entire visible area, at least, was scrolled, and so there is no point in +blitting text; a full redraw is needed. */ +EXPORT_C TInt CTextLayout::SetViewL(TInt aDocPos,TInt& aYPos,TViewYPosQualifier aYPosQualifier,TDiscard aDiscardFormat) + { + TTmDocPos pos(aDocPos, ETrue); + return SetViewL(pos,aYPos,aYPosQualifier,aDiscardFormat); + } + +/** Changes the top of the visible area so that the line containing aDocPos is +vertically positioned at aYPos. Which part of the line is set to appear at +aYPos (top, baseline, or bottom) is controlled by the TViewYPosQualifier +argument, which also specifies whether the visible area is to be filled and +whether the line should be made fully visible if possible. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aDocPos A valid document position. +@param aYPos The y coordinate at which to display the character at aDocPos. On +return, contains the actual vertical position of the specified part of the +line. +@param aYPosQualifier Controls which part of the line is set to appear at +aYPos. +@param aDiscardFormat If ETrue (EFViewDiscardAllFormat), the text is reformatted +to include aDocPos, otherwise text is formatted only as necessary when bringing +new lines into the visible area. +@return The number of pixels the text was scrolled, may be positive or +negative. A value of CTextLayout::EFScrollRedrawWholeScreen indicates that the +entire visible area, at least, was scrolled, and so there is no point in +blitting text; a full redraw is needed. */ +EXPORT_C TInt CTextLayout::SetViewL(const TTmDocPos& aDocPos, TInt& aYPos, + TViewYPosQualifier aYPosQualifier, TDiscard aDiscardFormat) + { + if (aDocPos.iPos < 0 || aDocPos.iPos > iSource->DocumentLength()) + Panic(EInvalidDocPos); + + /* + If the format is to be discarded, or no text has yet been formatted, or if the document position + to be viewed is not formatted, format the band. + */ + TTmLineInfo info; + TBool all_formatted = FALSE; + TBool pos_is_formatted = iText->DocPosToLine(aDocPos,info); + if (!pos_is_formatted || + aDiscardFormat == EFViewDiscardAllFormat || + (iText->StartChar() == iText->EndChar() && iSource->DocumentLength() > 0)) + { + FormatBandL(aDocPos.iPos,aDocPos.iPos); + all_formatted = TRUE; + pos_is_formatted = iText->DocPosToLine(aDocPos,info); + } + + // Find out where the top of the line is. + if (!pos_is_formatted) + return 0; + int line_top_y = info.iOuterRect.iTl.iY - iBandTop; + + // Determine the desired position of the top of the line. + int offset = 0; + if (aYPosQualifier.iHotSpot == TViewYPosQualifier::EFViewBaseLine) + offset = info.iBaseline - info.iOuterRect.iTl.iY; + else if (aYPosQualifier.iHotSpot == TViewYPosQualifier::EFViewBottomOfLine) + offset = info.iOuterRect.iBr.iY - info.iOuterRect.iTl.iY; + int desired_line_top_y = aYPos - offset; + + // Adjust aYPos so that the line is fully visible if desired. + if (aYPosQualifier.iFullyVisible == TViewYPosQualifier::EFViewForceLineFullyVisible) + { + TInt screenHeight = VisibleHeightInPixels(); + TInt lineHeight = info.iOuterRect.Height(); + TInt lineAscent = info.iBaseline - info.iOuterRect.iTl.iY; + // If the top of the line is off the top of the screen, and the + // baseline and the top can both fit, make the top of the line flush + // with the top of the screen. + if (lineAscent <= screenHeight + && desired_line_top_y < 0) + desired_line_top_y = 0; + // If the whole line can fit and the bottom if off the bottom of the + // screen, make the bottom flush with the bottom of the screen. + if (lineHeight <= screenHeight + && screenHeight < desired_line_top_y + lineHeight) + desired_line_top_y = screenHeight - lineHeight; + // If the ascent will not fit, or the baseline is off the bottom of + // the screen, move the baseline flush with the bottom of the screen + if (screenHeight < lineAscent + || screenHeight < desired_line_top_y + lineAscent) + desired_line_top_y = screenHeight - lineAscent; + } + + // Scroll the document position to the desired vertical coordinate and update aYPos. + TInt dy = desired_line_top_y - line_top_y; + if (dy) + { + dy = ScrollL(dy,aYPosQualifier.iFillScreen ? EFDisallowScrollingBlankSpace : EFAllowScrollingBlankSpace); + line_top_y += dy; + aYPos = line_top_y + offset; + + // Ensure that aYPos is in the line. + if (aYPosQualifier.iHotSpot == TViewYPosQualifier::EFViewBottomOfLine) + aYPos--; + } + return all_formatted ? EFScrollRedrawWholeScreen : dy; + } + +/** Formats enough text to fill the visible band. + +Note: Do not use if a CTextView object owns this CTextLayout object. */ +EXPORT_C void CTextLayout::FormatBandL() + { + FormatBandL(0,0); + } + +/** +Format enough text to fill the visible band and include both aStartDocPos and +aEndDocPos. Start at the start of the document if formatting everything, or at +the start of the paragraph containing aStartDocPos if formatting the visible +band only. +*/ +void CTextLayout::FormatBandL(TInt aStartDocPos,TInt aEndDocPos) + { + TTmFormatParam param; + InitFormatParam(param); + if (iBandHeight != CLayoutData::EFHeightForFormattingAllText) + param.iStartChar = iSource->ParagraphStart(aStartDocPos); + if (param.iWrapWidth < 1 || param.iMaxHeight < 1) + { + // Do just a little formatting if the values are illegal. + // This is to prevent the AddParL running with no + // height limit, taking up huge amounts of time, and + // having to return with 0 lines formatted, which + // confuses CEikEdwin. + param.iMaxHeight = 1; + param.iWrapWidth = 1; + iText->SetTextL(*iSource,param); + return; + } + iText->SetTextL(*iSource,param); + param.iMaxHeight = KMaxTInt; + + if(IsFormattingBand() && (iText->EndChar() <= aEndDocPos && iText->EndChar() < iSource->DocumentLength())) + { + param.iEndChar = aEndDocPos; + iText->ExtendFormattingDownwardsL(param); + } + else + { + while (iText->EndChar() <= aEndDocPos && iText->EndChar() < iSource->DocumentLength()) + { + int h,p; + AddFormattingAtEndL(param, h, p); + } + } + + + if (iBandHeight != CLayoutData::EFHeightForFormattingAllText) + { + int visible_height = VisibleHeightInPixels(); + while (iText->LayoutHeight() < visible_height) + { + int h,p; + if (!iText->AddParL(param,TRUE,h,p)) + break; + } + } + iBandTop = 0; + } + +/** Makes sure the line that aYPos is in (if it exists) is covered by the +formatting. +@param aYPos Y pixel position in window-relative co-ordinates. +@internalComponent +*/ +EXPORT_C void CTextLayout::ExtendFormattingToCoverYL(TInt aYPos) + { + TTmFormatParam param; + InitFormatParam(param); + param.iStartChar = iText->StartChar() - 1; + param.iEndChar = iText->EndChar(); + param.iMaxHeight = KMaxTInt; + TInt heightIncrease; + TInt p; + while (iBandTop < -aYPos && iText->AddParL(param, ETrue, heightIncrease, p)) + { + iBandTop += heightIncrease; + param.iStartChar = iText->StartChar() - 1; + } + TInt heightRemaining = iBandTop + aYPos - iText->LayoutHeight() + 1; + if(heightRemaining > 0) + { + param.iStartChar = iText->EndChar(); + param.iEndChar = KMaxTInt; + param.iMaxHeight = heightRemaining; + iText->ExtendFormattingDownwardsL(param); + } + } + +/** Allows you to increase the formatted text range by specifying a point in the text you +want to increase the range to. Makes sure the line that aDocPos is in (if it exists) is covered by the +formatting. +@param aDocPos Position in the text you wish to extend the formatting to. e.g. passing in 0 will +increase the formatting range to the very first character entered in the document. +@pre aDocPos is in the range 0...DocumentLength +@post aDocPos has been formatted +*/ +EXPORT_C void CTextLayout::ExtendFormattingToCoverPosL(TInt aDocPos) + { + __ASSERT_DEBUG(0 <= aDocPos && aDocPos <= DocumentLength(), + Panic(EInvalidDocPos)); + TTmFormatParam param; + InitFormatParam(param); + param.iStartChar = iText->StartChar(); + param.iEndChar = iText->EndChar(); + param.iMaxHeight = KMaxTInt; + TInt heightIncrease; + TInt p; + TInt pos = aDocPos; + if(pos > 0) // Avoid going into infinite loop. + { + pos -= 1; + } + while ((pos < param.iStartChar) && (iText->AddParL(param, ETrue, heightIncrease, p))) + { + iBandTop += heightIncrease; + param.iStartChar = iText->StartChar(); + } + param.iEndChar = aDocPos + 1; + if(iText->EndChar() < param.iEndChar) + { + iText->ExtendFormattingDownwardsL(param); + } + __ASSERT_DEBUG((aDocPos >= iText->StartChar()) && (aDocPos <= iText->EndChar()), + Panic(ECharacterNotFormatted)); + } + + +/** Sets the formatted text to begin at the start of the paragraph including +aStartPos and end at aEndPos. Moves the line containing aStartDocPos to the top +of the visible area. + +Notes: + +This function is not generally useful; it exists for the convenience of the +printing system. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aStartDocPos A document position within the paragraph from which to +begin formatting. +@param aEndDocPos Document position at which to end formatting. */ +EXPORT_C void CTextLayout::FormatCharRangeL(TInt aStartDocPos,TInt aEndDocPos) + { + FormatCharRangeL(aStartDocPos,aEndDocPos,0); + } + +void CTextLayout::FormatCharRangeL(TInt aStartDocPos,TInt aEndDocPos,TInt aPixelOffset) + { + __ASSERT_DEBUG(aStartDocPos >= 0 && aStartDocPos <= DocumentLength(),Panic(EInvalidDocPos)); + __ASSERT_DEBUG(aEndDocPos >= 0 && aEndDocPos <= DocumentLength(),Panic(EInvalidDocPos)); + __ASSERT_DEBUG(aStartDocPos <= aEndDocPos,Panic(ENoCharRangeToFormat)); + + TTmFormatParam param; + InitFormatParam(param); + param.iStartChar = iSource->ParagraphStart(aStartDocPos); + param.iEndChar = aEndDocPos; + param.iMaxHeight = KMaxTInt; + iText->SetTextL(*iSource,param); + TTmLineInfo info; + TTmDocPos pos(aStartDocPos, ETrue); + if (iText->DocPosToLine(pos,info)) + iBandTop = info.iOuterRect.iTl.iY - aPixelOffset; + else + iBandTop = 0; //+ raise an exception? + } + +/** A special function to support background formatting by the higher level +CTextView class. It formats the next pending line. The return value is ETrue if +there is more formatting to do. On entry, aBotPixel contains the y coordinate +of the bottom of the formatted text; this is updated by the function. + +Notes: + +Not generally useful. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aBotPixel On entry, contains the y coordinate of the bottom of the +formatted text; this is updated by the function. +@return ETrue if there is more formatting to do. EFalse if not. */ +EXPORT_C TBool CTextLayout::FormatNextLineL(TInt& aBottomPixel) + { + if (iUnformattedStart < KMaxTInt) + { + TTmFormatParamBase param; + InitFormatParam(param); + param.iMaxHeight = KMaxTInt; + TTmReformatParam reformat_param; + reformat_param.iStartChar = iUnformattedStart; + reformat_param.iMaxExtraLines = KMaxExtraLines; + reformat_param.iParInvalid = iParInvalid; + TTmReformatResult result; + iText->FormatL(param,reformat_param,result); + + // If there is no formatting to do, indicate that formatting is complete to the end of the paragraph + if (result.iUnformattedStart == KMaxTInt) + { + TTmLineInfo info; + TTmDocPos pos(iUnformattedStart, ETrue); + TBool isFormatted = iText->DocPosToLine(pos,info); + __ASSERT_DEBUG(isFormatted, Panic(EPosNotFormatted)); + isFormatted = iText->ParNumberToLine(info.iParNumber,KMaxTInt,info); + __ASSERT_DEBUG(isFormatted, Panic(EPosNotFormatted)); + aBottomPixel = info.iOuterRect.iBr.iY - iBandTop; + } + + // Indicate that formatting is complete up to the lower edge of the current line. + else + aBottomPixel = result.iRedrawRect.iBr.iY - iBandTop; + iUnformattedStart = result.iUnformattedStart; + } + return iUnformattedStart < KMaxTInt; + } + +/** Controls the height of a single line, for use by the pagination system +only. Using the format supplied in aParaFormat, determines the height of the +line containing aDocPos and returns it in aHeight. Changes aDocPos to the end +of the line and returns ETrue if that position is not the end of the paragraph. + +Notes: + +Not generally useful; it exists for use by the pagination system only. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aParaFormat Contains paragraph formatting. +@param aDocPos A document position. On return, contains the document position +of the end of the line. +@param aHeight On return, contains the height of the formatted line containing +aDocPos. +@param aPageBreak On return, ETrue if the last character on the line is a page +break. EFalse if not. +@return ETrue if the line is not the last line in the paragraph. EFalse if it is +the last line. */ +EXPORT_C TBool CTextLayout::FormatLineL(CParaFormat* /*aParaFormat*/,TInt& aDocPos, + TInt& aHeight,TBool& aPageBreak) + { + // If the line is not formatted, replace the formatted text with the single paragraph containing the line. + if (aDocPos < iText->StartChar() || aDocPos >= iText->EndChar()) + { + TTmFormatParam param; + InitFormatParam(param); + param.iStartChar = iSource->ParagraphStart(aDocPos); + param.iEndChar = iSource->ParagraphEnd(aDocPos); + param.iMaxHeight = KMaxTInt; + iText->SetTextL(*iSource,param); + } + TTmLineInfo info; + TTmDocPos pos(aDocPos, ETrue); + if (!iText->DocPosToLine(pos,info)) + User::Leave(KErrGeneral); + aHeight = info.iOuterRect.Height(); + aDocPos = info.iEnd; + TPtrC text; + TTmCharFormat format; + iSource->GetText(info.iEnd - 1,text,format); + aPageBreak = text[0] == CEditableText::EPageBreak; + + return !(info.iFlags & TTmLineInfo::EParEnd); + } + +/** Scrolls the text up or down by aNumParas paragraphs, disallowing blank +space at the bottom of the visible area if aScrollBlankSpace is +CTextLayout::EFDisallowScrollingBlankSpace. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aNumParas The number of paragraphs to scroll; may be a positive or +negative value. On return, contains the number of paragraphs not scrolled; that +is the difference between the requested number and the number of paragraphs +actually scrolled. +@param aScrollBlankSpace Only relevant when scrolling downwards. +CTextLayout::EFAllowScrollingBlankSpace allows blank space to scroll into the +visible area. CTextLayout::EFDisallowScrollingBlankSpace prevents blank space +from scrolling into the visible area. +@pre aPars must not scroll the display beyond the formatted range. If aPars +scrolls beyond the formatted range, this method will leave with the error code +CTextLayout::EPosNotFormatted +@return The number of pixels actually scrolled. */ +EXPORT_C TInt CTextLayout::ScrollParagraphsL(TInt& aPars,TAllowDisallow aScrollBlankSpace) + { + TTmFormatParam param; + InitFormatParam(param); + param.iMaxHeight = KMaxTInt; + TTmLineInfo info; + int height_increase = 0; + int paragraphs_increase = 0; + int cur_par = 0; + int desired_par = 0; + int pixels_to_scroll = 0; + + if (aPars > 0) + { + if (iText->YPosToLine(iBandTop,info)) + cur_par = info.iParNumber; + else + User::Leave(EPosNotFormatted); + if (info.iParTop < iBandTop) + aPars--; + desired_par = cur_par - aPars; + while (desired_par < 0 && iText->AddParL(param,TRUE,height_increase,paragraphs_increase)) + { + iBandTop += height_increase; + desired_par += paragraphs_increase; + } + aPars = -desired_par; + if (desired_par < 0) + desired_par = 0; + if (!iText->ParNumberToLine(desired_par,0,info)) + User::Leave(EPosNotFormatted); + pixels_to_scroll = iBandTop - info.iOuterRect.iTl.iY; + } + else if (aPars < 0) + { + int band_bottom = iBandTop + VisibleHeightInPixels(); + + // Extend formatting until the visible height is filled. + param.iEndChar = KMaxTInt; + param.iMaxHeight = band_bottom - iText->LayoutHeight(); + if(param.iMaxHeight > 0) + { + iText->ExtendFormattingDownwardsL(param); + } + + if (iText->YPosToLine(band_bottom - 1,info)) + cur_par = info.iParNumber; + else + User::Leave(EPosNotFormatted); + if (!((info.iFlags & TTmLineInfo::EParEnd) && info.iOuterRect.iBr.iY == band_bottom)) + aPars++; + desired_par = cur_par - aPars; + int last_par = iText->Paragraphs() - 1; + while (desired_par > last_par && iText->AddParL(param, EFalse, height_increase,paragraphs_increase)) + last_par += paragraphs_increase; + aPars = last_par - desired_par; + if (desired_par > last_par) + desired_par = last_par; + if (!iText->ParNumberToLine(desired_par,KMaxTInt,info)) + iText->AddParL(param, EFalse, height_increase, paragraphs_increase); + if (!iText->ParNumberToLine(desired_par,KMaxTInt,info)) + User::Leave(EPosNotFormatted); + pixels_to_scroll = band_bottom - info.iOuterRect.iBr.iY; + } + + return ScrollL(pixels_to_scroll,aScrollBlankSpace); + } + +/** Scrolls the text up or down by aNumLines lines, disallowing blank space at +the bottom of the visible area if aScrollBlankSpace is +CTextLayout::EFDisallowScrollingBlankSpace. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aNumLines The number of lines to scroll; may be a positive or negative +value. On return, contains the number of lines not scrolled; that is, the +requested number, minus the number actually scrolled. +@param aScrollBlankSpace Only relevant when scrolling downwards. +CTextLayout::EFAllowScrollingBlankSpace allows blank space to scroll into the +visible area. CTextLayout::EFDisallowScrollingBlankSpace prevents blank space +from scrolling into the visible area. +@pre aLines must not scroll the display beyond the formatted range. If aLines +scrolls beyond the formatted range, this method will leave with the error code +CTextLayout::EPosNotFormatted +@return The number of pixels actually scrolled. */ +EXPORT_C TInt CTextLayout::ScrollLinesL(TInt& aLines,TAllowDisallow aScrollBlankSpace) + { + TTmFormatParam param; + InitFormatParam(param); + param.iMaxHeight = KMaxTInt; + TTmLineInfo info; + int height_increase = 0; + int paragraphs_increase = 0; + int lines_scrolled = aLines; + int visible_height = VisibleHeightInPixels(); + if (aLines > 0) // bring aLines lines into view at the top of the display + { + int desired_top_line_number = 0; + for (;;) + { + // Find the line number of the first visible line. + TBool partial_line = FALSE; + int top_line_number = 0; + if (iBandTop >= iText->LayoutHeight()) + top_line_number = iText->Lines(); + else + { + if (iText->YPosToLine(iBandTop,info)) + top_line_number = info.iLineNumber; + else + User::Leave(EPosNotFormatted); + partial_line = iBandTop > info.iOuterRect.iTl.iY; + } + + // Find the line number of the desired first visible line. + // Defect fix for INC015850. Changed IF so that if the currently + // visible top line is as tall or taller (due to a large font or picture) + // than the visible height of the view our desired top line remains + // the next one above so that a scroll takes place. + desired_top_line_number = top_line_number - aLines; + if (partial_line && (info.iOuterRect.iBr.iY-info.iOuterRect.iTl.iY < visible_height)) + desired_top_line_number++; + + // If the desired first visible line number is negative, more lines need to be formatted. + if (desired_top_line_number >= 0) + break; + if (!iText->AddParL(param,TRUE,height_increase,paragraphs_increase)) + break; + iBandTop += height_increase; + } + + if (desired_top_line_number < 0) + { + lines_scrolled += desired_top_line_number; + desired_top_line_number = 0; + } + aLines -= lines_scrolled; + if (lines_scrolled) + { + if (!iText->LineNumberToLine(desired_top_line_number,info)) + User::Leave(EPosNotFormatted); + // if the line to be scrolled to is taller than the screen, we want + // to make sure that the baseline is not scrolled off the screen. + if (visible_height < info.iBaseline - info.iOuterRect.iTl.iY) + return ScrollL(iBandTop + visible_height - info.iBaseline, aScrollBlankSpace); + return ScrollL(iBandTop - info.iOuterRect.iTl.iY,aScrollBlankSpace); + } + else + return 0; + } + else if (aLines < 0) // bring aLines lines into view at the bottom of the display + { + if (iScrollFlags & EFScrollOnlyToTopsOfLines) + { + // If we are restricting scroll to the tops of lines, then lines at + // bottom are irrelevant, so all we do is lose the top line. + if (!iText->YPosToLine(iBandTop, info)) + User::Leave(EPosNotFormatted); + return ScrollL(-info.iOuterRect.Height(), aScrollBlankSpace); + } + + int desired_bottom_line_number = 0; + int band_bottom = iBandTop + visible_height; + int last_formatted_line = iText->Lines() - 1; + + // Extend formatting until the visible height is filled. + param.iEndChar = KMaxTInt; + param.iMaxHeight = band_bottom - iText->LayoutHeight(); + if(param.iMaxHeight > 0) + { + iText->ExtendFormattingDownwardsL(param); + } + for (;;) + { + // Find the line number of the last visible line. + TBool partial_line = FALSE; + int bottom_line_number = 0; + if (iText->YPosToLine(band_bottom - 1,info)) + bottom_line_number = info.iLineNumber; + else + User::Leave(EPosNotFormatted); + partial_line = band_bottom < info.iOuterRect.iBr.iY; + + // Find the line number of the desired last visible line. + desired_bottom_line_number = bottom_line_number - aLines; + if (partial_line) + desired_bottom_line_number--; + + // If the desired last visible line number is greater than the last line, more lines need to be formatted. + if (desired_bottom_line_number <= last_formatted_line) + break; + if (!AddFormattingAtEndL(param, height_increase,paragraphs_increase)) + break; + last_formatted_line = iText->Lines() - 1; + } + + int shortfall = desired_bottom_line_number - last_formatted_line; + if (shortfall > 0) + { + lines_scrolled += shortfall; + desired_bottom_line_number = last_formatted_line; + } + aLines -= lines_scrolled; + if (lines_scrolled) + { + if (!iText->LineNumberToLine(desired_bottom_line_number,info)) + User::Leave(EPosNotFormatted); + return ScrollL(band_bottom - info.iOuterRect.iBr.iY,aScrollBlankSpace); + } + else + return 0; + } + else + return 0; + } + +/** Scrolls the text up or down by aPixels pixels, disallowing blank space at +the bottom of the visible area if aScrollBlankSpace is +CTextLayout::EFDisallowScrollingBlankSpace. + +The return value (not aPixels, as you would expect from ScrollParagraphsL() and +ScrollLinesL()) contains the number of pixels not successfully scrolled, that +is, the original value of aPixels, minus the number of pixels actually +scrolled. On return, aPixels is set to the number of pixels actually scrolled. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aPixels The number of pixels to scroll; may be a positive or negative +value. On return, contains the number of pixels actually scrolled. +@param aScrollBlankSpace Only relevant when scrolling downwards. +CTextLayout::EFAllowScrollingBlankSpace allows blank space to scroll into the +visible area. CTextLayout::EFDisallowScrollingBlankSpace prevents blank space +from scrolling into the visible area. +@return The difference between the requested number of pixels to scroll and the +number of pixels actually scrolled. */ +EXPORT_C TInt CTextLayout::ChangeBandTopL(TInt& aPixels,TAllowDisallow aScrollBlankSpace) + { + int desired_pixels = aPixels; + aPixels = ScrollL(aPixels,aScrollBlankSpace); + return desired_pixels - aPixels; + } + + + +/** Scrolls the text up or down by aPixels pixels, allowing blank space at +top and bottom of the visible area, which means the scrolling can go beyond the +top or bottom border. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aPixels The number of pixels to scroll; may be a positive or negative +value. The actual scrolled pixel number is always identical to aPixels*/ +EXPORT_C void CTextLayout::ChangeBandTopNoLimitBorderL(TInt aPixels) + { + ScrollL(aPixels,EFAllowScrollingBlankSpace,ETrue,ETrue); + } + + +/** + * Finds a position (in pixels, from the top of the window) where the cursor + * can be such that its line will be fully visible. If this is not possible, + * then return one with its baseline visible. If this is not possible, we don't + * care what the answer is. + */ +TInt CTextLayout::SuggestCursorPos(TInt aCurrentCursorPos) const + { + int visible_height = VisibleHeightInPixels(); + TTmLineInfo info; + if (iText->YPosToLine(iBandTop + aCurrentCursorPos, info)) + { + TBool currentLineHasBaselineVisible = + (TBool)(iBandTop <= info.iBaseline + && info.iBaseline < iBandTop + visible_height); + TInt tryThisLine = -1; + // find a good line to put the cursor on. + if (info.iOuterRect.iTl.iY < iBandTop) + { + // try next line + tryThisLine = info.iLineNumber + 1; + } + else if (iBandTop + visible_height < info.iOuterRect.iBr.iY) + { + tryThisLine = info.iLineNumber - 1; + } + if (0 <= tryThisLine && iText->LineNumberToLine(tryThisLine, info)) + { + if (iBandTop <= info.iOuterRect.iTl.iY + && info.iOuterRect.iBr.iY < iBandTop + visible_height) + // this line fully visible + aCurrentCursorPos = info.iBaseline - iBandTop; + else if (!currentLineHasBaselineVisible + && iBandTop <= info.iBaseline + && info.iBaseline < iBandTop + visible_height) + // not fully visible, but its baseline is, and the original + // line's baseline was not + aCurrentCursorPos = info.iBaseline - iBandTop; + } + } + return aCurrentCursorPos; + } + +/** Scrolls up by a page (that is the band height as set by SetBandHeight(), or +half that amount if scrolling over lines taller than this), moving the text +downwards. The current desired vertical cursor position is passed in +aYCursorPos and updated to a new suggested position as near as possible to it, +but within the visible text and on a baseline. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aYCursorPos The current desired vertical cursor position. On return, +updated to a new suggested position as near as possible to it. +@param aPixelsScrolled On return, contains the number of pixels scrolled. */ +EXPORT_C void CTextLayout::PageUpL(TInt& aYCursorPos,TInt& aPixelsScrolled) + { + // Move the cursor into the visible area. + int visible_height = VisibleHeightInPixels(); + if (aYCursorPos < 0) + aYCursorPos = 0; + else if (aYCursorPos > visible_height) + aYCursorPos = visible_height - 1; + + TTmLineInfo info; + // position the top of the screen must be at least as low as + TInt longestScrollTo = iBandTop + visible_height + - visible_height * KMaxProportionOfScreenToScroll/1000; + // position the top of the screen must be at least as high as + TInt shortestScrollTo = iBandTop + visible_height + - visible_height * KMinProportionOfScreenToScroll/1000; + TInt desiredScrollTo = shortestScrollTo; + // find the line at the top of the screen + // (we cannot find the one that includes the first pixel off the screen + // because it might not have been formatted yet) + if (iText->YPosToLine(iBandTop, info)) + { + // subtract one from the line number if this was on the screen + TInt line = info.iLineNumber + - (info.iOuterRect.iTl.iY < iBandTop? 0 : 1) + + KNumberOfLinesToKeepVisibleDuringScroll; + if (iText->LineNumberToLine(Max(0, line), info)) + desiredScrollTo = info.iOuterRect.iTl.iY; + } + if (shortestScrollTo < desiredScrollTo) + desiredScrollTo = shortestScrollTo; + else if (desiredScrollTo < longestScrollTo) + desiredScrollTo = longestScrollTo; + aPixelsScrolled = ScrollL(iBandTop + visible_height - desiredScrollTo, + EFDisallowScrollingBlankSpace); + aYCursorPos = aPixelsScrolled == 0? + 0 + : SuggestCursorPos(aYCursorPos); + } + +/** Scrolls down by a page (that is the band height as set by SetBandHeight(), +or half that amount if scrolling over lines taller than this), moving the text +upwards. The current desired vertical cursor position is passed in aYCursorPos +and updated to a new suggested position as near as possible to it, but within +the visible text and on a baseline. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aYCursorPos The current desired vertical cursor position. On return, +updated to a new suggested position as near as possible to it. +@param aPixelsScrolled On return, contains the number of pixels scrolled - a +negative value. */ +EXPORT_C void CTextLayout::PageDownL(TInt& aYCursorPos,TInt& aPixelsScrolled) + { + // Move the cursor into the visible area. + int visible_height = VisibleHeightInPixels(); + if (aYCursorPos < 0) + aYCursorPos = 0; + else if (aYCursorPos > visible_height) + aYCursorPos = visible_height - 1; + + TTmLineInfo info; + // position the bottom of the screen must be at least as high as + TInt longestScrollTo = iBandTop + + visible_height * KMaxProportionOfScreenToScroll/1000; + // position the bottom of the screen must be at least as low as + TInt shortestScrollTo = iBandTop + visible_height * KMinProportionOfScreenToScroll/1000; + TInt desiredScrollTo = shortestScrollTo; + // find the line at the bottom of the screen + // (we cannot find the one that includes the first pixel off the screen + // because it might not have been formatted yet) + if (iText->YPosToLine(iBandTop + visible_height - 1, info)) + { + // add one to the line number if this was on the screen + TInt line = info.iLineNumber + + (iBandTop + visible_height < info.iBaseline? 0 : 1) + - KNumberOfLinesToKeepVisibleDuringScroll; + if (iText->LineNumberToLine(Max(0, line), info)) + desiredScrollTo = info.iOuterRect.iBr.iY; + } + if (desiredScrollTo < shortestScrollTo) + desiredScrollTo = shortestScrollTo; + else if (longestScrollTo < desiredScrollTo) + desiredScrollTo = longestScrollTo; + aPixelsScrolled = ScrollL(iBandTop - desiredScrollTo, + EFDisallowScrollingBlankSpace); + aYCursorPos = aPixelsScrolled == 0? + visible_height - 1 + : SuggestCursorPos(aYCursorPos); + + __ASSERT_DEBUG(-visible_height <= aPixelsScrolled, + Panic(EPageScrollError)); + __ASSERT_DEBUG(0 <= aYCursorPos && aYCursorPos <= visible_height, + Panic(EPageScrollError)); + } + +/** Reformats to reflect a single character edit. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aType Indicates the type of edit which has taken place. +CTextLayout::EFCharacterInsert (the default) for a character insertion, +CTextLayout::EFParagraphDelimiter for a paragraph delimiter insertion, +CTextLayout::EFLeftDelete or CTextLayout::EFRightDelete for a character or +paragraph delimiter deletion to the left or right of the document position. +@param aCursorPos The document position at which the edit took place, before +the edit. If this position is not formatted, a panic occurs; it is modified in +accordance with the edit. +@param aGood On return, the y coordinate of the top of the paragraph following +the paragraph which has been edited, before the edit. +@param aFormattedUpTo On return, the y coordinate of the bottom of the +reformatted line or lines, after the edit. +@param aFormattedFrom On return, the vertical layout coordinate of the top of +the reformatted line or lines, after the edit. +@param aScroll The number of pixels by which the text had to be scrolled +(positive means text moved down). +@param aFormatChanged ETrue if text is to be reformatted from the start of the +paragraph the cursor was on before the edit, EFalse if from the start of the +line the cursor was on before the edit. +@return EFalse if no more lines need to be reformatted. ETrue if some more lines +need to be reformatted. */ +EXPORT_C TBool CTextLayout::HandleCharEditL(TUint aType,TInt& aCursorPos,TInt& aGood,TInt& aFormatBottom, + TInt& aFormatTop,TInt& aScroll,TBool aFormatFromStartOfPar) + { + __ASSERT_ALWAYS(iSource->iFormatMode != CLayoutData::EFPrintPreviewMode,Panic(EPrintPreviewModeError)); + __ASSERT_ALWAYS(aType <= EFRightDelete,Panic(EBadCharacterEditType)); + __ASSERT_ALWAYS(!aFormatFromStartOfPar || aType == EFRightDelete || aType == EFLeftDelete,Panic(EBadCharacterEditType)); + __ASSERT_ALWAYS(aCursorPos >= iText->StartChar() && aCursorPos < iText->EndChar(),Panic(ECharacterNotFormatted)); + + // Mark the entire paragraph invalid if background formatting is taking place. + iParInvalid = iUnformattedStart != KMaxTInt; + + // Cancel any pending background formatting, which has now been invalidated by the change. + iUnformattedStart = KMaxTInt; + + // Adjust the cursor position and determine the range of characters to reformat. + TTmReformatParam reformat_param; + reformat_param.iParInvalid = iParInvalid; + switch (aType) + { + case EFCharacterInsert: + case EFParagraphDelimiter: + reformat_param.iStartChar = aCursorPos++; + reformat_param.iNewLength = 1; + break; + case EFLeftDelete: + reformat_param.iStartChar = --aCursorPos; + reformat_param.iOldLength = 1; + break; + case EFRightDelete: + reformat_param.iStartChar = aCursorPos; + reformat_param.iOldLength = 1; + break; + default: break; + } + + // Set up the formatting parameters. + TTmFormatParam param; + InitFormatParam(param); + param.iMaxHeight = KMaxTInt; + + // Format the whole band if necessary. + TTmDocPos cursorPos(aCursorPos, EFalse); + if (reformat_param.iStartChar < iText->StartChar() || reformat_param.iStartChar + reformat_param.iOldLength >= iText->EndChar()) + { + FormatBandL(reformat_param.iStartChar,reformat_param.iStartChar + reformat_param.iOldLength); + aFormatTop = 0; + aFormatBottom = iText->LayoutHeight() - iBandTop; + aGood = aFormatBottom; + aScroll = 0; + ScrollDocPosIntoViewL(cursorPos); + return FALSE; + } + + // Reformat the chosen range. + reformat_param.iMaxExtraLines = KMaxExtraLines; + TTmReformatResult result; + iText->FormatL(param,reformat_param,result); + result.iRedrawRect.Move(0,-iBandTop); + iUnformattedStart = result.iUnformattedStart; + + // Scroll if necessary and extend the redraw area to include material scrolled into view. + aScroll = ScrollDocPosIntoViewL(cursorPos); + if (aScroll > 0) + result.iRedrawRect.iBr.iY += aScroll; + else + result.iRedrawRect.iTl.iY += aScroll; + + // Return coordinates. + aFormatTop = result.iRedrawRect.iTl.iY; + aFormatBottom = result.iRedrawRect.iBr.iY; + aGood = result.iUnchangedTop - iBandTop; + + // Add new paragraphs if necessary. + int visible_height = VisibleHeightInPixels(); + + param.iEndChar = KMaxTInt; + param.iMaxHeight = (iBandTop + visible_height) - iText->LayoutHeight(); + if(param.iMaxHeight > 0) + { + iText->ExtendFormattingDownwardsL(param); + } + + //remove formatting from the end if necessary + PruneFormatL(EFalse); + // Return TRUE if more text needs to be formatted. + return iUnformattedStart < KMaxTInt; + } + +/** Reformats to reflect changes to a block of text. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aSelection The start and new length of the changed block. When +inserting, specify the insertion position. When deleting, specify the position +of the start of the deletion. When reformatting, specify the start and length +of the reformatted block. +@param aOldCharsChanged The old length of the changed block. When inserting, +specify zero. When deleting, specify the number of deleted characters. When +reformatting, specify the number of reformatted characters. +@param aViewChanges On return, contains the top of the reformatted text +(iFormattedFrom), the bottom of the reformatted text (iFormattedTo), the amount +by which the text above the reformatted text has scrolled (iScrollAtTop) and +the amount by which the text below the reformatted text has scrolled +(iScrollAtBottom) (positive values mean the text moves down). +@param aFormatChanged Indicates whether the paragraph format for the first or +last affected paragraph has changed, meaning that the text to be reformatted +must extend out to paragraph boundaries and cannot be restricted to only some +lines. */ +EXPORT_C void CTextLayout::HandleBlockChangeL(TCursorSelection aSelection,TInt aOldLength, + TViewRectChanges& aChanges,TBool aFormatFromStartOfPar) + { + __ASSERT_ALWAYS(iSource->iFormatMode != CLayoutData::EFPrintPreviewMode,Panic(EPrintPreviewModeError)); + + // Do nothing if the selection is outside the formatted range. + if (aSelection.LowerPos() > iText->EndChar() || aSelection.HigherPos() < iText->StartChar()) + { + aChanges.iFormattedFrom = 0; + aChanges.iFormattedTo = 0; + aChanges.iScrollAtTop = 0; + aChanges.iScrollAtBottom = 0; + return; + } + + // Format the whole band if necessary. + TTmDocPos cursorPos(aSelection.iCursorPos, + aSelection.iCursorPos < aSelection.iAnchorPos? ETrue : EFalse); + if (aSelection.LowerPos() < iText->StartChar() || aSelection.LowerPos() + aOldLength >= iText->EndChar()) + { + FormatBandL(aSelection.iCursorPos,aSelection.iCursorPos); + aChanges.iFormattedFrom = 0; + aChanges.iFormattedTo = VisibleHeightInPixels(); + aChanges.iScrollAtTop = 0; + aChanges.iScrollAtBottom = 0; + ScrollDocPosIntoViewL(cursorPos); + return; + } + + // Reformat the chosen range. + TTmFormatParam param; + InitFormatParam(param); + param.iMaxHeight = KMaxTInt; + TTmReformatParam reformat_param; + reformat_param.iStartChar = aSelection.LowerPos(); + reformat_param.iOldLength = aOldLength; + reformat_param.iNewLength = aSelection.Length(); + reformat_param.iParFormatChanged = aFormatFromStartOfPar; + TTmReformatResult result; + iText->FormatL(param,reformat_param,result); + result.iRedrawRect.Move(0,-iBandTop); + + // Scroll if necessary. + int dy; + if(iTextViewCursorPos) + { + dy = ScrollDocPosIntoViewL(iTextViewCursorPos->TmDocPos()); + iTextViewCursorPos = NULL; + } + else + { + dy = ScrollDocPosIntoViewL(cursorPos); + } + result.iRedrawRect.Move(0,dy); + + aChanges.iFormattedFrom = result.iRedrawRect.iTl.iY; + aChanges.iFormattedTo = result.iRedrawRect.iBr.iY; + aChanges.iScrollAtTop = dy; + aChanges.iScrollAtBottom = dy + result.iHeightChange; + + // Extend formatting to fill the band if necessary. + int visible_height = VisibleHeightInPixels(); + + param.iEndChar = KMaxTInt; + param.iMaxHeight = (iBandTop + visible_height) - iText->LayoutHeight(); + if(param.iMaxHeight > 0) + { + iText->ExtendFormattingDownwardsL(param); + } + + //remove formatting from the end if necessary + PruneFormatL(EFalse); + } + +/** Reformats to reflect the addition of one or more complete paragraphs at the +end of the text. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aFirstPixel On return, the top y coordinate of the added material. +@param aLastPixel On return, the bottom y coordinate of the added material. +*/ +EXPORT_C void CTextLayout::HandleAdditionalCharactersAtEndL(TInt& aNewTextTop,TInt& aNewTextBottom) + { + aNewTextTop = aNewTextBottom = iText->LayoutHeight() - iBandTop; + int format_required = BandHeightInPixels() - aNewTextBottom; + if (format_required > 0) + { + TTmFormatParam param; + InitFormatParam(param); + param.iMaxHeight = format_required; + TInt oldHeight = iText->LayoutHeight(); + iText->ExtendFormattingDownwardsL(param); + aNewTextBottom += (iText->LayoutHeight() - oldHeight); + } + } + +/** Reformats to reflect changes to the space above and below paragraphs +(CParaFormat::iSpaceBeforeInTwips and iSpaceAfterInTwips). + +Do not use if a CTextView object owns this CTextLayout object. +@deprecated 6.1 Use FormatBandL() +*/ +EXPORT_C void CTextLayout::ReformatVerticalSpaceL() + { + // Reformat the whole band; only space above and below paragraphs has changed, but who cares? + FormatBandL(); + } + +/** Temporarily changes the vertical alignment of the text with respect to the +visible height. + +Notes: + +Not generally useful. + +Do not use if a CTextView object owns this CTextLayout object. + +@param aVerticalAlignment Specifies whether the formatted text should be placed +at the top (CParaFormat::ETopAlign), vertical centre (CParaFormat::ECenterAlign +or CParaFormat::EJustifiedAlign) or bottom (CParaFormat::EBottomAlign) of the +band. CParaFormat::EUnspecifiedAlign or CParaFormat::ECustomAlign may also be +specified. These values cause the baseline of the first formatted line to be +positioned 82% of the way down the band (provided for the Agenda's +application's year view). */ +EXPORT_C void CTextLayout::AdjustVerticalAlignment(CParaFormat::TAlignment aVerticalAlignment) + { + int excess = BandHeight() - FormattedHeightInPixels(); + int space_before = 0; + __ASSERT_ALWAYS(!IsFormattingBand(),Panic(EMustFormatAllText)); + TTmLineInfo info; + + switch (aVerticalAlignment) + { + case CParaFormat::EAbsoluteLeftAlign: + case CParaFormat::ETopAlign: + break; + case CParaFormat::ECenterAlign: + case CParaFormat::EJustifiedAlign: + space_before = excess / 2; + break; + case CParaFormat::EAbsoluteRightAlign: + case CParaFormat::EBottomAlign: + space_before = excess; + break; + case CParaFormat::EUnspecifiedAlign: + case CParaFormat::ECustomAlign: + if (iText->LineNumberToLine(0,info)) + { + space_before = CLayoutData::EFBaseLinePosition * BandHeight() / 100 - info.iBaseline; + } + else + { + space_before = CLayoutData::EFBaseLinePosition * BandHeight() / 100; + } + break; + } + + iBandTop = -space_before; + } + +static TInt SingleBorderWidthInPixels(const MGraphicsDeviceMap* aGd,const TParaBorder& aBorder,TBool aHoriz) + { + TInt width = aBorder.iThickness; + if (width > 0) + { + if (aHoriz) + width = aGd->VerticalTwipsToPixels(width); + else + width = aGd->HorizontalTwipsToPixels(width); + } + else + width = 1; + return width; + } + +/** Draws paragraph borders, optionally with a background colour for the border +and a clip region. Provided for applications that display a menu of border +styles, like a wordprocessor. + +@param aGd Provides twip-to-pixel conversion. +@param aGc Graphics context to which to draw the border. Its pen settings are +overridden by the values specified by aBorder and its draw mode is set to +CGraphicsContext::EDrawModePEN. +@param aRect The outer bounds of the border. +@param aBorder Specifies the four sides of the border. +@param aBackground If not null, the background colour, (used between double +border lines, or between dots or dashes). +@param aClipRegion If non-null, specifies a clip region. +@param aDrawRect If non-null, and if aClipRegion is non-null, specifies a +rectangle to be subtracted from the clip region. */ +EXPORT_C void CTextLayout::DrawBorders(const MGraphicsDeviceMap* aGd,CGraphicsContext& aGc,const TRect& aBoundingRect, + const TParaBorderArray& aBorder,const TRgb* aBackground,TRegion *aClipRegion, + const TRect* aDrawRect) + { + TPoint pointTl,pointBr; + TRect rect; + TInt * ptrStartLength=NULL; //To stop a warning + TInt * ptrEndLength=NULL; //To stop a warning + TInt * ptrStartWidth=NULL; //To stop a warning + TInt * ptrEndWidth=NULL; //To stop a warning + TInt directionOut=0; //To stop a warning + TInt indexJoint1=0,indexJoint2=0; //To stop a warning + TBool drawAsLine=EFalse; + TRect clipRect; + CGraphicsContext::TPenStyle penStyle[4]; + TInt widthInPixels[4]; + TBool horiz; + const MFormParam* form_param = MFormParam::Get(); + + {for (TInt border=0; border<=3; border++) + { + TParaBorder::TLineStyle lineStyle=aBorder.iBorder[border].iLineStyle; + if (lineStyle == TParaBorder::ENullLineStyle) + { + penStyle[border]=CGraphicsContext::ENullPen; + widthInPixels[border]=0; + continue; + } + else + { + horiz=(border==CParaFormat::EParaBorderTop || border==CParaFormat::EParaBorderBottom); + + widthInPixels[border]=SingleBorderWidthInPixels(aGd,aBorder.iBorder[border],horiz); + } + + if (lineStyle==TParaBorder::ESolid || lineStyle==TParaBorder::EDouble) + { + penStyle[border]=CGraphicsContext::ESolidPen; + continue; + } + + if (lineStyle == TParaBorder::EDashed) + penStyle[border]=CGraphicsContext::EDashedPen; + else if (lineStyle == TParaBorder::EDotted) + penStyle[border]=CGraphicsContext::EDottedPen; + else if (lineStyle == TParaBorder::EDotDash) + penStyle[border]=CGraphicsContext::EDotDashPen; + else if (lineStyle == TParaBorder::EDotDotDash) + penStyle[border]=CGraphicsContext::EDotDotDashPen; + + }} + + {for (TInt border=0; border<=3; border++) + { +// Go to next border, if have NULL linestyle. + if (widthInPixels[border]==0) + continue; + +// Reset clipping region + clipRect.SetSize(TSize(0,0)); + +// Draw as line if not solid lines. + + if (penStyle[border]!=CGraphicsContext::ESolidPen) + drawAsLine=ETrue; + + pointTl=aBoundingRect.iTl; + pointBr=aBoundingRect.iBr; + + if (border==CParaFormat::EParaBorderLeft) + { + pointBr.iX=pointTl.iX; + ptrStartLength=&pointTl.iY; + ptrEndLength=&pointBr.iY; + ptrStartWidth=&pointTl.iX; + ptrEndWidth=&pointBr.iX; + directionOut=-1; + indexJoint1=CParaFormat::EParaBorderTop; + indexJoint2=CParaFormat::EParaBorderBottom; + } + if (border == CParaFormat::EParaBorderRight) + { + pointTl.iX=pointBr.iX; + ptrStartLength=&pointTl.iY; + ptrEndLength=&pointBr.iY; + ptrStartWidth=&pointTl.iX; + ptrEndWidth=&pointBr.iX; + directionOut=1; + indexJoint1=CParaFormat::EParaBorderTop; + indexJoint2=CParaFormat::EParaBorderBottom; + } + if (border == CParaFormat::EParaBorderTop) + { + pointBr.iY=pointTl.iY; + ptrStartLength=&pointTl.iX; + ptrEndLength=&pointBr.iX; + ptrStartWidth=&pointTl.iY; + ptrEndWidth=&pointBr.iY; + directionOut=-1; + indexJoint1=CParaFormat::EParaBorderLeft; + indexJoint2=CParaFormat::EParaBorderRight; + } + if (border == CParaFormat::EParaBorderBottom) + { + pointTl.iY=pointBr.iY; + ptrStartLength=&pointTl.iX; + ptrEndLength=&pointBr.iX; + ptrStartWidth=&pointTl.iY; + ptrEndWidth=&pointBr.iY; + directionOut=1; + indexJoint1=CParaFormat::EParaBorderLeft; + indexJoint2=CParaFormat::EParaBorderRight; + } + + if (!ptrStartWidth || !ptrEndWidth) + { + continue; + } + + if (drawAsLine) + { + if (directionOut<0) + { + (*ptrStartWidth)+=(widthInPixels[border]-1)/2; + (*ptrEndWidth)+=(widthInPixels[border]-1)/2; + } + else + { + (*ptrStartWidth)-=(widthInPixels[border]+2)/2; + (*ptrEndWidth)-=(widthInPixels[border]+2)/2; + } + (*ptrStartLength)+=(widthInPixels[border]-1)/2; + (*ptrEndLength)-=(widthInPixels[border])/2; + } + else + { + if (directionOut<0) + (*ptrEndWidth)+=widthInPixels[border]; + else + (*ptrStartWidth)-=widthInPixels[border]; + } + +// Colour of pen as is - NO logical combination with background etc. + aGc.SetDrawMode(CGraphicsContext::EDrawModePEN); + + if (drawAsLine) + { +// Must draw lines in background colour first, as have dotted/dashed lines. + aGc.SetPenSize(TSize(widthInPixels[border],widthInPixels[border])); + if (aBackground) + { + FormUtil::SetPenColor(form_param,&aGc,*aBackground); + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + aGc.DrawLine(pointTl,pointBr); + } + FormUtil::SetPenColor(form_param,&aGc,aBorder.iBorder[border].iColor); + aGc.SetPenStyle(penStyle[border]); + aGc.DrawLine(pointTl,pointBr); + (*ptrStartWidth)-=(widthInPixels[border]-1)/2; + (*ptrEndWidth)+=(widthInPixels[border]+2)/2; + (*ptrStartLength)-=(widthInPixels[border]-1)/2; + (*ptrEndLength)+=(widthInPixels[border])/2; + clipRect.SetRect(pointTl,pointBr); + } + else + { +// Brush + FormUtil::SetBrushColor(form_param,&aGc,aBorder.iBorder[border].iColor); + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetPenStyle(CGraphicsContext::ENullPen); + rect.SetRect(pointTl,pointBr); + aGc.DrawRect(rect); + clipRect=rect; + }; + +// Repeat draw, for double border. + if (aBorder.iBorder[border].iLineStyle==TParaBorder::EDouble) // Now have only got solid border, drawn as rect. + { + __ASSERT_DEBUG(!drawAsLine,Panic(EDrawingBorderError)); + (*ptrStartWidth)-=directionOut*widthInPixels[border]; + (*ptrEndWidth)-=directionOut*widthInPixels[border]; + (*ptrStartLength)+=widthInPixels[indexJoint1]; + (*ptrEndLength)-=widthInPixels[indexJoint2]; + + if (aBackground) + { + rect.SetRect(pointTl,pointBr); + FormUtil::SetBrushColor(form_param,&aGc,*aBackground); + aGc.DrawRect(rect); + } + + (*ptrStartWidth)-=directionOut*widthInPixels[border]; + (*ptrEndWidth)-=directionOut*widthInPixels[border]; + + if (aBorder.iBorder[indexJoint1].iLineStyle==TParaBorder::EDouble) + (*ptrStartLength)+=widthInPixels[indexJoint1]; + if (aBorder.iBorder[indexJoint2].iLineStyle==TParaBorder::EDouble) + (*ptrEndLength)-=widthInPixels[indexJoint2]; + + rect.SetRect(pointTl,pointBr); + FormUtil::SetBrushColor(form_param,&aGc,aBorder.iBorder[border].iColor); + aGc.DrawRect(rect); + clipRect.BoundingRect(rect); + }; + + +// Restore defaults + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + aGc.SetPenSize(TSize(1,1)); +// Should change to BACKGROUND colour. + if (aBackground) + FormUtil::SetBrushColor(form_param,&aGc,*aBackground); +// If have to clip region, then remove rectangles corresponding to the border region. + + if (aClipRegion) + { + if (aDrawRect) + clipRect.Intersection(*aDrawRect); + aClipRegion->SubRect(clipRect); + } + + }}; + + if (aClipRegion) + { + aClipRegion->Tidy(); + ((CWindowGc *) &aGc)->SetClippingRegion(*aClipRegion); + } + + } + +/** Draws the text. Draws any lines that intersect aDrawRect, which is +specified in window coordinates. The drawing parameters, including the graphics +context, are given in aDrawTextLayoutContext. If aHighlight is non-null, +highlights (by exclusive-ORing) the specified range of text. + +@param aDrawRect The function draw the lines within the visible area, which +intersect this rectangle (which is specified in window coordinates). +@param aDrawTextLayoutContext Provides a graphics context and other parameters +for the function. +@param aHighlight If not NULL, this range of text is drawn highlighted. */ +EXPORT_C void CTextLayout::DrawL(const TRect& aDrawRect,const TDrawTextLayoutContext* aDrawTextLayoutContext, + const TCursorSelection* aHighlight) + { + // Set the drawing parameters in the MTmSource interface. + iSource->iFormParam = MFormParam::Get(); + iSource->iLabelsGutter = aDrawTextLayoutContext->iGutterMarginWidth; + + // Calculate the top left corner of the text. + TPoint top_left = aDrawTextLayoutContext->TopLeftText(); + top_left.iY -= iBandTop; + + // Get the graphics context. + CGraphicsContext* gc = aDrawTextLayoutContext->PrimaryGc(); + + /* + Clip the draw rectangle to the view rectangle, and clip it further to exclude + a final partial line if necessary. + */ + TRect clip_rect(aDrawRect); + clip_rect.Intersection(aDrawTextLayoutContext->iViewRect); + + + if (aDrawTextLayoutContext->UseClippingRect()) + { + gc->SetClippingRect(clip_rect); + } + + // Draw the text and background. + + TBool isDrawingOnAWindowDC = aDrawTextLayoutContext->UseWindowGc(); + + if (isDrawingOnAWindowDC) + { + BeginRedraw(clip_rect); + } + + iText->DrawLayout(*gc,top_left,clip_rect,&aDrawTextLayoutContext->iBackgroundColor,TRUE, aHighlight, iHighlightExtensions); + + if (isDrawingOnAWindowDC) + { + EndRedraw(); + } + + iSource->iFormParam = NULL; + } + +/** Default constructor. + +The start and end positions are set to zero - Set() should be called to +initialise the object. */ +EXPORT_C CTextLayout::TRangeChange::TRangeChange() + : iA(0), iB(0) {} + +/** Sets the start and end positions and whether the highlighting should be +set or cleared. + +Called by the non-default constructor. The start and end positions can be +specified in any order. + +@param aStart The start of the range. +@param aEnd The end of the range. +@param aChange Whether the highlighting should be set or cleared. */ +EXPORT_C void CTextLayout::TRangeChange::Set(TInt aStart, TInt aEnd, + CTextLayout::TRangeChange::TChangeType aChange) + { + if ((aChange == ESet && aStart < aEnd) + || (!(aChange == ESet) && !(aStart < aEnd))) + { + iA = aStart; + iB = aEnd; + } + else + { + iA = aEnd; + iB = aStart; + } + } + +/** Constructor with a start and end position and whether the highlighting +in the range should be set or cleared. + +The start and end positions can be specified in any order. + +@param aStart The start position. +@param aEnd The end position. +@param aChange Specifies whether the highlighting should be set or cleared. +*/ +EXPORT_C CTextLayout::TRangeChange::TRangeChange(TInt aStart, TInt aEnd, + CTextLayout::TRangeChange::TChangeType aChange) + { + Set(aStart, aEnd, aChange); + } + +/** Gets the start and end of the range and whether the highlighting should be +set or cleared. + +@param aStart On return, the start of the range. This is always the lesser of +the two positions. +@param aEnd On return, the end of the range. This is always the greater of the +two positions. +@return Specifies whether the highlighting should be set or cleared. */ +EXPORT_C CTextLayout::TRangeChange::TChangeType + CTextLayout::TRangeChange::Get(TInt& aStart, TInt& aEnd) const + { + if (iA < iB) + { + aStart = iA; + aEnd = iB; + return ESet; + } + aStart = iB; + aEnd = iA; + return EClear; + } + +/** Tests whether the range is not null. + +@return ETrue if the range is not of zero length, EFalse if the range is of zero +length. */ +EXPORT_C TBool CTextLayout::TRangeChange::NonNull() const + { + return iA - iB; + } + +/** Clips the range so that its start and end positions are within the minimum +and maximum positions specified. + +@param aMin The minimum value for the start and end of the range. +@param aMax The maximum value for the start and end of the range. +@return ETrue if the resulting range is not of zero length, EFalse if it is of +zero length. */ +EXPORT_C TBool CTextLayout::TRangeChange::Clip(TInt aMin, TInt aMax) + { + if (iA < aMin) + iA = aMin; + if (iB < aMin) + iB = aMin; + if (aMax < iA) + iA = aMax; + if (aMax < iB) + iB = aMax; + return iA - iB; + } + +/** Try to cancel out sections of the ranges that overlap Merges two ranges of + characters. + +Two successive calls to CTextLayout::Highlight() could cause unecessary flicker +or redrawing if the arguments to each call overlap. For example, if extending a +highlight involved removing the old highlight and then drawing the new one, +this would cause visible flicker. This can be eliminated by calling this +function to remove any overlap between the two ranges. If there is overlap, +this range is set to the result of the merge, and the other range (aBuddy) is +set to zero. + +When calling this function, it does not matter whether or not the two ranges +overlap. Also it does not matter which range is the parameter and which is the +calling object. After calling OptimizeWith(), it is guaranteed that the +resulting ranges will not overlap, and they will represent the same change to +the highlight as the original two ranges. + +See the code fragment in the class description for TRangeChange for an example +of how this function is used. + +@param aBuddy The range of characters to combine with this range. */ +EXPORT_C void CTextLayout::TRangeChange::OptimizeWith(TRangeChange& aBuddy) + { + // we make this have the minimum iA and iB, and aBuddy have the maximum + if (aBuddy.iA < iA) + { + TInt temp = aBuddy.iA; + aBuddy.iA = iA; + iA = temp; + } + if (aBuddy.iB < iB) + { + TInt temp = aBuddy.iB; + aBuddy.iB = iB; + iB = temp; + } + // if they now overlap, we combine them into one and zero the other + if (aBuddy.iB <= iA) + iA = aBuddy.iB = aBuddy.iA; + else if (aBuddy.iA <= iB) + iB = aBuddy.iA = aBuddy.iB; + } + + +TBool CTextLayout::TRangeChange::IsJoinedTo(const TRangeChange aRange) + { + TInt a1 = (iA < iB) ? iA : iB; + TInt b1 = (iA < iB) ? iB : iA; + TInt a2 = (aRange.iA < aRange.iB) ? aRange.iA : aRange.iB; + TInt b2 = (aRange.iA < aRange.iB) ? aRange.iB : aRange.iA; + + return a2 <= b1 && a1 <= b2; + } + +void CTextLayout::TRangeChange::Join(const TRangeChange aRange) + { + TInt a1 = (iA < iB) ? iA : iB; + TInt b1 = (iA < iB) ? iB : iA; + TInt a2 = (aRange.iA < aRange.iB) ? aRange.iA : aRange.iB; + TInt b2 = (aRange.iA < aRange.iB) ? aRange.iB : aRange.iA; + + // type set to ESet + iA = (a1 < a2) ? a1 : a2; + iB = (b1 > b2) ? b1 : b2; + } + + +/** Sets or clears a highlight. + +If the range of characters to highlight is of zero length, the function has no +effect. + +The function affects only those lines that intersect aDrawRect, which is +specified in window coordinates. The drawing parameters, including the graphics +context, are given in aDrawTextLayoutContext. + +From v7.0, this function replaces InvertRangeL(). + +This function is not intended to be used to set any part of a highlight already +set, nor to clear any piece of text not highlighted. It is intended to do +either or both of: clear an existing selection, set a new selection. See the +class description for TRangeChange for a code fragment showing how this +function should be used. + +@param aHighlight Specifies the range of characters to highlight or from which +to remove the highlight. +@param aDrawRect Only lines which intersect this rectangle are affected +(specified in window coordinates). +@param aDrawTextLayoutContext Provides a graphics context and other drawing +parameters, e.g. the text and background colours for the highlighted region. */ + +EXPORT_C void CTextLayout::Highlight(const CTextLayout::TRangeChange& aChangeHighlight, + const TRect& aDrawRect, const TDrawTextLayoutContext* aDrawTextLayoutContext) + { + if (!aChangeHighlight.NonNull()) + return; + + TRect clip_rect(aDrawRect); + + CGraphicsContext* gc = aDrawTextLayoutContext->PrimaryGc(); + if (aDrawTextLayoutContext->UseClippingRect()) + gc->SetClippingRect(clip_rect); + + TInt visible_start; + TInt visible_length = PosRangeInBand(visible_start); + + TInt start_pos; + TInt end_pos; + + CTextLayout::TRangeChange::TChangeType type = aChangeHighlight.Get(start_pos, end_pos); + start_pos = start_pos < visible_start? visible_start : start_pos; + end_pos = end_pos < visible_start + visible_length? end_pos : start_pos + visible_length; + TCursorSelection selection(start_pos, end_pos); + + TPoint top_left = aDrawTextLayoutContext->TopLeftText(); + top_left.iY -= iBandTop; + + TBool isDrawingOnAWindowDC = aDrawTextLayoutContext->UseWindowGc(); + + TRect boundingRect; + iText->GetUpdateBoundingRect(start_pos, end_pos, top_left, boundingRect); + iHighlightExtensions->AbsExtendRect(boundingRect); + boundingRect.Intersection(clip_rect); + if (! boundingRect.IsEmpty()) + { + if (isDrawingOnAWindowDC) + { + BeginRedraw(boundingRect); + } + iText->DrawLayout(*gc, top_left, boundingRect, &aDrawTextLayoutContext->iBackgroundColor, TRUE, &selection, NULL); + if (isDrawingOnAWindowDC) + { + EndRedraw(); + } + } + } + +void CTextLayout::HighlightUsingExtensions(const CTextLayout::TRangeChange& aChangeHighlight,const TRangeChange& aFullHighlight, + const TRect& aDrawRect, const TDrawTextLayoutContext* aDrawTextLayoutContext) + { + if (!aChangeHighlight.NonNull()) + return; + + TRect clip_rect(aDrawRect); + clip_rect.Intersection(aDrawTextLayoutContext->TextArea()); + + CGraphicsContext* gc = aDrawTextLayoutContext->PrimaryGc(); + if (aDrawTextLayoutContext->UseClippingRect()) + { + gc->SetClippingRect(clip_rect); + } + + TInt visible_start; + TInt visible_length = PosRangeInBand(visible_start); + TInt start_pos; + TInt end_pos; + CTextLayout::TRangeChange::TChangeType type = aChangeHighlight.Get(start_pos, end_pos); + start_pos = start_pos < visible_start? visible_start : start_pos; + end_pos = end_pos < visible_start + visible_length? end_pos : start_pos + visible_length; + + TInt full_start_pos; + TInt full_end_pos; + (void)aFullHighlight.Get(full_start_pos, full_end_pos); + full_start_pos = full_start_pos < visible_start? visible_start : full_start_pos; + full_end_pos = full_end_pos < visible_start + visible_length? full_end_pos : full_start_pos + visible_length; + TCursorSelection selection(full_start_pos, full_end_pos); + + TPoint top_left = aDrawTextLayoutContext->TopLeftText(); + top_left.iY -= iBandTop; + + TBool isDrawingOnAWindowDC = aDrawTextLayoutContext->UseWindowGc(); + + TRect boundingRect; + iText->GetUpdateBoundingRect(start_pos, end_pos, top_left, boundingRect); + iHighlightExtensions->AbsExtendRect(boundingRect); + boundingRect.Intersection(clip_rect); + if (! boundingRect.IsEmpty()) + { + if (isDrawingOnAWindowDC) + { + BeginRedraw(boundingRect); + } + iText->DrawLayout(*gc, top_left, boundingRect, &aDrawTextLayoutContext->iBackgroundColor, TRUE, &selection, iHighlightExtensions); + if (isDrawingOnAWindowDC) + { + EndRedraw(); + } + } + + if (aDrawTextLayoutContext->UseClippingRect()) + { + gc->CancelClippingRect(); + } + } + +/** Toggles the selection highlight for the range of text in aHighlight. + +Highlights only those lines that intersect aDrawRect, which is specified in +window coordinates. The drawing parameters, including the graphics context, are +given in aDrawTextLayoutContext. + +In v7.0 and onwards, this function is deprecated -Highlight() should be used +instead. +@deprecated +@param aHighlight The range of characters for which to invert the highlighting. +@param aDrawRect Only lines which intersect this rectangle are affected; +specified in window coordinates. +@param aDrawTextLayoutContext Provides a graphics context and other drawing +parameters. */ +EXPORT_C void CTextLayout::InvertRangeL(const TCursorSelection& aHighlight,const TRect& aDrawRect, + const TDrawTextLayoutContext* aDrawTextLayoutContext) + { + TRangeChange range(aHighlight.iAnchorPos, aHighlight.iCursorPos, TRangeChange::ESet); + HighlightUsingExtensions(range,range,aDrawRect,aDrawTextLayoutContext); + } + +/** +Return the FORM major version number. This function is not generally useful. It +is used in test code and was used while making a transition between this and +the former version of FORM. The return value is always 2. +*/ +EXPORT_C TInt CTextLayout::MajorVersion() const + { + return 2; + } + +/** +This method allows Form clients to register an object able to +create or return references to customisation objects used within Form for +various tasks e.g. inline text. +@param aProvider + Reference to interface provider object to register with Formm. +*/ +EXPORT_C void CTextLayout::SetInterfaceProvider( MFormCustomInterfaceProvider* aProvider ) + { + iSource->iInterfaceProvider = aProvider; + } + +/** Gets the width and height of the bounding box of the text, including +indents and margins, when formatted to the specified wrap width. + +This is useful for applications like a web browser that need to determine the +minimum width for a piece of text: if you specify zero as the wrap width, the +returned aSize.iWidth contains the minimum width that could be used for the +text without illegal line breaks, and if you specify KMaxTInt for aWrapWidth, +the returned aSize.iHeight contains the minimum height: the height when each +paragraph is a single line of unlimited length. + @since 6.0 +@param aWrapWidth The wrap width for the bounding box. +@param aSize On return, contains the width and height of the bounding box. */ +EXPORT_C void CTextLayout::GetMinimumSizeL(TInt aWrapWidth,TSize& aSize) + { + // + //Get the size of the minimal bounding box of the text when formatted to the specified wrap width. + //The width may be greater than aWrapWidth. To find the minimum width for the text, + //pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth. + // + iText->GetMinimumLayoutSizeL(aWrapWidth,aSize); + } + +/** Gets the width and height of the bounding box of the text, including +indents and margins, when formatted to the specified wrap width. + +This is useful for applications like a web browser that need to determine the +minimum width for a piece of text: if you specify zero as the wrap width, the +returned aSize.iWidth contains the minimum width that could be used for the +text, and if you specify KMaxTInt for aWrapWidth, the returned aSize.iHeight +contains the minimum height: the height when each paragraph is a single +line of unlimited length. Use aAllowLegalLineBreaksOnly to set whether or +not illegal line breaks should be considered when determining aSize. + @since 6.0 +@param aWrapWidth The wrap width for the bounding box. +@param aAllowLegalLineBreaksOnly ETrue to only allow legal line breaks, or EFalse to also allow illegal line breaks. +@param aSize On return, contains the width and height of the bounding box. */ +EXPORT_C void CTextLayout::GetMinimumSizeL(TInt aWrapWidth,TBool aAllowLegalLineBreaksOnly,TSize& aSize) + { + // + //Get the size of the minimal bounding box of the text when formatted to the specified wrap width. + //The width may be greater than aWrapWidth. To find the minimum width for the text, + //pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth. + // + iText->GetMinimumLayoutSizeL(aWrapWidth,aAllowLegalLineBreaksOnly,aSize); + } + +/** Sets the custom drawing object, for customising the way text and its +background are drawn. +@since 6.0 +@param aCustomDraw Pointer to a custom drawing object. */ +EXPORT_C void CTextLayout::SetCustomDraw(const MFormCustomDraw* aCustomDraw) + { + iSource->iCustomDraw = aCustomDraw; + } + +/** Returns a pointer to the current custom drawing implementation. Returns +NULL if custom drawing is not in force. +@since 6.0 +@return Pointer to the custom drawing object. */ +EXPORT_C const MFormCustomDraw* CTextLayout::CustomDraw() const + { + return iSource->iCustomDraw; + } + +/** Sets custom line breaking. + +If this function is not called, default line breaking behaviour is used. + +Ownership of the custom line breaking object is not transferred to this object. + +@param aCustomWrap A pointer to an object that implements the custom line +breaking interface. Specify NULL to disable custom line breaking. */ +EXPORT_C void CTextLayout::SetCustomWrap(const MFormCustomWrap* aCustomWrap) + { + iSource->iCustomWrap = aCustomWrap; + } + +/** Gets the custom line breaking object, as set using SetCustomWrap(). + +@return A pointer to the custom line breaking object, or NULL if custom line +breaking is not in effect. */ +EXPORT_C const MFormCustomWrap* CTextLayout::CustomWrap() const + { + return iSource->iCustomWrap; + } + +/** +@internalAll +@released +*/ +EXPORT_C void MFormCustomDraw::MFormCustomDraw_Reserved_2() + { + } + +/** This function is called whenever part of the background of a CTextLayout or +CTextView object needs to be drawn. The default implementation fills +aParam.iDrawRect with the colour specified in aBackground. + +The default background colour is contained in aBackground. This is the +background colour of the paragraph if drawing text, or the background colour +specified in the TDrawTextLayoutContext object passed to CTextLayout::DrawL() +if drawing outside the text area. + +The rectangle which is drawn by this function, (this may not be the whole of +aParam.iDrawRect) must be returned in aDrawn; areas not drawn by you are +automatically filled using the colour aBackground. + +@param aParam Contains the drawing parameters: aParam.iGc is the graphics +context to use. aParam.iMap is the graphics device map, which allows you to +convert between pixels and twips and create fonts. aParam.iTextLayoutTopLeft is +the origin of the text; bitmaps and other graphics must be drawn relative to +this position. aParam.iDrawRect is the area to be drawn; do not draw outside +this rectangle. +@param aBackground The default background colour. This is the background colour +of the paragraph if drawing text, or the background colour specified in the +TDrawTextLayoutContext object passed to CTextLayout::DrawL() if drawing outside +the text area. +@param aDrawn Must return the rectangle you actually draw. This may not be the +whole of aParam.iDrawRect (for instance, if you are drawing a non-tiled bitmap +that occupies only part of aRect). */ +EXPORT_C void MFormCustomDraw::DrawBackground(const TParam& aParam,const TRgb& aBackground,TRect& aDrawn) const + { + MTmCustom c; + c.DrawBackground(aParam.iGc,aParam.iTextLayoutTopLeft,aParam.iDrawRect,aBackground,aDrawn); + } + +/** This function is called after the background has been drawn by +DrawBackground(), and before drawing the text. This function might be used to +draw a ruled line under each line of text. + +The default implementation of this function does nothing. + +@param aParam Contains the drawing parameters. You should only draw to +aParam.iDrawRect. There is no need to fill aParam.iDrawRect or to indicate the +rectangle drawn. +@param aLineInfo Contains the line metrics: aLineInfo.iOuterLineRect specifies +the bounding rectangle of the line, including margins, indents and automatic +space above and below paragraphs, aLineInfo.iInnerLineRect specifies the bounds +of the text only, aLineInfo.iBaseline specifies the baseline of the text. */ +EXPORT_C void MFormCustomDraw::DrawLineGraphics(const TParam& /*aParam*/,const TLineInfo& /*aLineInfo*/) const + { + // do nothing + } + +/** This function is called to draw the text and its highlighted background, if +any, after bidirectional reordering and other character mappings have taken +place. + +The default implementation of this function draws the text with no special +effects and supports standard, round-cornered and shadowed highlighting only. +The text is drawn with the left end of its baseline located at aTextOrigin +after drawing the background, if any, in aParam.iDrawRect. + +The main reason to override this function is to apply custom text highlighting, +(for this, aFormat.iFontPresentation.iHighlightStyle should be in the range +EFontHighlightFirstCustomStyle to EFontHighlightLastCustomStyle). + +The horizontal spacing between the characters in the text string is increased +by the number of pixels specified in aExtraPixels. The standard way to do this +is by calling CGraphicsContext::SetCharJustification(). + +The font and other graphics parameters (e.g. pen colour, font style), are +specified in aParam.iGc but a character format container (aFormat) is supplied +so that a different font can be used. Note that any graphics drawn cannot +exceed the bounds of aParam.iDrawRect, so changes are usually restricted to +drawing shadows, outlines, etc. if custom highlighting is in use. + +@param aParam Contains the drawing parameters. Drawing can only occur within +aParam.iDrawRect. +@param aLineInfo Contains the line metrics. +@param aFormat Specifies the character formatting to apply to the text, +including the type of text highlighting. +@param aText The text string to be drawn. +@param aTextOrigin The point at which the left end of the baseline of the text +should be drawn. +@param aExtraPixels The number of additional pixels to insert between the +characters in the text string, in order to increase its length. */ +EXPORT_C void MFormCustomDraw::DrawText(const TParam& aParam,const TLineInfo& aLineInfo,const TCharFormat& aFormat, + const TDesC& aText,const TPoint& aTextOrigin,TInt aExtraPixels) const + { + TTmLineInfo info; + info.iOuterRect = aLineInfo.iOuterRect; + info.iInnerRect = aLineInfo.iInnerRect; + info.iBaseline = aLineInfo.iBaseline; + + MTmCustom c; + c.DrawText(aParam.iGc,aParam.iTextLayoutTopLeft,aParam.iDrawRect,info,aFormat, + aText,aTextOrigin,aExtraPixels); + } + +EXPORT_C void MFormCustomDraw::DrawText(const TParam& aParam,const TLineInfo& aLineInfo,const TCharFormat& aFormat, + const TDesC& aText,const TInt aStart, const TInt aEnd, const TPoint& aTextOrigin,TInt aExtraPixels) const + { + TTmLineInfo info; + info.iOuterRect = aLineInfo.iOuterRect; + info.iInnerRect = aLineInfo.iInnerRect; + info.iBaseline = aLineInfo.iBaseline; + + MTmCustomExtension c; + c.DrawText(aParam.iGc,aParam.iTextLayoutTopLeft,aParam.iDrawRect,info,aFormat, + aText,aStart,aEnd,aTextOrigin,aExtraPixels); + } + +/** This function translates logical colours specified in FORM objects into +real colours. The default implementation just returns the default colour that +is passed in and ignores aColorIndex. + +Overriding implementations may use aColorIndex in any desired way, either to +replace or modify aDefaultColor. The values used in aColorIndex are taken from +the top byte of a TLogicalRgb object and are thus in the range 0...255. The +TLogicalRgb class defines two reserved values: +TLogicalRgb::ESystemForegroundIndex = 254 and +TLogicalRgb::ESystemBackgroundIndex = 255. +*/ +EXPORT_C TRgb MFormCustomDraw::SystemColor(TUint /*aColorIndex*/,TRgb aDefaultColor) const + { + return aDefaultColor; + } + +void CTextLayout::DrawBackground(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aClipRect, + const TLogicalRgb& aBackground) const + { + TPoint top_left(aTopLeft); + top_left.iY -= iBandTop; + iText->DrawBackground(aGc,top_left,aClipRect,aBackground); + } + +/** Returns the line break class for a Unicode character. + +For convenience, it also gets the range of consecutive characters (if any) +according to the Unicode standard, including aCode, that share the same line +break class. + +The Unicode line break classes are enumerated in class MTmCustom. + +Each character's line break class is obtained using LineBreakClass(). To find +out whether a line break is allowed between two adjacent characters, call +LineBreakPossible() with the line break classes of the two characters as +arguments. For example, the line break class EClLineBreakClass (closing +punctuation) applies to characters such as ")", "]" and ";". Line breaks are +typically allowed after these characters, but not before, so a call to +LineBreakPossible() with the arguments (EAlLineBreakClass, EClLineBreakClass) +would return EFalse in the default implementation, but a call with +(EClLineBreakClass, EAlLineBreakClass) would return ETrue. + +@param aCode The Unicode character code of interest. +@param aRangeStart On return, contains the Unicode character code at the start +of the range including aCode that shares the same line break class as aCode. +@param aRangeEnd On return, contains the Unicode character code at the end of +the range including aCode that shares the same line break class as aCode. +@return The line break class assigned to the character. Line break classes are +enumerated in class MTmCustom. */ + EXPORT_C TUint MFormCustomWrap::LineBreakClass(TUint aCode,TUint& aRangeStart,TUint& aRangeEnd) const + { + // Create an instance of MTmCustom and then call the MTmCustom's functions for getting a Line Break class + MTmCustom c; + TUint temp; + temp=c.LineBreakClass(aCode,aRangeStart,aRangeEnd); + return temp; + } + +/** Tests whether a line break is possible between two characters. + +If aHaveSpaces is true, the characters are not adjacent one or more space +characters (with a line break class of ESpLineBreakClass) occur between them. + +The aPrevClass and aNextClass arguments never have the value ESpLineBreakClass. +Instead, this function is called with the classes of the characters on either +side of the space or run of spaces, (and if so, aHaveSpaces is true). This is +so that line breaks can be prohibited between certain characters with +intervening spaces, for instance an alphabetic character (EAlLineBreakClass, +such as 'a') and a closing bracket, with a space inbetween. + +Additionally, the arguments to this function never have a value of +ESaLineBreakClass. For such characters, GetLineBreakInContext() is called +instead. + +@param aPrevClass The line break class of the previous non-space character. +@param aNextClass The line break class of the next non-space character. +@param aHaveSpaces ETrue if there are one or more space characters (with a line +break class of ESpLineBreakClass) between aPrevClass and aNextClass. EFalse if +not. +@return ETrue if a line break is possible between characters with the two line +break classes, EFalse if not. */ +EXPORT_C TBool MFormCustomWrap::LineBreakPossible(TUint aPrevClass,TUint aNextClass,TBool aHaveSpaces) const + { + MTmCustom c; + TBool temp; + temp=c.LineBreakPossible(aPrevClass,aNextClass,aHaveSpaces); + return temp; + } + +/** Gets the position of the first or last possible line break position in a +text string. + +This function is called instead of LineBreakPossible() for runs of characters +of class ESaLineBreakClass. It is used for South Asian languages like Thai, Lao +and Khmer that have no spaces between words, so that line breaks must be +calculated using dictionary lookup or a linguistic algorithm. + +The default implementation of this function just returns false. + +@param aText A string containing characters of class ESaLineBreakClass. +@param aMinBreakPos A position within aText at which to begin searching for a +possible line break position. +@param aMaxBreakPos A position within aText at which to stop searching for a +possible line break position. +@param aForwards If ETrue, the function gets the first possible line break +position (searches forwards from aMinBreakPos); if EFalse, gets the last one +(searches backwards from aMaxBreakPos). +@param aBreakPos On return, the position of the first or last possible line +break within aText. This must be greater than zero and less than aText.Length() +- 1, and must also be in the range aMinBreakPos to aMaxBreakPos. +@return ETrue if a possible line break position is found, EFalse if not. */ +EXPORT_C TBool MFormCustomWrap::GetLineBreakInContext(const TDesC& aText,TInt aMinBreakPos,TInt aMaxBreakPos, + TBool aForwards,TInt& aBreakPos) const + { + MTmCustom c; + TBool temp; + temp=c.GetLineBreakInContext(aText,aMinBreakPos,aMaxBreakPos,aForwards,aBreakPos); + return temp; + } + +/** Tests whether a character can overhang the right margin. + +This function can be overridden to customise the line breaking behaviour for +closing punctuation in Japanese. Any characters for which this function returns +ETrue are allowed to overhang the right margin. The rest will be moved to the +next line. + +The default implementation of this function just returns false. + +@param aChar The Unicode character code of interest. +@return ETrue if the character specified can overhang the right margin, EFalse if +not. */ +EXPORT_C TBool MFormCustomWrap::IsHangingCharacter(TUint aChar) const + { + MTmCustom c; + TBool temp; + temp=c.IsHangingCharacter(aChar); + return temp; + } + +// Reserved functions are private until they are used +/** + @internalAll + @released + */ +EXPORT_C void MFormCustomWrap::MFormCustomWrap_Reserved_1() + { + // reserved functions + } +// Reserved functions are private until they are used. +/** + @internalAll + @released + */ + +EXPORT_C void MFormCustomWrap::MFormCustomWrap_Reserved_2() + { + // reserved functions + } + +#ifdef _DEBUG +TBool CTextLayout::__DbgIsFormattingUpToDate() const + { + return iUnformattedStart == KMaxTInt; + } +#endif + +// TLayDocTextSource stuff begins here. +TLayDocTextSource::TLayDocTextSource(): + iLayDoc(NULL), + iFlags(EWrap), + iWidth(KMaxTInt), + iEllipsis(0x2026), + iLabelsWidth(0), + iLabelsGutter(0), + iFormatMode(CLayoutData::EFScreenMode), + iImageDevice(NULL), + iLabelsDevice(NULL), + iFormatDevice(NULL), + iFontHeightIncreaseFactor(EDefaultFontHeightIncreaseFactor), + iMinimumLineDescent(EDefaultMinimumLineDescent), + iNonPrintingCharVisibility(), + iFormParam(NULL), + iCustomDraw(NULL), + iCustomWrap(NULL), + iInterfaceProvider(NULL), + iDrawOpaque(EFalse), + iExcessHeightRequired(0), + iInvisibleCharacterRemapper(NULL) + { + } + +MGraphicsDeviceMap& TLayDocTextSource::FormatDevice() const + { + if (!iFormatDevice) + CTextLayout::Panic(CTextLayout::EFormatDeviceNotSet); + if (iLabelsDevice && (iFlags & EUseLabelsDevice)) + return *iLabelsDevice; + else + return *iFormatDevice; + } + +MGraphicsDeviceMap& TLayDocTextSource::InterpretDevice() const + { + if (!iImageDevice) + CTextLayout::Panic(CTextLayout::EImageDeviceNotSet); + if (iLabelsDevice && (iFlags & EUseLabelsDevice)) + return *iLabelsDevice; + else + return *iImageDevice; + } + +TInt TLayDocTextSource::DocumentLength() const + { + return iLayDoc->LdDocumentLength(); + } + +void TLayDocTextSource::GetText(TInt aPos,TPtrC& aText,TTmCharFormat& aFormat) const + { + TCharFormat f; + iLayDoc->GetChars(aText,f,aPos); + aFormat = f; + } + +void TLayDocTextSource::GetParagraphFormatL(TInt aPos,RTmParFormat& aFormat) const + { + CParaFormat f; + iLayDoc->GetParagraphFormatL(&f,aPos); + + // Labels should not have a forced line height or borders so remove these (this is necessary for Agenda). + if (iFlags & EUseLabelsDevice) + { + f.iLineSpacingInTwips = 0; + f.iLineSpacingControl = CParaFormat::ELineSpacingAtLeastInTwips; + f.RemoveAllBorders(); + } + + aFormat.CopyL(f); + f.Reset(); + } + +TRgb TLayDocTextSource::SystemColor(TUint aColorIndex,TRgb aDefaultColor) const + { + if (iCustomDraw) + return iCustomDraw->SystemColor(aColorIndex,aDefaultColor); + else if (iFormParam) + return iFormParam->SystemColor(aColorIndex,aDefaultColor); + else + return aDefaultColor; + } + +CPicture* TLayDocTextSource::PictureL(TInt aPos) const + { + return iLayDoc->PictureHandleL(aPos,MLayDoc::EForceLoadTrue); + } + +TInt TLayDocTextSource::GetPictureSizeInTwipsL(TInt aPos,TSize& aSize) const + { + return iLayDoc->GetPictureSizeInTwips(aSize,aPos); + } + +TInt TLayDocTextSource::ParagraphStart(TInt aPos) const + { + iLayDoc->LdToParagraphStart(aPos); + return aPos; + } + +TBool TLayDocTextSource::LabelModeSelect(TLabelType aType, TInt aPos) + { + if (!(iFlags & EUseLabelsDevice) && aType == EParLabel) + { + // Labels are not allowed on zero-length documents; + // this is required for Agenda (see ER5U defect EDNGASR-482LSF). + if (iLayDoc->LdDocumentLength() == 0) + return FALSE; + + if (iLayDoc->SelectParagraphLabel(aPos)) + { + iFlags |= EUseLabelsDevice; + return TRUE; + } + } + + return FALSE; + } + +void TLayDocTextSource::LabelMetrics(TLabelType aType, TSize& aLabelSize, TInt& aMarginSize) const + { + if (aType == EParLabel) + { + aLabelSize.iWidth = iLabelsWidth; + aLabelSize.iHeight = KMaxTInt; + aMarginSize = iLabelsWidth + iLabelsGutter; + } + else + { + aLabelSize.iWidth = 0; + aLabelSize.iHeight = 0; + aMarginSize = 0; + } + } + +void TLayDocTextSource::LabelModeCancel() + { + iLayDoc->CancelSelectLabel(); + iFlags &= ~EUseLabelsDevice; + } + +/** +This method is responsible for discovering interface extension objects +requried by Form for the specified interface Uid. +@param aInterfaceId + Identifier for the optional interface requried. +@return + Pointer to object supporting the requested interface, + or 0 if not supported. +*/ +TAny* TLayDocTextSource::GetExtendedInterface(const TUid& aInterfaceId) + { + TAny* interfacePtr = 0; + + // First check to see if their is an external interface provider + // registered and ask it for the interface. + if (iInterfaceProvider) + { + interfacePtr = iInterfaceProvider->GetExtendedInterface( aInterfaceId ); + } + + // If interface still not supplied check self and parent to provide it + if (!interfacePtr) + { + if (aInterfaceId == KFormLabelApiExtensionUid) + { + return static_cast(this); + } + else if(aInterfaceId == KTmTextDrawExtId) + { + return static_cast (this); + } + else if(aInterfaceId == KTmCustomExtensionUid) + { + return static_cast (this); + } + else + { + // In this instance, calling the parent class will always return NULL + // but the pattern should be followed by all implementors for safety + return MTmSource::GetExtendedInterface(aInterfaceId); + } + } + + // Return the interface object or 0 if not supported. + return interfacePtr; + } + +void TLayDocTextSource::SetLineHeight(const TLineHeightParam& aParam,TInt& aAscent,TInt& aDescent) const + { + // Increase the ascent by the font height increase percentage. + TLineHeightParam p = aParam; + p.iFontMaxAscent += ((p.iFontMaxAscent + p.iFontMaxDescent) * iFontHeightIncreaseFactor) / 100; + + // Call the standard SetLineHeight. + MTmSource::SetLineHeight(p,aAscent,aDescent); + + // iExcessHeightRequired is used when height of the highest glyph can be + // greater than CFont::AscentInPixels() and in iExactLineSpacing mode + // This value is set via CTextView::SetExcessHeightRequired() + if ( aParam.iExactLineHeight ) + { + aAscent += iExcessHeightRequired; + aDescent -= iExcessHeightRequired; + } + + // Enforce the minimum descent; the following logic is borrowed from CLineLayout::WrapLineL in old FORM. + if (aAscent + aDescent <= iMinimumLineDescent && aDescent == 0) + { + aDescent = 1; + aAscent--; + } + else if (aDescent < iMinimumLineDescent) + aDescent = iMinimumLineDescent; + + /* + Ensure the line is at least 1 pixel high and ascent and descent are non-negative so that assertion + TCursorPosition::GetLineRectL that cursor pos is contained in line rect doesn't fire. + */ + if (aAscent < 0) + aAscent = 0; + if (aDescent < 0) + aDescent = 0; + if (aAscent + aDescent == 0) + aDescent = 1; + } + +TBool TLayDocTextSource::CanMap() const + { + return iFormatMode == CLayoutData::EFScreenMode || iFormatMode == CLayoutData::EFWysiwygMode; + } + +TBool TLayDocTextSource::PageBreakInRange(TInt aStartPos,TInt aEndPos) const + { + if (CanMap() && iNonPrintingCharVisibility.PageBreaksVisible()) + return iLayDoc->EnquirePageBreak(aStartPos,aEndPos - aStartPos); + else + return FALSE; + } + +void TLayDocTextSource::DrawBackground(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aRect, + const TLogicalRgb& aBackground,TRect& aDrawn) const + { + ResetOpaque(aGc); + if (iCustomDraw) + { + MFormCustomDraw::TParam param(aGc,InterpretDevice(),aTopLeft,aRect); + TLogicalRgb background = aBackground; + FormUtil::LogicalToActualColor(iFormParam,background); + iCustomDraw->DrawBackground(param,background,aDrawn); + } + else + MTmSource::DrawBackground(aGc,aTopLeft,aRect,aBackground,aDrawn); + } + +void TLayDocTextSource::DrawLineGraphics(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aRect, + const TTmLineInfo& aLineInfo) const + { + SetOpaque(aGc); + if (iCustomDraw) + { + MFormCustomDraw::TParam param(aGc,InterpretDevice(),aTopLeft,aRect); + MFormCustomDraw::TLineInfo lineinfo(aLineInfo.iOuterRect,aLineInfo.iInnerRect,aLineInfo.iBaseline); + iCustomDraw->DrawLineGraphics(param,lineinfo); + } + else + MTmSource::DrawLineGraphics(aGc,aTopLeft,aRect,aLineInfo); + ResetOpaque(aGc); + } + +void TLayDocTextSource::DrawText(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aRect, + const TTmLineInfo& aLineInfo,const TTmCharFormat& aFormat, + const TDesC& aText,const TPoint& aTextOrigin,TInt aExtraPixels) const + { + SetOpaque(aGc); + if (iCustomDraw) + { + MFormCustomDraw::TParam param(aGc,InterpretDevice(),aTopLeft,aRect); + MFormCustomDraw::TLineInfo lineinfo(aLineInfo.iOuterRect,aLineInfo.iInnerRect,aLineInfo.iBaseline); + TCharFormat f; + aFormat.GetTCharFormat(f); + iCustomDraw->DrawText(param,lineinfo,f,aText,aTextOrigin,aExtraPixels); + } + else + MTmSource::DrawText(aGc,aTopLeft,aRect,aLineInfo,aFormat,aText,aTextOrigin,aExtraPixels); + ResetOpaque(aGc); + } + +void TLayDocTextSource::DrawText(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aRect, + const TTmLineInfo& aLineInfo,const TTmCharFormat& aFormat, + const TDesC& aText,const TInt aStart, const TInt aEnd, const TPoint& aTextOrigin,TInt aExtraPixels) const + { + SetOpaque(aGc); + if (iCustomDraw) + { + MFormCustomDraw::TParam param(aGc,InterpretDevice(),aTopLeft,aRect); + MFormCustomDraw::TLineInfo lineinfo(aLineInfo.iOuterRect,aLineInfo.iInnerRect,aLineInfo.iBaseline); + TCharFormat f; + aFormat.GetTCharFormat(f); + iCustomDraw->DrawText(param,lineinfo,f,aText,aStart,aEnd,aTextOrigin,aExtraPixels); + } + else + MTmCustomExtension::DrawText(aGc,aTopLeft,aRect,aLineInfo,aFormat,aText,aStart,aEnd,aTextOrigin,aExtraPixels); + ResetOpaque(aGc); + } + +TBool TLayDocTextSource::LineBreakPossible(TUint aPrevClass,TUint aNextClass,TBool aHaveSpaces) const + + { + TBool temp; + if (iCustomWrap) + temp=iCustomWrap->LineBreakPossible(aPrevClass,aNextClass,aHaveSpaces); + else + temp=MTmSource::LineBreakPossible(aPrevClass,aNextClass,aHaveSpaces); + return temp; + } + +TUint TLayDocTextSource::LineBreakClass(TUint aCode,TUint& aRangeStart,TUint& aRangeEnd) const + { + TUint temp; + if (iCustomWrap) + temp=iCustomWrap->LineBreakClass(aCode,aRangeStart,aRangeEnd); + else + temp=MTmSource::LineBreakClass(aCode,aRangeStart,aRangeEnd); + return temp; + } + + +TBool TLayDocTextSource::GetLineBreakInContext(const TDesC& aText,TInt aMinBreakPos,TInt aMaxBreakPos, + TBool aForwards,TInt& aBreakPos) const + { + TBool temp; + if (iCustomWrap) + temp=iCustomWrap->GetLineBreakInContext(aText,aMinBreakPos,aMaxBreakPos,aForwards,aBreakPos); + else + temp=MTmSource::GetLineBreakInContext(aText,aMinBreakPos,aMaxBreakPos,aForwards,aBreakPos); + return temp; + } + +TBool TLayDocTextSource::IsHangingCharacter(TUint aChar) const + { + TBool temp; + if (iCustomWrap) + temp=iCustomWrap->IsHangingCharacter(aChar); + else + temp=MTmSource::IsHangingCharacter(aChar); + return temp; + } + + +TUint TLayDocTextSource::Map(TUint aChar) const + { + // Check if custom formatting has been installed + if (iInvisibleCharacterRemapper) + { // Then use the supplied custom invisible character remapping + return iInvisibleCharacterRemapper->Remap(aChar, iNonPrintingCharVisibility, *this); + } + else // Use the default + return MFormCustomInvisibleCharacterRemapper::DefaultMapping(aChar, iNonPrintingCharVisibility, *this); + } + +void TLayDocTextSource::DrawPicture(CGraphicsContext& aGc, + const TPoint& aTextLayoutTopLeft, const TRect& aRect, + MGraphicsDeviceMap& aDevice, const CPicture& aPicture) const + { + SetOpaque(aGc); + MTmSource::DrawPicture(aGc, aTextLayoutTopLeft, aRect, aDevice, aPicture); + ResetOpaque(aGc); + } + +//MTmTextDrawExt implementations + +/** +Draws a line. Implements MTmTextDrawExt::DrawLine(). +If the opaque drawing mode is active, then the line color will stay unchanged (it will not be +alpha-blended in a case of a transparent window). +@param aGc A reference to a graphics context. If the drawing mode is opaque, then this is a + CWindowGc reference. +@param aPt1 Line start point +@param aPt2 Line end point +*/ +void TLayDocTextSource::DrawLine(CGraphicsContext& aGc, const TPoint& aPt1, const TPoint& aPt2) const + { + SetOpaque(aGc); + aGc.DrawLine(aPt1, aPt2); + ResetOpaque(aGc); + } + +/** +Draws a text. Implements MTmTextDrawExt::DrawText(). +If the opaque drawing mode is active, then the text color will stay unchanged (it will not be +alpha-blended in a case of a transparent window). +@param aGc A reference to a graphics context. If the drawing mode is opaqe, then this is a + CWindowGc reference. +@param aPt1 Text start point +*/ +void TLayDocTextSource::DrawText(CGraphicsContext& aGc, const TDesC& aText, const TPoint& aPt) const + { + SetOpaque(aGc); + aGc.DrawText(aText, aPt); + ResetOpaque(aGc); + } + +/** +Draws a rectangle. Implements MTmTextDrawExt::DrawRect(). +If the opaque drawing mode is active, then the rectabgle color will stay unchanged (it will not be +alpha-blended in a case of a transparent window). +@param aGc A reference to a graphics context. If the drawing mode is opaqe, then this is a + CWindowGc reference. +@param aRc Rectangle coordinates +*/ +void TLayDocTextSource::DrawRect(CGraphicsContext& aGc, const TRect& aRc) const + { + SetOpaque(aGc); + aGc.DrawRect(aRc); + ResetOpaque(aGc); + } + +/** +Sets opaque drawing mode. +@param aGc A reference to a graphics context. If the drawing mode is opaqe, then this is a + CWindowGc reference. +*/ +void TLayDocTextSource::SetOpaque(CGraphicsContext& aGc) const + { + if(iDrawOpaque) + { + static_cast (aGc).SetOpaque(ETrue); + } + } + +/** +Resets opaque drawing mode. +@param aGc A reference to a graphics context. If the drawing mode is opaqe, then this is a + CWindowGc reference. +*/ +void TLayDocTextSource::ResetOpaque(CGraphicsContext& aGc) const + { + if(iDrawOpaque) + { + static_cast (aGc).SetOpaque(EFalse); + } + } + +// Private CTextLayout functions start here. + +void CTextLayout::Panic(TPanicNumber aNumber) + { + _LIT(KPanicNumber,"CTextLayout using TAGMA"); + User::Panic(KPanicNumber,aNumber); + } + +void CTextLayout::GetParagraphRect(const TTmDocPos& aDocPos,TRect& aRect) const + { + aRect.SetRect(0,0,0,0); + TTmLineInfo info, info2; + if (!iText->DocPosToLine(aDocPos,info)) + return; + aRect = info.iOuterRect; + if (!(info.iFlags & TTmLineInfo::EParStart)) + { + iText->ParNumberToLine(info.iParNumber,0,info2); + aRect.iTl = info2.iOuterRect.iTl; + } + if (!(info.iFlags & TTmLineInfo::EParEnd)) + { + iText->ParNumberToLine(info.iParNumber,KMaxTInt,info2); + aRect.iBr = info2.iOuterRect.iBr; + } + aRect.Move(0,-iBandTop); + } + +/** +Scroll aDy pixels (positive = text moves down); return number of pixels +actually scrolled. Create a new formatted band if necessary. +*/ +TInt CTextLayout::ScrollL(TInt aDy,TAllowDisallow aScrollBlankSpace, + TBool aTopNoLimitBorder/*=EFalse*/, + TBool aBottomNoLimitBorder/*=EFalse*/) + { + if ( EFDisallowScrollingBlankSpace == aScrollBlankSpace ) + { + aTopNoLimitBorder = EFalse; + aBottomNoLimitBorder = EFalse; + } + int old_bandtop = iBandTop; + int desired_bandtop = iBandTop - aDy; + int pixels_scrolled = 0; + int height_increase = 0; + int paragraphs_increase = 0; + TTmFormatParamBase param; + InitFormatParam(param); + // Refuse to scroll if the width is illegal. This prevents + // time being taken in certain situations where it does + // not matter. Once the formatting is capable of + // adding smaller chunks of text at a time, this early-out + // should become unnecessary. + if ((param.iWrapWidth < 1 || param.iMaxHeight < 1) + && param.iFlags & TTmFormatParamBase::EWrap) + return 0; + param.iMaxHeight = KMaxTInt; + int visible_height = VisibleHeightInPixels(); + if (aDy > 0) // text moves down; iBandTop decreases + { + if (aTopNoLimitBorder) + iBandTop = desired_bandtop; + else + iBandTop = Max(0,desired_bandtop);//Disallow text scrolled beyond top border + + pixels_scrolled = old_bandtop - iBandTop; + while (pixels_scrolled < aDy) + { + if (!iText->AddParL(param,TRUE,height_increase,paragraphs_increase)) + break; + pixels_scrolled += height_increase; + } + if (pixels_scrolled > aDy) + { + iBandTop = pixels_scrolled - aDy; + pixels_scrolled = aDy; + } + } + else if (aDy < 0) // text moves up; iBandTop increases + { + if (aBottomNoLimitBorder) + iBandTop = desired_bandtop; + else + iBandTop = Min(iText->LayoutHeight(),desired_bandtop);//Disallow text scrolled beyond bottom border + + pixels_scrolled = old_bandtop - iBandTop; + while (pixels_scrolled > aDy) + { + if (!AddFormattingAtEndL(param, height_increase,paragraphs_increase)) + break; + pixels_scrolled -= height_increase; + if (pixels_scrolled < aDy) + { + height_increase -= aDy - pixels_scrolled; + pixels_scrolled = aDy; + } + iBandTop += height_increase; + } + + // Fill in missing part of visible height. + while (iText->LayoutHeight() - iBandTop < visible_height) + { + if (!AddFormattingAtEndL(param, height_increase,paragraphs_increase)) + break; + } + } + + // Scroll blank space off the display if desired. + if (aScrollBlankSpace == EFDisallowScrollingBlankSpace && iText->LayoutHeight() - iBandTop < visible_height) + { + int new_bandtop = iText->LayoutHeight() - visible_height; + if (new_bandtop < 0) + new_bandtop = 0; + pixels_scrolled += iBandTop - new_bandtop; + iBandTop = new_bandtop; + } + + PruneFormatL(aDy < 0); + return pixels_scrolled + SetBandTop(); + } + +TInt CTextLayout::ScrollDocPosIntoViewL(const TTmDocPos& aDocPos) + { + __ASSERT_DEBUG(aDocPos.iPos <= iText->Source()->DocumentLength(), + Panic(EInvalidDocPos)); + TTmLineInfo info; + ExtendFormattingToCoverPosL(aDocPos.iPos); + if (!iText->DocPosToLine(aDocPos,info)) + { + __ASSERT_DEBUG(iText->Source()->DocumentLength() == 0, + Panic(ECharacterNotFormatted)); + return ScrollL(iBandTop, EFDisallowScrollingBlankSpace); + } + TRect line_rect = info.iOuterRect; + line_rect.Move(0,-iBandTop); + int visible_height = VisibleHeightInPixels(); + // if the line is taller than the screen, we must not scroll the + // baseline off the screen. + if (visible_height < info.iBaseline - info.iOuterRect.iTl.iY) + return ScrollL(iBandTop + visible_height - info.iBaseline, + EFDisallowScrollingBlankSpace); + if (line_rect.iTl.iY < 0) + return ScrollL(-line_rect.iTl.iY, EFDisallowScrollingBlankSpace); + if (line_rect.iBr.iY > visible_height) + { + int available = line_rect.iTl.iY; + int desired = line_rect.iBr.iY - visible_height; + if (available > 0) + return ScrollL(-Min(desired,available), EFDisallowScrollingBlankSpace); + } + return 0; + } + +EXPORT_C TInt CTextLayout::GetLineNumber(TInt aDocPos) + { + TTmLineInfo info; + TTmDocPos pos(aDocPos,TRUE); + if (iText->DocPosToLine(pos,info)) + return info.iLineNumber; + return 0; + }; + + +/* +Prune the formatted band, if not formatting all the text, to the required size. If aFromStart is ETrue +prune from the start, otherwise prune from the end. +*/ +void CTextLayout::PruneFormatL(TBool aFromStart) + { + if (IsFormattingBand()) + { + int pixels_to_prune = 0; + if (aFromStart) + pixels_to_prune = iBandTop; + else + pixels_to_prune = iText->LayoutHeight() - iBandTop - BandHeightInPixels(); + if (pixels_to_prune <= 0) + return; + TTmFormatParamBase param; + InitFormatParam(param); + int height_decrease = 0; + if(aFromStart) + { + while (pixels_to_prune > 0 && iText->DeletePar(param,aFromStart,pixels_to_prune,height_decrease)) + { + pixels_to_prune -= height_decrease; + if (aFromStart) + iBandTop -= height_decrease; + } + } + else + { + if (pixels_to_prune > (iBandHeight/2)) + { + iText->DeleteFormattingFromEndL(param,pixels_to_prune,height_decrease); + } + } + } + } + +/** Sets the hotspot. + +@param aHotSpot Which part of the line (top, baseline or bottom) should appear +at a vertical pixel position. */ +EXPORT_C void TViewYPosQualifier::SetHotSpot(TPartOfLine aHotSpot) + { + iHotSpot = aHotSpot; + } + +/** Sets whether blank space should be allowed at the bottom of the view. This +applies if the document is more than one page long and the last line is +visible. + +@param aFillScreen ETrue (the default) tries to fill the screen, by ensuring +that there is as little blank space as possible at the bottom of the view. +EFalse allows blank space at the bottom. */ +EXPORT_C void TViewYPosQualifier::SetFillScreen(TBool aFillScreen) + { + iFillScreen = aFillScreen; + } + +/** Forces the top line in the view to become fully visible if it is partially +above the top of the view rectangle. + +@param aMakeLineFullyVisible EFViewForceLineFullyVisible (the default) forces +the top line to be fully visible EFViewDontForceLineFullyVisible does not. */ +EXPORT_C void TViewYPosQualifier::SetMakeLineFullyVisible(TFullyVisible aMakeLineFullyVisible) + { + iFullyVisible = aMakeLineFullyVisible; + } + +void CTextLayout::InitFormatParam(TTmFormatParamBase& aParam) + { + aParam.iMaxHeight = BandHeightInPixels(); + iSource->iExcessHeightRequired = iExcessHeightRequired; + + aParam.iFlags = TTmFormatParamBase::EAtLeastMaxHeight; + aParam.iWrapWidth = iSource->iWidth; + if (iSource->iFlags & TLayDocTextSource::EWrap) + aParam.iFlags |= TTmFormatParamBase::EWrap; + if (iSource->iFlags & TLayDocTextSource::ETruncateWithEllipsis) + { + aParam.iFlags |= TTmFormatParamBase::ETruncateWithEllipsis; + aParam.iEllipsis = iSource->iEllipsis; + } + } + +TInt CTextLayout::VisibleHeightInPixels() const + { + if (iSource->iFormatMode == CLayoutData::EFScreenMode || iSource->iFormatMode == CLayoutData::EFWysiwygMode) + return iVisibleHeight; + else + return iSource->InterpretDevice().VerticalTwipsToPixels(iVisibleHeight); + } + +TInt CTextLayout::BandHeightInPixels() const + { + if (iBandHeight == CLayoutData::EFHeightForFormattingAllText) + return CLayoutData::EFHeightForFormattingAllText; + else + return VisibleHeightInPixels(); + } + +/** +Sets offsets for the edges of the selection highlight. +@param aLeftExtension + Number of pixels to move the left edge of the highlight to the left. +@param aRightExtension + Number of pixels to move the right edge of the highlight to the right. +@param aTopExtension + Number of pixels to move the top edge of the highlight to up. +@param aBottomExtension + Number of pixels to move the bottom edge of the highlight down. +*/ +EXPORT_C void CTextLayout::SetHighlightExtensions(TInt aLeftExtension, + TInt aRightExtension, TInt aTopExtension, TInt aBottomExtension) + { + iHighlightExtensions->SetLeftExtension(aLeftExtension); + iHighlightExtensions->SetRightExtension(aRightExtension); + iHighlightExtensions->SetTopExtension(aTopExtension); + iHighlightExtensions->SetBottomExtension(aBottomExtension); + } + +/** +Set the delta required to position the baseline so there is enough +space for the highset glyph in pixels. This is the height of the highest glyph - +CFont::AscentInPixels(). Only used when using TLineSpacingControl::EAttLineSpacingControl. +By default zero. +@param aExcessHeightRequired + Extra height above CFont::AscentInPixels() required for the highest glyph in pixels. +*/ +void CTextLayout::SetExcessHeightRequired(TInt aExcessHeightRequired) + { + iExcessHeightRequired = aExcessHeightRequired; + } + +/** +For any rectangle, aRect, which may be extended, calculate +the "remainder" rectanges when the view rectangle is intersected with the +extended rect and then subtracted. +The remainder rectangles are returned via aRemainderRects, which is required +to be a pointer to an array of 4 TRect's. +aRemainderRects[0] is top remainder, ...[1] is bottom, ...[2] is left, ...[3] is right +*/ +void CTextLayout::GetHighlightRemnants(const TRect& aRect, const TDrawTextLayoutContext& aDrawTextLayoutContext, + TRect* aRemainderRects) const + { + ASSERT(aRemainderRects); + /* + overlap is the portion of the view rect that aRect intersects with + subtract this from the aRect, giving 4 non-overlapping remainder rectangles, + aRemainderRects, any or all of which may be empty. Copied from SubtractRect in TAGMA + */ + TRect overlap(aDrawTextLayoutContext.iViewRect); + overlap.Intersection(aRect); + if (overlap.IsEmpty()) + overlap.SetRect(aRect.iTl,aRect.iTl); + aRemainderRects[0] = aRect; + aRemainderRects[0].iBr.iY = overlap.iTl.iY; + aRemainderRects[1] = aRect; + aRemainderRects[1].iTl.iY = overlap.iBr.iY; + aRemainderRects[2] = overlap; + aRemainderRects[2].iTl.iX = aRect.iTl.iX; + aRemainderRects[2].iBr.iX = overlap.iTl.iX; + aRemainderRects[3] = overlap; + aRemainderRects[3].iTl.iX = overlap.iBr.iX; + aRemainderRects[3].iBr.iX = aRect.iBr.iX; + } + +/** +Cleanup method for the opaque flag. +*/ +void CTextLayout::ResetOpaque(void* aThis) + { + ASSERT(aThis != NULL); + CTextLayout* p = reinterpret_cast (aThis); + p->iSource->iDrawOpaque = EFalse; + } + +/** +Sets opaque drawing flag for CTextLayout object. It will used later when the +content/background has to be drawn. +Until the flag is not reseted, the opaque drawing will be used +for all the content except the background - the flag has an useful meaning only for transparent +editors. +A TCleanupItem object will be pushed into the Cleanup Stack, which will reset the opaque +flag durring its destruction. +*/ +void CTextLayout::SetOpaqueLC() + { + iSource->iDrawOpaque = ETrue; + CleanupStack::PushL(TCleanupItem(&CTextLayout::ResetOpaque, this)); + } + +void FormPanic(TFormPanic aPanic) + { + _LIT(KFormPanic,"Form"); + User::Panic(KFormPanic,aPanic); + } + +/** +Default implementation of mapping invisible character to its specified alternate. + +Called by TLayDocTextSource::Map() unless overidden by custom mapping class. +May be called by custom mapping class +@param aChar + Invisible character to be remapped +@param aNonPrintingCharVisibility + Current state of flags showing visibility of invisible characters +@param aLayDoc + Const ref to the calling CLayDocTextSource +@return + The replacement character if remapping has taken place, else return original character +*/ +EXPORT_C TUint MFormCustomInvisibleCharacterRemapper::DefaultMapping( TUint aChar, const TNonPrintingCharVisibility aNonPrintingCharVisibility, const TLayDocTextSource& aLayDoc ) + { + // If mapping special characters is possible, use the specified flags. + if (!aNonPrintingCharVisibility.NoneVisible() && aLayDoc.CanMap()) + { + switch (aChar) + { + case CEditableText::EParagraphDelimiter: + if (aNonPrintingCharVisibility.ParagraphDelimitersVisible()) + return KVisibleParagraphBreak; + break; + + case CEditableText::ELineBreak: + if (aNonPrintingCharVisibility.LineBreaksVisible()) + return KVisibleLineBreak; + break; + + case CEditableText::ENonBreakingSpace: + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return KVisibleNonBreakSpace; + break; + + case CEditableText::EPotentialHyphen: + if (aNonPrintingCharVisibility.PotentialHyphensVisible()) + return KVisiblePotentialHyphen; + break; + + case CEditableText::ENonBreakingHyphen: + if (aNonPrintingCharVisibility.NonBreakingHyphensVisible()) + return KVisibleNonBreakHyphen; + break; + + case CEditableText::ETabCharacter: + if (aNonPrintingCharVisibility.TabsVisible()) + return KVisibleTab; + break; + + case CEditableText::EPictureCharacter: + return KVisiblePicture; + + case 0x200B: // Zero Width Space: the same behaviour as 0x20, while different category from 0x20. + if (aNonPrintingCharVisibility.SpacesVisible()) + return KVisibleSpace; + break; + + /* + For the moment, treat bidirectional controls as if they were non-break spaces, as far as visibility is + concerned, and map as follows: LRE=<, RLE=>, PDF=currency symbol, LRO=left guillemet, RLO=right guillemet. + */ + case 0x202A: // LRE + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return 0x003C; + break; + case 0x202B: // RLE + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return 0x003E; + break; + case 0x202C: // PDF + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return 0x00A4; + break; + case 0x202D: // LRO + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return 0x00AB; + break; + case 0x202E: // RLO + if (aNonPrintingCharVisibility.NonBreakingSpacesVisible()) + return 0x00BB; + break; + + default: + if (aNonPrintingCharVisibility.SpacesVisible() && TChar(aChar).GetCategory() == TChar::EZsCategory) + return KVisibleSpace; + break; + } + } + + // If not mapping special characters, or not mapping this particular character, use the default mapping. + return aLayDoc.MTmSource::Map(aChar); + } + + +/** +Allows Form clients to register an invisible character remapper object to +customize the visible display of invisible characters such as paragraph marks. +@param aInvisibleCharacterRemapper + Pointer to custom invisible character remapper to use +*/ +EXPORT_C void CTextLayout::SetCustomInvisibleCharacterRemapper( MFormCustomInvisibleCharacterRemapper* aInvisibleCharacterRemapper ) + { + iSource->iInvisibleCharacterRemapper = aInvisibleCharacterRemapper; + } + +/** +Allows Form clients to see which character remapper object is currently +registered. +*/ +EXPORT_C MFormCustomInvisibleCharacterRemapper* CTextLayout::GetCustomInvisibleCharacterRemapper() + { + return iSource->iInvisibleCharacterRemapper; + } + +/** INC092568: CTextView::SetPendingSelection is not honoured +Sets the cursor position member added for this fix that allows the text layout object +to access any pending selection made by the owning text view object +@param aPos:- pointer to the owning textview's iCursorPos +*/ +void CTextLayout::SetTextViewCursorPos(TCursorPosition* aPos) + { + iTextViewCursorPos = aPos; + } + +/** +This is the function used by CTextLayout when it wants to extend the formatted range downwards. +It just calls CTmTextLayout::AddParL, but restricts the maximum height of the new formatting to the +band height/2. If the next paragraph is bigger than this, AddParL will only format part of that +paragraph, and the formatting will end in the middle of the paragraph. +*/ +TBool CTextLayout::AddFormattingAtEndL(TTmFormatParamBase& aFormatParam, TInt& aHeightIncrease, TInt& aParagraphsIncrease) + { + aFormatParam.iMaxHeight = iBandHeight/2; + return iText->AddParL(aFormatParam, EFalse, aHeightIncrease, aParagraphsIncrease); + } + +/** +Stops or allows text to be drawn. Included to allow users to control visibility +if text is part of an invisible control. + +@param aVisible ETrue to make the text visible, EFalse to make it invisible. +@see CCoeControl::MakeVisible() +*/ +EXPORT_C void CTextLayout::MakeVisible(TBool aVisible) + { + iText->MakeVisible(aVisible); + } +