textrendering/textformatting/tagma/TMLAYOUT.CPP
changeset 32 8b9155204a54
parent 0 1fb32624e06b
child 40 91ef7621b7fc
equal deleted inserted replaced
31:b9ad20498fb4 32:8b9155204a54
       
     1 /*
       
     2 * Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * The CTmTextLayout class: TAGMA's simplest text class. It holds the layout of rectangular piece of text.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include "TmLayoutImp.h"
       
    21 #include "TmHighlightSource.h"
       
    22 #include "TMINTERP.H"
       
    23 #include "TmChunkInterp.h"
       
    24 #include <txtfrmat.h>
       
    25 #include "TmTextDrawExt.h"
       
    26 #include <frmtlay.h>
       
    27 #include "tmreformat.h"
       
    28 #include "frmUtils.h"
       
    29 
       
    30 #define UNUSED_VAR(a) a = a
       
    31 
       
    32 /**
       
    33 Construct a TTmFormatParamBase object. Set iWrapWidth, iMaxHeight and iMaxLines to 'infinity' (KMaxTInt),
       
    34 iFlags to 0 (wrapping off, no truncation with ellipsis, etc.), and iEllipsis to the ordinary ellipsis character, U+2026.
       
    35 */
       
    36 EXPORT_C TTmFormatParamBase::TTmFormatParamBase():
       
    37 	iWrapWidth(KMaxTInt),
       
    38 	iMaxHeight(KMaxTInt),
       
    39 	iMaxLines(KMaxTInt),
       
    40 	iFlags(0),
       
    41 	iEllipsis(0x2026)
       
    42 	{
       
    43 	}
       
    44 
       
    45 /**
       
    46 Construct a TTmFormatParam object, setting iStartChar to 0, iEndChar to 'infinity' (KMaxTInt) and iLineInPar to 0.
       
    47 */
       
    48 EXPORT_C TTmFormatParam::TTmFormatParam():
       
    49 	iStartChar(0),
       
    50 	iEndChar(KMaxTInt),
       
    51 	iLineInPar(0)
       
    52 	{
       
    53 	}
       
    54 
       
    55 /**
       
    56 Construct a TTmFormatParam object with its base class part (TTmFormatParamBase) set to aBase, and setting iStartChar to 0,
       
    57 iEndChar to 'infinity' (KMaxTInt) and iLineInPar to 0.
       
    58 */
       
    59 EXPORT_C TTmFormatParam::TTmFormatParam(const TTmFormatParamBase& aBase):
       
    60 	TTmFormatParamBase(aBase),
       
    61 	iStartChar(0),
       
    62 	iEndChar(KMaxTInt),
       
    63 	iLineInPar(0)
       
    64 	{
       
    65 	}
       
    66 
       
    67 /**
       
    68 Construct a TTmReformatParam object, setting everything to 0 or FALSE apart from iMaxExtraLines, which is
       
    69 set to 'infinity' (KMaxTInt).
       
    70 */
       
    71 EXPORT_C TTmReformatParam::TTmReformatParam():
       
    72 	iStartChar(0), 
       
    73 	iOldLength(0),
       
    74 	iNewLength(0),
       
    75 	iMaxExtraLines(KMaxTInt),
       
    76 	iParFormatChanged(FALSE),
       
    77 	iParInvalid(FALSE)
       
    78 	{
       
    79 	}
       
    80 
       
    81 /**
       
    82 Construct a TTmReformatResult object, setting iHeightChange to 0 and iUnchangedTop and iUnformattedStart to
       
    83 'infinity' (KMaxTInt).
       
    84 */
       
    85 EXPORT_C TTmReformatResult::TTmReformatResult():
       
    86 	iHeightChange(0),
       
    87 	iUnchangedTop(KMaxTInt),
       
    88 	iUnformattedStart(KMaxTInt)
       
    89 	{
       
    90 	}
       
    91 
       
    92 /**
       
    93 Construct an empty object with no text and zero width and height.
       
    94 It is legal to call all CTmTextLayout functions on an empty object,
       
    95 with the exception of AddParL and FormatL, which panic with ENoSource.
       
    96 */
       
    97 EXPORT_C CTmTextLayout::CTmTextLayout() :
       
    98 	iCurrentContextChar(NULL)
       
    99 	{
       
   100 	// do nothing
       
   101 	}
       
   102 
       
   103 /**
       
   104 The destructor.
       
   105 */
       
   106 EXPORT_C CTmTextLayout::~CTmTextLayout()
       
   107 	{
       
   108 	delete iBdStateAtEnd;
       
   109 	}
       
   110 
       
   111 /**
       
   112 Set the text, discarding any existing layout information. The text from aParam.iStartChar to aParam.iEndChar is
       
   113 extracted from aSource and formatted.
       
   114 */
       
   115 EXPORT_C void CTmTextLayout::SetTextL(MTmSource& aSource,const TTmFormatParam& aParam)
       
   116 	{
       
   117 	if (aParam.iMaxHeight <= 0 ||
       
   118 		aParam.iStartChar < 0 || aParam.iEndChar < aParam.iStartChar ||
       
   119 		aParam.iLineInPar < 0)
       
   120 		TmPanic(EBadArg);
       
   121 		
       
   122 	if (iBdStateAtEnd)
       
   123 		{
       
   124 		iBdStateAtEnd->Reset();
       
   125 		}
       
   126 	else
       
   127 		{
       
   128 		iBdStateAtEnd = new(ELeave) TBidirectionalContext;
       
   129 		}
       
   130 
       
   131 		
       
   132 	iSource = &aSource;
       
   133 	iCode.Reset();
       
   134 	iStartChar = aParam.iStartChar;
       
   135 	CTmFormatContext::TInfo info;
       
   136 	if (aParam.iFlags & TTmFormatParamBase::EWrap
       
   137 		&& (aParam.iWrapWidth < 1 || aParam.iMaxHeight < 1))
       
   138 		{
       
   139 		// Illegal parameters, so we should not waste time formatting.
       
   140 		// We will assume that good parameters will be along later.
       
   141 		iHeight = 0;
       
   142 		iEndChar = iStartChar;
       
   143 		iWidth = 0;
       
   144 		}
       
   145 	else
       
   146 		{
       
   147 		//Get line context character from previous line if there is
       
   148 		TTmDocPosSpec startDocPos(aParam.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1));
       
   149 		TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   150 		TBool lineFound = interpreter.DocPosToLine(startDocPos);
       
   151 		if (lineFound)
       
   152 			info.iContextCharPerLine = interpreter.LineContextCharChar();
       
   153 		else
       
   154 			info.iContextCharPerLine = NULL;
       
   155 		
       
   156 		CTmFormatContext::FormatL(aSource,aParam,iCode,info,this,NULL,iBdStateAtEnd, NULL);
       
   157 		iHeight = info.iHeight;
       
   158 		iEndChar = info.iEndChar;
       
   159 		iWidth = 0;
       
   160 		AdjustWidth(aParam,info.iWidth);
       
   161 		}
       
   162 	}
       
   163 
       
   164 /**
       
   165 Format part of the text that has changed and indicate whether further formatting needs to be done.
       
   166 
       
   167 The backing text must remain constant during background formatting. What this means is that
       
   168 if background formatting is enabled (TTmReformatParam::iMaxExtraLines is some small number, causing
       
   169 formatting to end mid-way with TTmReformatResult::iUnformattedStart less than KMaxTInt), so that text
       
   170 can be formatted bit by bit by a higher-level object, as is done by CTextView, the backing text must not
       
   171 change between the series of calls to this function that make up a single reformatting act.
       
   172 */
       
   173 EXPORT_C void CTmTextLayout::FormatL(const TTmFormatParamBase& aParam,const TTmReformatParam& aReformatParam,
       
   174 									 TTmReformatResult& aResult)
       
   175 	{
       
   176 	if (!iSource)
       
   177 		TmPanic(ENoSource);
       
   178 
       
   179 	CTmReformat* reformat = CTmReformat::NewLC(*this, aParam, aReformatParam);
       
   180 	reformat->ReformatL();
       
   181 	CTmCode* new_code = &(reformat->NewCode());
       
   182 	TTmByteCodeFinder::TInfo oldCodeInfo = reformat->ReformatRange();
       
   183 	CTmFormatContext::TInfo newCodeInfo = reformat->FormatInfo();
       
   184 	TBool bd_changed = reformat->BidirectionalStateChanged();
       
   185 	/*
       
   186 	Find the lines that have changed and need to be redisplayed.
       
   187 	If aParagraphFormatChanged is true at least one paragraph format has changed,
       
   188 	so the redraw rectangle includes the whole of the paragraphs affected.
       
   189 
       
   190 	Also redraw the whole paragraph if background formatting is needed, or if the bidirectional state has changed.
       
   191 	*/
       
   192 	if (aReformatParam.iParFormatChanged || aResult.iUnformattedStart < KMaxTInt || bd_changed)
       
   193 		{
       
   194 		aResult.iRedrawRect = oldCodeInfo.iBounds;
       
   195 		aResult.iRedrawRect.iBr.iY = aResult.iRedrawRect.iTl.iY + newCodeInfo.iHeight;
       
   196 		}
       
   197 	else
       
   198 		{
       
   199 		TTmInterpreterParam p(*this);
       
   200 		p.iCodeStart = oldCodeInfo.iStartCodePos;
       
   201 		p.iCodeEnd = oldCodeInfo.iEndCodePos;
       
   202 		p.iTextStart = oldCodeInfo.iStartInfo.iStart;
       
   203 		TTmInterpreter old_code_interpreter(p);
       
   204 		p.iByteCode = new_code;
       
   205 		p.iCodeStart = 0;
       
   206 		p.iCodeEnd = new_code->Size();
       
   207 		TTmInterpreter new_code_interpreter(p);
       
   208 		old_code_interpreter.CalculateRedrawRect(new_code_interpreter,aReformatParam.iStartChar,
       
   209 												 aReformatParam.iOldLength,aReformatParam.iNewLength,aResult.iRedrawRect);
       
   210 		aResult.iRedrawRect.Move(0,oldCodeInfo.iBounds.iTl.iY);
       
   211 		}
       
   212 
       
   213 	// Delete the old bytecode and insert the new.
       
   214 	iCode.ChangeL(oldCodeInfo.iStartCodePos,oldCodeInfo.iEndCodePos,*new_code);
       
   215 
       
   216 	// Adjust the band's bounds.
       
   217 	iHeight += newCodeInfo.iHeight - oldCodeInfo.iBounds.Height();
       
   218 	
       
   219 	//if the range we are replacing includes the end of the current formatted range,
       
   220 	//then the end BD state pointer may be invalidated, so we need to update it
       
   221 	if(oldCodeInfo.iEndInfo.iEnd == iEndChar)
       
   222 		{
       
   223 		*iBdStateAtEnd = reformat->BidirectionalStateAtEnd();
       
   224 		}
       
   225 	// Adjust the band's width if necessary.
       
   226 	AdjustWidth(aParam,newCodeInfo.iWidth);
       
   227 
       
   228 	// Adjust the band's length.
       
   229 	TInt lengthOfOldRange = oldCodeInfo.iEndInfo.iEnd - oldCodeInfo.iStartInfo.iStart;
       
   230 	TInt lengthOfNewRange = newCodeInfo.iEndChar - oldCodeInfo.iStartInfo.iStart;
       
   231 	iEndChar += lengthOfNewRange - lengthOfOldRange;
       
   232 	// Determine the change in height of the reformatted text.
       
   233 	aResult.iHeightChange = newCodeInfo.iHeight - oldCodeInfo.iBounds.Height();
       
   234 
       
   235 	/*
       
   236 	Set the top of the unchanged text, and if not all text has been formatted
       
   237 	remove the first unformatted line from the redraw rect.
       
   238 	*/
       
   239 	if (aResult.iUnformattedStart < KMaxTInt)
       
   240 		{
       
   241 		TTmLineInfo info;
       
   242 		TTmDocPosSpec pos(aResult.iUnformattedStart,TTmDocPosSpec::ETrailing);
       
   243 		DocPosToLine(pos,info);
       
   244 		aResult.iRedrawRect.iBr.iY = info.iOuterRect.iTl.iY;
       
   245 		ParNumberToLine(info.iParNumber,KMaxTInt,info);
       
   246 		aResult.iUnchangedTop = info.iOuterRect.iBr.iY - aResult.iHeightChange;
       
   247 		}
       
   248 	else
       
   249 		aResult.iUnchangedTop = aResult.iRedrawRect.iBr.iY - aResult.iHeightChange;
       
   250 
       
   251 	CleanupStack::PopAndDestroy(reformat);
       
   252 	
       
   253 	Invariant();
       
   254 	}
       
   255 
       
   256 /**
       
   257 Format a new paragraph immediately before or after the band and add it to the formatted text.
       
   258 If the text starts or ends in the middle of the paragraph, complete the paragraph.
       
   259 Return TRUE if text was successfully added, or FALSE if there is no more text to add, or
       
   260 the new text would have exceeded the maximum height allowed. Place the height of the new text in aHeightIncrease.
       
   261 Place the increase in the number of complete paragraphs (0 or 1) in aParagraphsIncrease.
       
   262 
       
   263 Note that this function will not necessarily add a whole paragraph to the band: if the client has restricted
       
   264 the amount of formatting to add by setting the relevant values in aParam, then these restrictions will
       
   265 be respected with the result that less than a paragraph of formatting may be generated.
       
   266 
       
   267 This is the case, for example, when CTextLayout adds text below the band. 
       
   268 */
       
   269 EXPORT_C TBool CTmTextLayout::AddParL(const TTmFormatParamBase& aParam,TBool aAtStart,TInt& aHeightIncrease,
       
   270 									  TInt& aParagraphsIncrease)
       
   271 	{	
       
   272 	if (!iSource)
       
   273 		TmPanic(ENoSource);
       
   274 
       
   275 	aHeightIncrease = 0;
       
   276 	aParagraphsIncrease = 0;
       
   277 	int start_char = 0;
       
   278 	int end_char = 0;
       
   279 	int deleted_height = 0;
       
   280 	TTmFormatParam format_param(aParam);
       
   281 
       
   282 	TBidirectionalContext* pStartBd = NULL;
       
   283 	TBidirectionalContext* pEndBd = NULL;
       
   284 	TBidirectionalEndOfLineContext* pEOLContext = NULL;		
       
   285 	
       
   286 	if (aAtStart)
       
   287 		{
       
   288 		if (iStartChar == 0)
       
   289 			return FALSE;
       
   290 		start_char = iSource->ParagraphStart(iStartChar - 1);
       
   291 		end_char = iSource->ParagraphEnd(iStartChar - 1);
       
   292 		if (end_char > iStartChar)
       
   293 			{
       
   294 			if (end_char > iEndChar)
       
   295 				end_char = iEndChar;
       
   296 			DeletePar(aParam,TRUE,KMaxTInt,deleted_height);
       
   297 			}
       
   298 		else
       
   299 			aParagraphsIncrease = 1;
       
   300 		}
       
   301 	else
       
   302 		{
       
   303 		if (iEndChar > iSource->DocumentLength())
       
   304 			return FALSE;
       
   305 		start_char = iEndChar;
       
   306 		end_char = iSource->ParagraphEnd(iEndChar);
       
   307 		
       
   308 		pStartBd = iBdStateAtEnd;
       
   309 		pEndBd = iBdStateAtEnd;
       
   310 			
       
   311 		TInt lastLineNumber = Lines()-1;
       
   312 		if(lastLineNumber >= 0)
       
   313 			{
       
   314 			TTmLineInfo lastLine;
       
   315 			TBool found = LineNumberToLine(lastLineNumber, lastLine);
       
   316 			ASSERT(found);
       
   317 			if(!(lastLine.iFlags & TTmLineInfo::EParEnd))
       
   318 				{
       
   319 				format_param.iLineInPar = lastLine.iLineInPar+1;
       
   320 				}
       
   321 			}				
       
   322 						
       
   323 		aParagraphsIncrease = 1; 
       
   324 		}
       
   325 
       
   326 	CTmCode* new_code = new(ELeave) CTmCode;
       
   327 	CleanupStack::PushL(new_code);
       
   328 	format_param.iStartChar = start_char;
       
   329 	format_param.iEndChar = end_char;
       
   330 	int code_pos = aAtStart ? 0 : iCode.Size();
       
   331 	CTmFormatContext::TInfo info;
       
   332 	
       
   333 	//Get line context character from previous line if there is
       
   334 	TTmDocPosSpec startDocPos(format_param.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1));
       
   335 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   336 	TBool lineFound = interpreter.DocPosToLine(startDocPos);
       
   337 	if (lineFound)
       
   338 		info.iContextCharPerLine = interpreter.LineContextCharChar();
       
   339 	else
       
   340 		info.iContextCharPerLine = NULL;
       
   341 	
       
   342 	CTmFormatContext::FormatL(*iSource,format_param,*new_code,info,this,
       
   343 		pStartBd, pEndBd, pEOLContext);
       
   344 
       
   345 	// Insert the new code if any.
       
   346 	aHeightIncrease = info.iHeight;
       
   347 	if (aHeightIncrease > 0)
       
   348 		{
       
   349 		iCode.ChangeL(code_pos,code_pos,*new_code);
       
   350 
       
   351 		iHeight += aHeightIncrease;
       
   352 		if (aAtStart)
       
   353 			iStartChar = start_char;
       
   354 		else
       
   355 			iEndChar = info.iEndChar;
       
   356 
       
   357 		// Adjust the band's width if necessary.
       
   358 		AdjustWidth(aParam,info.iWidth);
       
   359 		}
       
   360 	//if we did actually format to the paragraph end, reset the bd state
       
   361 	if(!aAtStart)
       
   362 		{
       
   363 		if(iEndChar == format_param.iEndChar)
       
   364 			{
       
   365 			iBdStateAtEnd->Reset();
       
   366 			}
       
   367 		}
       
   368 	CleanupStack::PopAndDestroy();	// new code
       
   369 	aHeightIncrease -= deleted_height;
       
   370 	
       
   371 	Invariant();
       
   372 	
       
   373 	return aHeightIncrease > 0;
       
   374 	}
       
   375 	
       
   376 TBool CTmTextLayout::LastLine(TTmLineInfo& aLine)
       
   377 	{
       
   378 	TInt lastLineNumber = Lines()-1;
       
   379 	if(lastLineNumber >= 0)
       
   380 		{
       
   381 		TTmLineInfo lastLine;
       
   382 		TBool found = LineNumberToLine(lastLineNumber, aLine);
       
   383 		ASSERT(found);
       
   384 		return ETrue;
       
   385 		}
       
   386 	return EFalse;	
       
   387 	}
       
   388 
       
   389 void CTmTextLayout::SetCurrentContextChar(TUint aContextChar)
       
   390 	{
       
   391 	iCurrentContextChar = aContextChar;
       
   392 	}
       
   393 	
       
   394 TUint CTmTextLayout::GetCurrentContextChar() const
       
   395 	{
       
   396 	return iCurrentContextChar;
       
   397 	}
       
   398 /**
       
   399 Extend the formatted range downwards. That is, starting at the end of the current 
       
   400 formatted range, generate some new formatting and append it to the end of the range.
       
   401 @param aParam 
       
   402 This controls how much new formatting to generate. We will generate formatting up whichever comes first of:
       
   403 - the character position specified in TTmFormatParam::iEndChar
       
   404 - the height specified (in pixels) in TTmFormatParamBase::iMaxHeight
       
   405 - the number of lines specified in TTmFormatParamBase::iMaxLines
       
   406 We replace the values specified in TTmFormatParam::iStartChar and TmFormatParam::iLineInPar
       
   407 @pre The object must have been initialised with an MTmSource, or it will panic.
       
   408 */
       
   409 EXPORT_C void CTmTextLayout::ExtendFormattingDownwardsL(TTmFormatParam& aParam)
       
   410 	{
       
   411 	if (!iSource)
       
   412 		TmPanic(ENoSource);
       
   413 
       
   414 	aParam.iStartChar = iEndChar;
       
   415 
       
   416 	if (iEndChar > iSource->DocumentLength())
       
   417 		return;
       
   418 	if (aParam.iStartChar > aParam.iEndChar)
       
   419 		return;
       
   420 		
       
   421 	TBidirectionalContext* pStartBd = iBdStateAtEnd;
       
   422 	TBidirectionalContext* pEndBd = iBdStateAtEnd;
       
   423 	TBidirectionalEndOfLineContext* pEOLContext = NULL;		
       
   424 
       
   425 	//if there is a last line (i.e. if there is any formatting at all)
       
   426 	//and the last line is not a paragraph boundary, 
       
   427 	//then initialise the line number				
       
   428 	TTmLineInfo lastLine;
       
   429 	TBool found = LastLine(lastLine);
       
   430 	if(found && !(lastLine.iFlags & TTmLineInfo::EParEnd))
       
   431 		{
       
   432 		aParam.iLineInPar = lastLine.iLineInPar+1;
       
   433 		}				
       
   434 	
       
   435 	//Generate the additional formatting
       
   436 	CTmCode* newCode = new(ELeave) CTmCode;
       
   437 	CleanupStack::PushL(newCode);
       
   438 
       
   439 	TInt newCodePos = iCode.Size();
       
   440 	CTmFormatContext::TInfo info;
       
   441 	
       
   442 	//Get line context character from previous line if there is
       
   443 	TTmDocPosSpec startDocPos(aParam.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1));
       
   444 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   445 	TBool lineFound = interpreter.DocPosToLine(startDocPos);
       
   446 	if (lineFound)
       
   447 		info.iContextCharPerLine = interpreter.LineContextCharChar();
       
   448 	else
       
   449 		info.iContextCharPerLine = NULL;
       
   450 	
       
   451 	CTmFormatContext::FormatL(*iSource,aParam,*newCode,info,this,pStartBd, pEndBd, pEOLContext);
       
   452 
       
   453 	// Insert the new code if any.
       
   454 	if (info.iHeight > 0)
       
   455 		{
       
   456 		iCode.ChangeL(newCodePos,newCodePos,*newCode);
       
   457 		iHeight += info.iHeight;
       
   458 		iEndChar = info.iEndChar;
       
   459 		AdjustWidth(aParam,info.iWidth);
       
   460 		}
       
   461 	//if we did actually format to the paragraph end, reset the bd state
       
   462 	found = LastLine(lastLine);
       
   463 	if(found && (lastLine.iFlags & TTmLineInfo::EParEnd))
       
   464 		{
       
   465 		iBdStateAtEnd->Reset();
       
   466 		}
       
   467 
       
   468 	CleanupStack::PopAndDestroy();	// new code
       
   469 	Invariant();	
       
   470 	}
       
   471 
       
   472 /**
       
   473 Delete the format for the first or last paragraph if its height does not exceed aMaxDeletedHeight.
       
   474 Return TRUE if a paragraph was successfully deleted. Place the height of the deleted paragraph in aHeightDecrease.
       
   475 */
       
   476 EXPORT_C TBool CTmTextLayout::DeletePar(const TTmFormatParamBase& aParam,TBool aAtStart,TInt aMaxDeletedHeight,
       
   477 										TInt& aHeightDecrease)
       
   478 	{
       
   479 	aHeightDecrease = 0;
       
   480 	if (!iSource || iStartChar >= iEndChar)
       
   481 		return FALSE;
       
   482 
       
   483 	int pos = aAtStart ? iStartChar : iEndChar - 1;
       
   484 	TTmByteCodeFinder finder(TTmInterpreterParam(*this), pos, pos);
       
   485 	TTmByteCodeFinder::TInfo info;
       
   486 	if (!finder.FindByteCode(TRUE,TRUE,KMaxTInt,info))
       
   487 		TmPanic(EFormatNotFound);
       
   488 	if (info.iBounds.Height() > aMaxDeletedHeight)
       
   489 		return FALSE;
       
   490 
       
   491 	iCode.Delete(info.iStartCodePos,info.iEndCodePos - info.iStartCodePos);
       
   492 	if (aAtStart)
       
   493 		iStartChar = info.iEndInfo.iEnd;
       
   494 	else
       
   495 		iEndChar = info.iStartInfo.iStart;
       
   496 	aHeightDecrease = info.iBounds.Height();
       
   497 	iHeight -= aHeightDecrease;
       
   498 
       
   499 	// Adjust the band's width if necessary.
       
   500 	AdjustWidth(aParam,0);
       
   501 	
       
   502 	Invariant();
       
   503 	
       
   504 	return TRUE;
       
   505 	}
       
   506 	
       
   507 /** 
       
   508 Delete as many lines of formatting as possible from the end of the formatted range, up to 
       
   509 the maximum height specified in aMaxDeletedHeight. The height decrease is placed in aHeightDecrease. 
       
   510 */
       
   511 EXPORT_C void CTmTextLayout::DeleteFormattingFromEndL(const TTmFormatParamBase& aParam, TInt aMaxDeletedHeight, TInt& aHeightDecrease)
       
   512 	{
       
   513 	aHeightDecrease = 0;
       
   514 	if (!iSource || iStartChar >= iEndChar)
       
   515 		return;
       
   516 	TBidirectionalContext* bdStart = new(ELeave) TBidirectionalContext;
       
   517 	CleanupStack::PushL(bdStart);
       
   518 	TBidirectionalContext* bdEnd = new(ELeave) TBidirectionalContext;
       
   519 	CleanupStack::PushL(bdEnd);
       
   520 	TTmByteCodeFinder::TInfo info;
       
   521 	TTmByteCodeFinder sectionFinder(TTmInterpreterParam(*this), iStartChar, iStartChar);
       
   522 	TBool found = sectionFinder.FindByteCodeAtEnd(info, aMaxDeletedHeight, iHeight, bdStart, bdEnd);
       
   523 	if (!found)
       
   524 		{
       
   525 		CleanupStack::PopAndDestroy(2);
       
   526 		}
       
   527 	else
       
   528 		{
       
   529 		//should use an assignment operator here instead
       
   530 		delete iBdStateAtEnd;
       
   531 		iBdStateAtEnd = bdStart;
       
   532 		CleanupStack::PopAndDestroy(bdEnd);
       
   533 		CleanupStack::Pop(bdStart);
       
   534 		iCode.Delete(info.iStartCodePos, info.iEndCodePos - info.iStartCodePos);
       
   535 		iEndChar = info.iStartInfo.iStart;
       
   536 		aHeightDecrease = info.iBounds.Height();
       
   537 		iHeight -= aHeightDecrease;
       
   538 		// Adjust the band's width if necessary.
       
   539 		AdjustWidth(aParam,0);
       
   540 		Invariant();
       
   541 		}	
       
   542 	}
       
   543 
       
   544 /**
       
   545 Reset the object to its empty state; no source or formatting, height and width of 0, start and end char both 0.
       
   546 */
       
   547 EXPORT_C void CTmTextLayout::Clear()
       
   548 	{
       
   549 	if(iBdStateAtEnd)
       
   550 		iBdStateAtEnd->Reset();
       
   551 	iSource = NULL;
       
   552 	iCode.Reset();
       
   553 	iWidth = 0;
       
   554 	iHeight = 0;
       
   555 	iStartChar = 0;
       
   556 	iEndChar = 0;
       
   557 
       
   558 	Invariant();
       
   559 	}
       
   560 
       
   561 /**
       
   562 Draw the text.
       
   563 
       
   564 @param aGc
       
   565 	Graphics context to draw to.
       
   566 @param aTopLeft
       
   567 	The origin of the formatted text in the coordinates of aGc.
       
   568 @param aClipRect
       
   569 	The clipping rectangle in the coordinates of aGc. Nowhere outside this
       
   570 	rectangle will be drawn.
       
   571 @param aDocBackground
       
   572 	The default document background colour, which is used for regions not drawn
       
   573 	by any custom background drawing routine and not covered by any text. If
       
   574 	null, no background is drawn in these places.
       
   575 @param aDrawParBackground
       
   576 	If false no default background is drawn on those areas covered by text.
       
   577 	Custom background drawers are invoked regardless of this argument.
       
   578 */
       
   579 
       
   580 EXPORT_C void CTmTextLayout::DrawLayout(CGraphicsContext& aGc,
       
   581 	const TPoint& aTopLeft,const TRect& aClipRect,
       
   582 	const TLogicalRgb* aDocBackground,TBool aDrawParBackground) const
       
   583 	{
       
   584 	DrawLayout(aGc, aTopLeft, aClipRect, aDocBackground, aDrawParBackground, NULL, NULL);
       
   585 	}
       
   586 
       
   587 /**
       
   588 Draw the text.
       
   589 
       
   590 @param aGc
       
   591 	Graphics context to draw to.
       
   592 @param aTopLeft
       
   593 	The origin of the formatted text in the coordinates of aGc.
       
   594 @param aClipRect
       
   595 	The clipping rectangle in the coordinates of aGc. Nowhere outside this
       
   596 	rectangle will be drawn.
       
   597 @param aDocBackground
       
   598 	The default document background colour, which is used for regions not drawn
       
   599 	by any custom background drawing routine and not covered by any text. If
       
   600 	null, no background is drawn in these places.
       
   601 @param aDrawParBackground
       
   602 	If false no default background is drawn on those areas covered by text.
       
   603 	Custom background drawers are invoked regardless of this argument.
       
   604 @param aHighlight
       
   605 	The current selection. If null, no selection is drawn.
       
   606 @param aHighlightExtensions
       
   607 	If not null, the selection highlight has its edges moved by the specified
       
   608 	number of pixels
       
   609 */
       
   610 
       
   611 EXPORT_C void CTmTextLayout::DrawLayout(CGraphicsContext& aGc,
       
   612 	const TPoint& aTopLeft,const TRect& aClipRect,
       
   613 	const TLogicalRgb* aDocBackground,TBool aDrawParBackground,
       
   614 	const TCursorSelection* aHighlight,
       
   615 	const TTmHighlightExtensions* aHighlightExtensions) const
       
   616 	{
       
   617 	if (iSource)
       
   618 		{
       
   619 		RTmDrawingInterpreter interpreter(*iSource, aGc,
       
   620 			TTmInterpreterParam(*this), aTopLeft, aClipRect, aDocBackground,
       
   621 			aDrawParBackground ? RTmDrawingInterpreter::EDrawParBackground : 0,
       
   622 			aHighlight, aHighlightExtensions);
       
   623 		interpreter.Draw();
       
   624 		interpreter.Close();
       
   625 		}
       
   626 	}
       
   627 
       
   628 /**
       
   629 Draw the background, using the custom background graphics implemented by overriding MTmSource::DrawBackground if any:
       
   630 aTopLeft is the top-left corner of the text, aRect is the portion of the background to be drawn, and aBackground is
       
   631 the default background colour. This function is used by higher-level classes for drawing backgrounds outside the ordinary
       
   632 text area consistently with the ordinary background.
       
   633 */
       
   634 EXPORT_C void CTmTextLayout::DrawBackground(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aClipRect,
       
   635 											const TLogicalRgb& aBackground) const
       
   636 	{
       
   637 	if (iSource)
       
   638 		{
       
   639 		RTmDrawingInterpreter interpreter(*iSource, aGc, TTmInterpreterParam(*this),
       
   640 			aTopLeft, aClipRect, &aBackground, 0, NULL, NULL);
       
   641 		interpreter.DrawBackground(aClipRect, aBackground);
       
   642 		interpreter.Close();
       
   643 		}
       
   644 	}
       
   645 
       
   646 EXPORT_C void CTmTextLayout::InvertLayout(CGraphicsContext& aGc,
       
   647 	const TPoint& aTopLeft, TInt aStartDocPos,TInt aEndDocPos) const
       
   648 	{
       
   649 	TTmHighlightExtensions highlightProperties;
       
   650 	highlightProperties.SetAll(0);
       
   651 	InvertLayout(aGc,aTopLeft,aStartDocPos,aEndDocPos,highlightProperties,0,0);
       
   652 	}
       
   653 
       
   654 /**
       
   655 Analogous to InvertLayout(CGraphicsContext, const TPoint&, TInt, TInt) but with
       
   656 highlight extensions applied.
       
   657 @see InvertLayout(CGraphicsContext, const TPoint&, TInt, TInt)
       
   658 @publishedPartner
       
   659 @released
       
   660 */
       
   661 EXPORT_C void CTmTextLayout::InvertLayout(CGraphicsContext& aGc,
       
   662 	const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos,
       
   663 	const TTmHighlightExtensions& aHighlightExtensions,
       
   664 	TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const
       
   665 	{
       
   666 	// note: Assumes that RWindow::BeginRedraw() has been called by the caller.
       
   667 
       
   668 	if (NULL == iSource)
       
   669 		{
       
   670 		return;
       
   671 		}
       
   672 
       
   673 	TRect clipRect;
       
   674 	GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, clipRect);
       
   675 
       
   676 	if (aStartDocPos < aHighlightStartDocPos)
       
   677 		{
       
   678 		aHighlightStartDocPos = aStartDocPos;
       
   679 		}
       
   680 	
       
   681 	if (aEndDocPos > aHighlightEndDocPos)
       
   682 		{
       
   683 		aHighlightEndDocPos = aEndDocPos;
       
   684 		}
       
   685 
       
   686 	TCursorSelection selection;
       
   687 	selection.SetSelection(aHighlightStartDocPos, aHighlightEndDocPos);
       
   688 
       
   689 	TRect boundingRect;
       
   690 	GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, boundingRect);
       
   691 	aHighlightExtensions.AbsExtendRect(boundingRect);
       
   692 	boundingRect.Intersection(clipRect);
       
   693 	if (! boundingRect.IsEmpty())
       
   694 		{
       
   695 		RTmDrawingInterpreter interpreter(*iSource, aGc, TTmInterpreterParam(*this),
       
   696 			aTopLeft, boundingRect, NULL, ETrue, &selection, &aHighlightExtensions, ETrue);
       
   697 		interpreter.Draw();
       
   698 		interpreter.Close();
       
   699 		}
       
   700 	}
       
   701 
       
   702 /**
       
   703 Calculate the bounding rectangle of the region that must be redrawn to redraw the given document section.
       
   704 @param aStartDocPos
       
   705 	The section starting position
       
   706 @param aEndDocPos
       
   707 	The section ending position
       
   708 @param aTopLeft
       
   709 	Textview position in graphics context coordinates. The resulting region can be used
       
   710 	to clip the drawing in that graphics context.
       
   711 @param aBoundingRect
       
   712 	The resulting bounding rectangle, that is the smallest rectangle that should be redrawn
       
   713 	to redraw the specified document section.
       
   714 */
       
   715 EXPORT_C void CTmTextLayout::GetUpdateBoundingRect(TInt aStartDocPos, TInt aEndDocPos,
       
   716 		const TPoint& aTopLeft, TRect& aBoundingRect) const
       
   717 	{
       
   718 	aBoundingRect = TRect(TRect::EUninitialized);
       
   719 
       
   720 	if (! iSource || aEndDocPos <= aStartDocPos)
       
   721 		{
       
   722 		return;
       
   723 		}
       
   724 
       
   725 	RTmBoundingRectInterpreter interpreter(*iSource, *this);
       
   726 	TRect rect(TRect::EUninitialized); // set by call to RTmBoundingRectInterpreter::FirstRect
       
   727 	TTmDocPos start(aStartDocPos, TRUE);
       
   728 	TTmDocPos end(aEndDocPos,FALSE);
       
   729 	TBool found = interpreter.FirstRect(start.iPos, end.iPos, rect);
       
   730 	while (found)
       
   731 		{
       
   732 		if (! rect.IsEmpty())
       
   733 			{
       
   734 			rect.Move(aTopLeft);
       
   735 			if(aBoundingRect.IsEmpty())
       
   736 				{
       
   737 				aBoundingRect = rect;
       
   738 				}
       
   739 			else
       
   740 				{
       
   741 				aBoundingRect.BoundingRect(rect);
       
   742 				}
       
   743 			}
       
   744 
       
   745 		found = interpreter.NextRect(rect);
       
   746 		}
       
   747 	interpreter.Close();
       
   748 	}
       
   749 
       
   750 EXPORT_C void CTmTextLayout::HighlightSection(CGraphicsContext& aGc,
       
   751 	const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, const TRect& aClipRect) const
       
   752 	{
       
   753 	TTmHighlightExtensions highlightProperties;
       
   754 	highlightProperties.SetAll(0);
       
   755 	HighlightSection(aGc,aTopLeft,aStartDocPos,aEndDocPos,aClipRect,highlightProperties,0,0);
       
   756 	}
       
   757 
       
   758 /**
       
   759 Analogous to HighlightSection(CGraphicsContext&, const TPoint&, TInt, TInt,
       
   760 const TRect&) but with highlight extensions applied.
       
   761 @see HighlightSecion(CGraphicsContext&, const TPoint&, TInt, TInt, const
       
   762 TRect&)
       
   763 @publishedPartner
       
   764 @released
       
   765 */
       
   766 EXPORT_C void CTmTextLayout::HighlightSection(CGraphicsContext& aGc,
       
   767 	const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos,
       
   768 	const TRect& aClipRect, const TTmHighlightExtensions& aHighlightExtensions,
       
   769 	TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const
       
   770 	{
       
   771 	if (0 == aHighlightStartDocPos && 0 == aHighlightEndDocPos)
       
   772 		{
       
   773 		aHighlightStartDocPos = aStartDocPos;
       
   774 		aHighlightEndDocPos = aEndDocPos;
       
   775 		}
       
   776 	else
       
   777 		{
       
   778 		if (aStartDocPos < aHighlightStartDocPos)
       
   779 			{
       
   780 			aHighlightStartDocPos = aStartDocPos;
       
   781 			}
       
   782 		
       
   783 		if (aEndDocPos > aHighlightEndDocPos)
       
   784 			{
       
   785 			aHighlightEndDocPos = aEndDocPos;
       
   786 			}
       
   787 		}
       
   788 
       
   789 	DrawSection(aGc, aTopLeft, aStartDocPos, aEndDocPos, aClipRect, aHighlightExtensions,
       
   790 		aHighlightStartDocPos, aHighlightEndDocPos);
       
   791 	}
       
   792 
       
   793 
       
   794 EXPORT_C void CTmTextLayout::DrawSection(CGraphicsContext& aGc,
       
   795 	const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, const TRect& aClipRect) const
       
   796 	{
       
   797 	TTmHighlightExtensions highlightProperties;
       
   798 	highlightProperties.SetAll(0);
       
   799 	DrawSection(aGc,aTopLeft,aStartDocPos,aEndDocPos,aClipRect,highlightProperties,0,0);
       
   800 	}
       
   801 	
       
   802 /**
       
   803 Analogous to DrawSection(CGraphicsContext&, const TPoint&, TInt, TInt, const
       
   804 TRect&) but with highlight extensions applied.
       
   805 @see DrawSection(CGraphicsContext&, const TPoint&, TInt, TInt, const TRect&)
       
   806 @publishedPartner
       
   807 @released
       
   808 */
       
   809 EXPORT_C void CTmTextLayout::DrawSection(CGraphicsContext& aGc,
       
   810 	const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos,
       
   811 	const TRect& aClipRect, const TTmHighlightExtensions& aHighlightExtensions,
       
   812 	TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const
       
   813 	{
       
   814 	// note: Assumes that RWindow::BeginRedraw() has been called by the caller.
       
   815 
       
   816 	TCursorSelection selection;
       
   817 	selection.SetSelection(aHighlightStartDocPos, aHighlightEndDocPos);
       
   818 
       
   819 	TRect boundingRect;
       
   820 	GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, boundingRect);
       
   821 	if (! boundingRect.IsEmpty())
       
   822 		{
       
   823 		aHighlightExtensions.AbsExtendRect(boundingRect);
       
   824 		boundingRect.Intersection(aClipRect);
       
   825 		if (! boundingRect.IsEmpty())
       
   826 			{
       
   827 			DrawLayout(aGc, aTopLeft, boundingRect, NULL, ETrue, &selection, &aHighlightExtensions);
       
   828 			}
       
   829 		}
       
   830 	}
       
   831 
       
   832 /**
       
   833 Finds a document position and returns information about it and the line it is
       
   834 in.
       
   835 @param aDocPos The position to find.
       
   836 @param aPosInfo Returns information on the found position.
       
   837 @param aLineInfo Returns information on the line containing the position found.
       
   838 @return
       
   839 	True if the position was found within the formatted text. False if the
       
   840 	position was not in the formatted text.
       
   841 */
       
   842 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPosSpec& aDocPos,
       
   843 	TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo) const
       
   844 	{
       
   845 	if (!iSource)
       
   846 		return FALSE;
       
   847 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
   848 	TBool found = interpreter.FindDocPos(aDocPos,aPosInfo);
       
   849 	aLineInfo = interpreter.LineInfo();
       
   850 	interpreter.Close();
       
   851 	return found;
       
   852 	}
       
   853 
       
   854 /**
       
   855 Find a document position and return information about it and the line it is in. Return FALSE if the document
       
   856 position is outside the formatted text. The document position to be found is passed in aDocPos and the information
       
   857 about the position found is returned in aPosInfo. The line information is returned in aLineInfo.
       
   858 @deprecated 7.0s
       
   859 */
       
   860 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPos& aDocPos,TTmPosInfo& aPosInfo,TTmLineInfo& aLineInfo) const
       
   861 	{
       
   862 	TTmDocPosSpec dp = aDocPos;
       
   863 	TTmPosInfo2 pi;
       
   864 	TBool r = FindDocPos(dp, pi, aLineInfo);
       
   865 	aPosInfo = pi;
       
   866 	return r;
       
   867 	}
       
   868 
       
   869 /**
       
   870 Finds a document position and returns information about it and the line it is
       
   871 in.
       
   872 @param aDocPos The position to find.
       
   873 @param aPosInfo Returns information on the found position.
       
   874 @param aLineInfo Returns information on the line containing the position found.
       
   875 @param aSubscript Returns the subscript height value.
       
   876 @return
       
   877 	True if the position was found within the formatted text. False if the
       
   878 	position was not in the formatted text.
       
   879 */
       
   880 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPosSpec& aDocPos,
       
   881 	TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo, TInt& aSubscript) const
       
   882 	{
       
   883 	if (!iSource)
       
   884 		return FALSE;
       
   885 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
   886 	TBool found = interpreter.FindDocPos(aDocPos,aPosInfo);
       
   887 	aLineInfo = interpreter.LineInfo();
       
   888 	aSubscript = interpreter.Subscript();
       
   889 	interpreter.Close();
       
   890 	return found;
       
   891 	}
       
   892 
       
   893 /**
       
   894 Finds a document position (i.e. the edge between two adjacent characters) by
       
   895 x-y position relative to the top-left corner of the formatted text.
       
   896 @param aXyPos Position to find.
       
   897 @param aPosInfo Returns information on the position closest to aXyPos.
       
   898 @param aLineInfo Returns information on the line containing aXyPos.
       
   899 @return
       
   900 	True if the Y-position is within the formatted text, or false otherwise.
       
   901 */
       
   902 EXPORT_C TBool CTmTextLayout::FindXyPos(const TPoint& aXyPos,
       
   903 	TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo) const
       
   904 	{
       
   905 	if (!iSource)
       
   906 		return FALSE;
       
   907 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
   908 	TBool found = interpreter.FindXyPos(aXyPos,aPosInfo);
       
   909 	aLineInfo = interpreter.LineInfo();
       
   910 	interpreter.Close();
       
   911 	return found;
       
   912 	}
       
   913 
       
   914 /**
       
   915 Find an x-y position, relative to the top-left corner of the text, and return information about it and the line it is in.
       
   916 Return FALSE if the position is outside the formatted text. The document position to be found is passed in aDocPos and
       
   917 the information about the position found is returned in aPosInfo. The line information is returned in aLineInfo.
       
   918 @deprecated 7.0s
       
   919 */
       
   920 EXPORT_C TBool CTmTextLayout::FindXyPos(const TPoint& aXyPos,TTmPosInfo& aPosInfo,TTmLineInfo& aLineInfo) const
       
   921 	{
       
   922 	TTmPosInfo2 pi;
       
   923 	TBool r = FindXyPos(aXyPos, pi, aLineInfo);
       
   924 	aPosInfo = pi;
       
   925 	return r;
       
   926 	}
       
   927 
       
   928 /**
       
   929 Return the number of formatted lines.
       
   930 */
       
   931 EXPORT_C TInt CTmTextLayout::Lines() const
       
   932 	{
       
   933 	if (!iSource)
       
   934 		return 0;
       
   935 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   936 	return interpreter.Lines();
       
   937 	}
       
   938 
       
   939 /**
       
   940 Return the number of formatted paragraphs.
       
   941 */
       
   942 EXPORT_C TInt CTmTextLayout::Paragraphs() const
       
   943 	{
       
   944 	if (!iSource)
       
   945 		return 0;
       
   946 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   947 	return interpreter.Paragraphs();
       
   948 	}
       
   949 
       
   950 /**
       
   951 Returns information (including line number and formatting information) of the
       
   952 line containing a given document position.
       
   953 @param aDocPos Position to find.
       
   954 @param aLineInfo
       
   955 	Returns information about the line containing aDocPos if aDocPos is within
       
   956 	the formatted text, or an undefined value if not.
       
   957 @return True if the aDocPos was within the formatted text.
       
   958 */
       
   959 EXPORT_C TBool CTmTextLayout::DocPosToLine(const TTmDocPosSpec& aDocPos,
       
   960 	TTmLineInfo& aLineInfo) const
       
   961 	{
       
   962 	if (!iSource)
       
   963 		return FALSE;
       
   964 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   965 	TBool found = interpreter.DocPosToLine(aDocPos);
       
   966 	aLineInfo = interpreter.LineInfo();
       
   967 	return found;
       
   968 	}
       
   969 
       
   970 /**
       
   971 Retrieve information about the line containing a certain document position.
       
   972 Put information about the line containing aDocPos in aLineInfo. Return FALSE if aDocPos is not in the formatted text.
       
   973 @deprecated 7.0s
       
   974 */
       
   975 EXPORT_C TBool CTmTextLayout::DocPosToLine(const TTmDocPos& aDocPos,TTmLineInfo& aLineInfo) const
       
   976 	{
       
   977 	TTmDocPosSpec dp = aDocPos;
       
   978 	return DocPosToLine(dp, aLineInfo);
       
   979 	}
       
   980 
       
   981 /**
       
   982 Retrieve information about a line, referring to the line by its line number.
       
   983 
       
   984 Put information about the line numbered aLineNumber, counting the first formatted line as 0, in aLineInfo.
       
   985 Return FALSE if aLineNumber is not formatted.
       
   986 */
       
   987 EXPORT_C TBool CTmTextLayout::LineNumberToLine(TInt aLineNumber,TTmLineInfo& aLineInfo) const
       
   988 	{
       
   989 	if (!iSource)
       
   990 		return FALSE;
       
   991 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
   992 	TBool found = interpreter.LineNumberToLine(aLineNumber);
       
   993 	aLineInfo = interpreter.LineInfo();
       
   994 	return found;
       
   995 	}
       
   996 
       
   997 /**
       
   998 Retrieve information about a line, referring to the line by its paragraph number and line number within the paragraph.
       
   999 
       
  1000 Put information about line aLineNumber in paragraph aParNumber, counting the first formatted paragraph as 0,
       
  1001 in aLineInfo. Return FALSE if aParNumber is not formatted. If aLineInPar is greater than the number of lines in
       
  1002 the paragraph the last line in the paragraph is returned.
       
  1003 */
       
  1004 EXPORT_C TBool CTmTextLayout::ParNumberToLine(TInt aParNumber,TInt aLineInPar,TTmLineInfo& aLineInfo) const
       
  1005 	{
       
  1006 	if (!iSource)
       
  1007 		return FALSE;
       
  1008 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
  1009 	TBool found = interpreter.ParNumberToLine(aParNumber,aLineInPar);
       
  1010 	aLineInfo = interpreter.LineInfo();
       
  1011 	return found;
       
  1012 	}
       
  1013 
       
  1014 /**
       
  1015 Retrieve information about a line containing a certain y coordinate.
       
  1016 
       
  1017 Put information about the line containing the y coordinate aYPos, relative to 0 as the top of the formatted text, in
       
  1018 aLineInfo. Return FALSE if aYPos is outside all formatted lines.
       
  1019 */
       
  1020 EXPORT_C TBool CTmTextLayout::YPosToLine(TInt aYPos,TTmLineInfo& aLineInfo) const
       
  1021 	{
       
  1022 	if (!iSource)
       
  1023 		return FALSE;
       
  1024 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
  1025 	TBool found = interpreter.YPosToLine(aYPos);
       
  1026 	aLineInfo = interpreter.LineInfo();
       
  1027 	return found;
       
  1028 	}
       
  1029 
       
  1030 
       
  1031 /**
       
  1032 Retrieve the text as displayed on a particular line.
       
  1033 
       
  1034 The text will be returned in display order, after all transformations have been
       
  1035 applied to the backing text. These transformations include bidirectional
       
  1036 reordering (making Arabic and Hebrew go right to left, etc.), ligation
       
  1037 (combining adjacent characters into a single glyph), suppressing control
       
  1038 characters, and converting characters to visible forms like visible spaces if
       
  1039 necessary.
       
  1040 
       
  1041 Precondition: SetTextL must have been called on this object before
       
  1042 GetDisplayedText can be called.
       
  1043 
       
  1044 Please note that any text that has passed through a shaper (for example
       
  1045 Devanagari text) will be replaced in the returned text with the Unicode
       
  1046 Replacement Character 0xFFFD. This is because the shaper produces glyph codes,
       
  1047 not Unicode characters, and this is because Unicode does not contain all the
       
  1048 ligatures and glyph variants required to display such scripts correctly.
       
  1049 
       
  1050 @param aLineNumber The line to fetch the display text of.
       
  1051 @param aText A buffer into which the display text is placed.
       
  1052 @param aNeeded
       
  1053 	Returns the number of characters in the displayed line. The text is
       
  1054 	truncated if aText is not big enough, aNeeded returns how large the buffer
       
  1055 	would need to be to return the whole line.
       
  1056 @return
       
  1057 	EFalse if the operation is impossible, perhaps because aLineNumber
       
  1058 is too large to be within the text.
       
  1059 @since 7.0
       
  1060 */
       
  1061 EXPORT_C TBool CTmTextLayout::GetDisplayedTextL(TInt aLineNumber, TDes& aText,
       
  1062 	TInt& aNeeded) const
       
  1063 	{
       
  1064 	__ASSERT_ALWAYS(iSource, TmPanic(ENoSource));
       
  1065 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1066 	CleanupClosePushL(interpreter);
       
  1067 	TBool result = interpreter.GetDisplayedTextL(aLineNumber, aText,0, aNeeded);
       
  1068 	CleanupStack::PopAndDestroy();
       
  1069 	return result;
       
  1070 	}
       
  1071 
       
  1072 /**
       
  1073 Retrieve the text as displayed on a particular line. Return FALSE if the operation is impossible (e.g., because no
       
  1074 MTmSource has yet been assigned). The text is returned in aText. The number of characters needed, which may be greater
       
  1075 than the size of aText, is placed in aNeeded.
       
  1076 
       
  1077 The text will be returned in display order, after all transformations have been applied to the backing text. These
       
  1078 transformations include bidirectional reordering (making Arabic and Hebrew go right to left, etc.), ligation (combining
       
  1079 adjacent characters into a single glyph), suppressing control characters, and converting characters to visible forms like
       
  1080 visible spaces if necessary.
       
  1081 @deprecated 7.0 It can fail due to environmental conditions, and should therefore be leavable. Use GetDisplayedTextL instead.
       
  1082 */
       
  1083 EXPORT_C TBool CTmTextLayout::GetDisplayedText(TInt aLineNumber,TDes& aText,TInt& aNeeded) const
       
  1084 	{
       
  1085 	if (!iSource)
       
  1086 		return FALSE;
       
  1087 	TBool result = EFalse;
       
  1088 	TRAPD(err, result = GetDisplayedTextL(aLineNumber, aText, aNeeded));
       
  1089     UNUSED_VAR(err);
       
  1090 	return result;
       
  1091 	}
       
  1092 
       
  1093 /**
       
  1094 Get the size of the minimal bounding box of the text when formatted to the specified wrap width.
       
  1095 The width may be greater than aWrapWidth. To find the minimum width for the text,
       
  1096 pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth.
       
  1097 */
       
  1098 EXPORT_C void CTmTextLayout::GetMinimumLayoutSizeL(TInt aWrapWidth,TSize& aSize) const
       
  1099 	{
       
  1100 		GetMinimumLayoutSizeL(aWrapWidth,ETrue,aSize);
       
  1101 	}
       
  1102 
       
  1103 /**
       
  1104 Get the size of the minimal bounding box of the text when formatted to the specified wrap width.
       
  1105 The width may be greater than aWrapWidth. To find the minimum width for the text,
       
  1106 pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth.
       
  1107 Use aAllowLegalLineBreaksOnly to set whether or not illegal line breaks should be considered
       
  1108 when determining aSize.
       
  1109 */
       
  1110 EXPORT_C void CTmTextLayout::GetMinimumLayoutSizeL(TInt aWrapWidth,TBool aAllowLegalLineBreaksOnly,TSize& aSize) const
       
  1111 	{
       
  1112 	if (!iSource)
       
  1113 		{
       
  1114 		aSize.iWidth = aSize.iHeight = 0;
       
  1115 		return;
       
  1116 		}
       
  1117 	TTmFormatParam param;
       
  1118 	param.iWrapWidth = aWrapWidth;
       
  1119 	param.iFlags = TTmFormatParam::EWrap;
       
  1120 	if(aAllowLegalLineBreaksOnly)
       
  1121 		param.iFlags |= TTmFormatParam::ELegalLineBreaksOnly;
       
  1122 	param.iStartChar = iStartChar;
       
  1123 	param.iEndChar = iEndChar;
       
  1124 	CTmCode* code = new(ELeave) CTmCode;
       
  1125 	CleanupStack::PushL(code);
       
  1126 	CTmFormatContext::TInfo info;
       
  1127 	
       
  1128 	//Get line context character from previous line if there is
       
  1129 	TTmDocPosSpec startDocPos(param.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1));
       
  1130 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
  1131 	TBool lineFound = interpreter.DocPosToLine(startDocPos);
       
  1132 	if (lineFound)
       
  1133 		info.iContextCharPerLine = interpreter.LineContextCharChar();
       
  1134 	else
       
  1135 		info.iContextCharPerLine = NULL;
       
  1136 	
       
  1137 	CTmFormatContext::FormatL(*iSource,param,*code,info,const_cast<CTmTextLayout*>(this));
       
  1138 	CleanupStack::PopAndDestroy(); // code
       
  1139 	aSize.iWidth = info.iWidth;
       
  1140 	aSize.iHeight = info.iHeight;
       
  1141 	}
       
  1142 
       
  1143 /**
       
  1144 Find the width of the widest line in the specified vertical range. The width is the 'inner width'; that of the text
       
  1145 itself not including indents or margins.
       
  1146 */
       
  1147 EXPORT_C TInt CTmTextLayout::WidthOfWidestLine(TInt aTop,TInt aBottom) const
       
  1148 	{
       
  1149 	if (!iSource)
       
  1150 		return 0;
       
  1151 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
  1152 	return interpreter.WidthOfWidestLine(aTop, aBottom);
       
  1153 	}
       
  1154 
       
  1155 EXPORT_C void CTmTextLayout::HorizontalExtremes(
       
  1156 	TInt &aLeft, TInt &aRight, TInt aTopY, TInt aBottomY) const
       
  1157 	{
       
  1158 	if (!iSource)
       
  1159 		{
       
  1160 		aLeft = KMaxTInt;
       
  1161 		aRight = KMinTInt;
       
  1162 		return;
       
  1163 		}
       
  1164 	TTmInterpreter interpreter(TTmInterpreterParam(*this));
       
  1165 	interpreter.HorizontalExtremes(aLeft, aRight, aTopY, aBottomY);
       
  1166 	}
       
  1167 
       
  1168 /**
       
  1169 Finds information about the visual position closest to the point specified. If
       
  1170 there are two positions at this place that represent the ends of blocks that
       
  1171 are not logically contiguous, different positions representing the ends of
       
  1172 these blocks are returned. there is an ambiguity at this position, the document
       
  1173 positions that represent the ends of the different blocks that meet here are
       
  1174 returned.
       
  1175 @param aXyPos
       
  1176 	The position to find.
       
  1177 @param aPosLeft
       
  1178 	The position returned. If this position is ambiguous, this is the position
       
  1179 	attached to the block on the left.
       
  1180 @param aPosRight
       
  1181 	The position returned. If this position is ambiguous, this is the position
       
  1182 	attached to the block on the right. If it is not ambiguous, aPosLeft ==
       
  1183 	aPosRight.
       
  1184 @param aLineInfo
       
  1185 	Information about the line containing aPosLeft and aPosRight.
       
  1186 @return
       
  1187 	ETrue if the position was found. EFalse otherwise. If EFalse, aPosLeft,
       
  1188 	aPosRight and aLineInfo are undefined.
       
  1189 */
       
  1190 EXPORT_C TBool CTmTextLayout::FindXyPosWithDisambiguation(
       
  1191 	const TPoint& aXyPos,
       
  1192 	TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight,
       
  1193 	TTmLineInfo& aLineInfo) const
       
  1194 	{
       
  1195 	if (!iSource)
       
  1196 		return EFalse;
       
  1197 
       
  1198 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1199 	if (!interpreter.YPosToLine(aXyPos.iY))
       
  1200 		return EFalse;
       
  1201 	aLineInfo = interpreter.LineInfo();
       
  1202 
       
  1203 	RTmGraphemeEdgeIterator edgeIterator;
       
  1204 	edgeIterator.Begin(interpreter);
       
  1205 	TTmVisualDocPos pos;
       
  1206 
       
  1207 	edgeIterator.FindXPos(aXyPos.iX, pos);
       
  1208 	aPosLeft = pos.LeftEdge();
       
  1209 	aPosRight = pos.RightEdge();
       
  1210 
       
  1211 	edgeIterator.Close();
       
  1212 	interpreter.Close();
       
  1213 	return pos.Ambiguity() != TTmVisualDocPos::ENotFound;
       
  1214 	}
       
  1215 
       
  1216 /**
       
  1217 Finds the position after the horizontally spacing element after aStart. A
       
  1218 horizontally spacing element is a spacing glyph (such as a letter or number)
       
  1219 plus all its combining accent, or other spacing character such as a tab or
       
  1220 carriage return. This function will also skip any zero-width characters that
       
  1221 precede the next horizontally spacing element.
       
  1222 @param aStart
       
  1223 	Starting position. The returned position will be greater than this.
       
  1224 @return
       
  1225 	The position of the first trailing edge beyond aStart not visually
       
  1226 	coincident with the leading edge of aStart, or KErrNotFound if there is
       
  1227 	none, or it is not within formatted text.
       
  1228 */
       
  1229 EXPORT_C TInt CTmTextLayout::FindNextPos(TInt aStart) const
       
  1230 	{
       
  1231 	if (!iSource)
       
  1232 		return KErrNotFound;
       
  1233 
       
  1234 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1235 
       
  1236 	if (!interpreter.DocPosToLine(TTmDocPos(aStart + 1, EFalse)))
       
  1237 		return KErrNotFound;
       
  1238 
       
  1239 	RTmGraphemeEdgeIterator edgeIterator;
       
  1240 	edgeIterator.Begin(interpreter);
       
  1241 
       
  1242 	TInt pos = edgeIterator.NextPosition(aStart);
       
  1243 
       
  1244 	edgeIterator.Close();
       
  1245 	interpreter.Close();
       
  1246 	return pos;
       
  1247 	}
       
  1248 
       
  1249 /**
       
  1250 Finds the position before the horizontally spacing element before aStart.
       
  1251 Zero-width characters immediately before aStart are also skipped.
       
  1252 @param aStart
       
  1253 	Starting position. The returned position will be greater than this.
       
  1254 @return
       
  1255 	The position of the first trailing edge beyond aStart not visually
       
  1256 	coincident with the leading edge of aStart, or KErrNotFound if there is
       
  1257 	none, or it is not within formatted text.
       
  1258 @see FindNextPos
       
  1259 */
       
  1260 EXPORT_C TInt CTmTextLayout::FindPreviousPos(TInt aStart) const
       
  1261 	{
       
  1262 	if (!iSource)
       
  1263 		return KErrNotFound;
       
  1264 
       
  1265 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1266 
       
  1267 	if (!interpreter.DocPosToLine(TTmDocPos(aStart - 1, ETrue)))
       
  1268 		return KErrNotFound;
       
  1269 
       
  1270 	RTmGraphemeEdgeIterator edgeIterator;
       
  1271 	edgeIterator.Begin(interpreter);
       
  1272 
       
  1273 	TInt pos = edgeIterator.PreviousPosition(aStart);
       
  1274 
       
  1275 	edgeIterator.Close();
       
  1276 	interpreter.Close();
       
  1277 	return pos;
       
  1278 	}
       
  1279 
       
  1280 /**
       
  1281 Finds information about the position visually to the left of the position
       
  1282 specified, as long as it is on the same line. If there are two positions at
       
  1283 this place that represent the ends of blocks that are not logically contiguous,
       
  1284 different positions representing the ends of these blocks are returned.
       
  1285 @param aDocPos
       
  1286 	The position to find.
       
  1287 @param aPosLeft
       
  1288 	The position returned. If this position is ambiguous, this is the position
       
  1289 	attached to the block on the left.
       
  1290 @param aPosRight
       
  1291 	The position returned. If this position is ambiguous, this is the position
       
  1292 	attached to the block on the right. If it is not ambiguous, aPosLeft ==
       
  1293 	aPosRight.
       
  1294 @return
       
  1295 	ETrue if the position was found on the same line as aDocPos. EFalse
       
  1296 	otherwise. If EFalse, aPosLeft and aPosRight are undefined.
       
  1297 */
       
  1298 EXPORT_C TBool CTmTextLayout::GetNextPosLeftWithDisambiguation(
       
  1299 	const TTmDocPosSpec& aDocPos,
       
  1300 	TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight) const
       
  1301 	{
       
  1302 	if (!iSource)
       
  1303 		return EFalse;
       
  1304 
       
  1305 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1306 	if (!interpreter.DocPosToLine(aDocPos))
       
  1307 		return EFalse;
       
  1308 
       
  1309 	RTmGraphemeEdgeIterator edgeIterator;
       
  1310 	edgeIterator.Begin(interpreter);
       
  1311 	TTmPosInfo2 closest;
       
  1312 	TTmVisualDocPos next;
       
  1313 
       
  1314 	edgeIterator.FindEdgeLeftwards(aDocPos, closest, next);
       
  1315 	aPosLeft = next.LeftEdge();
       
  1316 	aPosRight = next.RightEdge();
       
  1317 
       
  1318 	edgeIterator.Close();
       
  1319 	interpreter.Close();
       
  1320 	return next.Ambiguity() != TTmVisualDocPos::ENotFound;
       
  1321 	}
       
  1322 
       
  1323 /**
       
  1324 Finds information about the position visually to the right of the position
       
  1325 specified, as long as it is on the same line. If there are two positions at
       
  1326 this place that represent the ends of blocks that are not logically contiguous,
       
  1327 different positions representing the ends of these blocks are returned.
       
  1328 @param aDocPos
       
  1329 	The position to find.
       
  1330 @param aPosLeft
       
  1331 	The position returned. If this position is ambiguous, this is the position
       
  1332 	attached to the block on the left.
       
  1333 @param aPosRight
       
  1334 	The position returned. If this position is ambiguous, this is the position
       
  1335 	attached to the block on the right. If it is not ambiguous, aPosLeft ==
       
  1336 	aPosRight.
       
  1337 @return
       
  1338 	ETrue if the position was found on the same line as aDocPos. EFalse
       
  1339 	otherwise. If EFalse, aPosLeft and aPosRight are undefined.
       
  1340 */
       
  1341 EXPORT_C TBool CTmTextLayout::GetNextPosRightWithDisambiguation(
       
  1342 	const TTmDocPosSpec& aDocPos,
       
  1343 	TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight) const
       
  1344 	{
       
  1345 	if (!iSource)
       
  1346 		return EFalse;
       
  1347 
       
  1348 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1349 	if (!interpreter.DocPosToLine(aDocPos))
       
  1350 		return EFalse;
       
  1351 
       
  1352 	RTmGraphemeEdgeIterator edgeIterator;
       
  1353 	edgeIterator.Begin(interpreter);
       
  1354 	TTmPosInfo2 closest;
       
  1355 	TTmVisualDocPos next;
       
  1356 
       
  1357 	edgeIterator.FindEdgeRightwards(aDocPos, closest, next);
       
  1358 	aPosLeft = next.LeftEdge();
       
  1359 	aPosRight = next.RightEdge();
       
  1360 
       
  1361 	edgeIterator.Close();
       
  1362 	interpreter.Close();
       
  1363 	return next.Ambiguity() != TTmVisualDocPos::ENotFound;
       
  1364 	}
       
  1365 
       
  1366 /**
       
  1367 Find the nearest document position to the current one in the visual direction
       
  1368 specified. This only works if the document position is within formatted text.
       
  1369 False is returned if this condition is not met.
       
  1370 @param aDocPos Start position.
       
  1371 @param aInfo
       
  1372 	Returns the position found, or an undefined value if aDocPos is not in
       
  1373 	formatted text or is already at the end of the line in the direction being
       
  1374 	searched.
       
  1375 @param aToLeft True if the direction to search in is leftwards.
       
  1376 @return True if the next position was found (see the description of aInfo).
       
  1377 */
       
  1378 EXPORT_C TBool CTmTextLayout::GetNextVisualCursorPos(
       
  1379 	const TTmDocPosSpec& aDocPos, TTmPosInfo2& aInfo, TBool aToLeft) const
       
  1380 	{
       
  1381 	TTmPosInfo2 dummy;
       
  1382 	return aToLeft?
       
  1383 		GetNextPosLeftWithDisambiguation(aDocPos, dummy, aInfo)
       
  1384 		: GetNextPosRightWithDisambiguation(aDocPos, aInfo, dummy);
       
  1385 	}
       
  1386 
       
  1387 /**
       
  1388 Get the next cursor position in visual order. This function is useful for text that contains Arabic, Hebrew, or
       
  1389 other right-to-left languages because it allows the cursor to be moved right or left on the display whatever the
       
  1390 order of the backing text.
       
  1391 
       
  1392 The cursor position to the left or right of aDocPos is found, depending on the value of aToLeft. Information about
       
  1393 the resulting position is returned in aInfo. The function returns TRUE if successful, FALSE if not. A FALSE return value
       
  1394 means that there is no text, or aDocPos is outside the formatted text, or aDocPos cannot move in the required direction
       
  1395 because it is at the end of the line.
       
  1396 @deprecated 7.0s
       
  1397 */
       
  1398 EXPORT_C TBool CTmTextLayout::GetNextVisualCursorPos(const TTmDocPos& aDocPos,TTmPosInfo& aInfo,TBool aToLeft) const
       
  1399 	{
       
  1400 	TTmDocPosSpec dp = aDocPos;
       
  1401 	TTmPosInfo2 pi;
       
  1402 	TBool r = GetNextVisualCursorPos(dp, pi, aToLeft);
       
  1403 	aInfo = pi;
       
  1404 	return r;
       
  1405 	}
       
  1406 
       
  1407 /**
       
  1408 Returns the position at the left or right extreme of the line containing aPos.
       
  1409 @param aToRight EFalse for finding the left hand end, ETrue for the right.
       
  1410 @param aExtreme Returns the document position at the end requested.
       
  1411 @return
       
  1412 	EFalse if the call failed either because the position was unformatted or
       
  1413 	because the line contained no text.
       
  1414 */
       
  1415 EXPORT_C TBool CTmTextLayout::LineExtreme(const TTmDocPosSpec& aPos,
       
  1416 	TBool aToRight, TTmDocPos& aExtreme) const
       
  1417 	{
       
  1418 	TTmPosInfo2 posInfo;
       
  1419 	TTmLineInfo lineInfo;
       
  1420 	if (!FindDocPos(aPos, posInfo, lineInfo))
       
  1421 		return EFalse;
       
  1422 	TPoint extreme(
       
  1423 		aToRight? lineInfo.iInnerRect.iBr.iX : lineInfo.iInnerRect.iTl.iX,
       
  1424 		lineInfo.iInnerRect.iTl.iY);
       
  1425 	if (!FindXyPos(extreme, posInfo, lineInfo))
       
  1426 		return EFalse;
       
  1427 	aExtreme = posInfo.iDocPos;
       
  1428 	return ETrue;
       
  1429 	}
       
  1430 
       
  1431 /**
       
  1432 Returns the chunks of text adjacent to aPos.
       
  1433 @param aLeft Returns a description of the chunk on the left of the cursor.
       
  1434 @param aRight Returns a description of the chunk on the right.
       
  1435 @return
       
  1436 	EFalse if the call failed because the line is not formatted or contains
       
  1437 	no text.
       
  1438 */
       
  1439 EXPORT_C TBool CTmTextLayout::FindAdjacentChunks(const TTmDocPosSpec& aPos,
       
  1440 	CTmTextLayout::TTmChunkDescription& aLeft,
       
  1441 	CTmTextLayout::TTmChunkDescription& aRight) const
       
  1442 	{
       
  1443 	// Following block of code is used to check whether a doc position is shared by two text chunks. 
       
  1444 	TBool overlapped = EFalse;
       
  1445 	TTmChunkInterpreter tempCi(*this);
       
  1446 	if (!tempCi.ChunkSetToLeftOfLine(aPos))
       
  1447 		return EFalse;
       
  1448 	TTmChunkInterpreter::TContainment contain1 = tempCi.ChunkContainsPos(aPos);
       
  1449 	TTmChunkInterpreter::TContainment contain2;
       
  1450 	while(tempCi.ChunkNext())
       
  1451 		{
       
  1452 		contain2 = tempCi.ChunkContainsPos(aPos);
       
  1453 		if ( (contain1 == TTmChunkInterpreter::EMiddleOfChunk && contain2 != TTmChunkInterpreter::ENotInChunk)
       
  1454 				|| (contain1 != TTmChunkInterpreter::ENotInChunk && contain2 == TTmChunkInterpreter::EMiddleOfChunk) )
       
  1455 			{
       
  1456 			overlapped = ETrue;
       
  1457 			break;
       
  1458 			}
       
  1459 		if ( contain1 != TTmChunkInterpreter::ENotInChunk )
       
  1460 			break;
       
  1461 		contain1 = contain2;
       
  1462 		}
       
  1463 	// end of checking...
       
  1464 
       
  1465 	TTmChunkInterpreter ci(*this);
       
  1466 	if (!ci.ChunkSetToLeftOfLine(aPos))
       
  1467 		return EFalse;
       
  1468 	aLeft.iStart = -1;
       
  1469 	if (aPos.iPos == ci.LineInfo().iStart
       
  1470 		&& aPos.iType == TTmDocPosSpec::ETrailing
       
  1471 		&& !(ci.LineInfo().iFlags & TTmLineInfo::EParRightToLeft))
       
  1472 		{
       
  1473 		aRight.iStart = ci.ChunkStart();
       
  1474 		aRight.iEnd = ci.ChunkEnd();
       
  1475 		aRight.iRightToLeft = ci.ChunkRightToLeft();
       
  1476 		return ETrue;
       
  1477 		}
       
  1478 	TTmChunkInterpreter::TContainment containment = ci.ChunkContainsPos(aPos);
       
  1479 	// When a doc postion is overlapped, it would be in middle of one chunk and on edge of another
       
  1480 	// chunk, so (MiddleOfChunk && overlapped) is also included.
       
  1481 	while (containment == TTmChunkInterpreter::ENotInChunk
       
  1482 		|| containment == TTmChunkInterpreter::ERightEdgeOfChunk
       
  1483 		||(containment == TTmChunkInterpreter::EMiddleOfChunk && overlapped))
       
  1484 		{
       
  1485 		aLeft.iStart = ci.ChunkStart();
       
  1486 		aLeft.iEnd = ci.ChunkEnd();
       
  1487 		aLeft.iRightToLeft = ci.ChunkRightToLeft();
       
  1488 		if (!ci.ChunkNext())
       
  1489 			{
       
  1490 			aRight.iStart = -1;
       
  1491 			return ETrue;
       
  1492 			}
       
  1493 
       
  1494 		if ( containment == TTmChunkInterpreter::ENotInChunk )
       
  1495 			{
       
  1496 			containment = ci.ChunkContainsPos(aPos);
       
  1497 			}
       
  1498 		else if (containment == TTmChunkInterpreter::EMiddleOfChunk && overlapped)
       
  1499 			{
       
  1500 			containment = ci.ChunkContainsPos(aPos);
       
  1501 			// just in case the doc position is in middle of both of the two overlapped chunks,
       
  1502 			// however this should not happen.
       
  1503 			if (containment == TTmChunkInterpreter::EMiddleOfChunk)
       
  1504 				break;
       
  1505 			}
       
  1506 		else if (containment == TTmChunkInterpreter::ERightEdgeOfChunk)
       
  1507 			{
       
  1508 			containment = TTmChunkInterpreter::ELeftEdgeOfChunk;
       
  1509 			}
       
  1510 		}
       
  1511 	if (containment == TTmChunkInterpreter::ELeftEdgeOfChunk)
       
  1512 		{
       
  1513 		aRight.iStart = ci.ChunkStart();
       
  1514 		aRight.iEnd = ci.ChunkEnd();
       
  1515 		aRight.iRightToLeft = ci.ChunkRightToLeft();
       
  1516 		return ETrue;
       
  1517 		}
       
  1518 	// position is in the middle of a chunk, so we will split it.
       
  1519 	if (ci.ChunkRightToLeft())
       
  1520 		{
       
  1521 		aLeft.iRightToLeft = ETrue;
       
  1522 		aRight.iRightToLeft = ETrue;
       
  1523 		aRight.iStart = ci.ChunkStart();
       
  1524 		aRight.iEnd = aPos.iPos;
       
  1525 		aLeft.iStart = aPos.iPos;
       
  1526 		aLeft.iEnd = ci.ChunkEnd();
       
  1527 		}
       
  1528 	else
       
  1529 		{
       
  1530 		aLeft.iRightToLeft = EFalse;
       
  1531 		aRight.iRightToLeft = EFalse;
       
  1532 		aLeft.iStart = ci.ChunkStart();
       
  1533 		aLeft.iEnd = aPos.iPos;
       
  1534 		aRight.iStart = aPos.iPos;
       
  1535 		aRight.iEnd = ci.ChunkEnd();
       
  1536 		}
       
  1537 	return ETrue;
       
  1538 	}
       
  1539 
       
  1540 /**
       
  1541 Returns metrics for the cursor suitable for the document position and placement
       
  1542 specified, as well as information about the line containing the position
       
  1543 specified.
       
  1544 @param aDocPos The document position to return information about.
       
  1545 @param aPlacement The shape of the cursor.
       
  1546 @param aLineInfo
       
  1547 	Returns information about the line containing aDocPos if this position is
       
  1548 	within the formatted text, or an undefined value otherwise.
       
  1549 @param aOrigin
       
  1550 	Returns a position to which aWidth, aAscent and aDescent is relative if the
       
  1551 	position is within formatted text. Returns an undefined value otherwise.
       
  1552 	This position will be on the baseline of the character found.
       
  1553 @param aWidth
       
  1554 	When aPlacement is ECursorVertical aWidth represents which side of the
       
  1555 	origin to paint the cursor, -1 paint left, +1 paint right. When aPlacement
       
  1556 	is ECursorUnderlineXXXX aWidth represents the X offset from the origin X to
       
  1557 	draw the cursor between, -ve for previous & +ve for next when text L2R
       
  1558 	(e.g. Latin), +ve for previous & -ve for next when text is R2L (e.g. Arabic)
       
  1559 @param aAscent
       
  1560 	Returns how far above aOrigin the cursor extends if aDocPos is within
       
  1561 	formatted text, or an undefined value otherwise.
       
  1562 @param aDescent
       
  1563 	Returns how far below aOrigin the cursor extends if aDocPos is within
       
  1564 	formatted text, or an undefined value otherwise.
       
  1565 */
       
  1566 EXPORT_C TBool CTmTextLayout::GetCursor(const TTmDocPosSpec& aDocPos,TTmCursorPlacement aPlacement,
       
  1567 		TTmLineInfo& aLineInfo,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const
       
  1568 	{
       
  1569 	aOrigin.SetXY(0,0);
       
  1570 	aWidth = aAscent = aDescent = 0;
       
  1571 	if (!iSource)
       
  1572 		return EFalse;
       
  1573 
       
  1574 	RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this));
       
  1575 	if (!interpreter.DocPosToLine(aDocPos))
       
  1576 		return EFalse;
       
  1577 	RTmGraphemeEdgeIterator edgeIterator;
       
  1578 	edgeIterator.Begin(interpreter);
       
  1579 
       
  1580 	TTmPosInfo2 this_info;
       
  1581 	TTmVisualDocPos next;
       
  1582 	TBool go_left = (aPlacement == ECursorUnderlinePrev);
       
  1583 	RTmGraphemeEdgeIterator::TEdgesFound found = go_left?
       
  1584 		edgeIterator.FindEdgeLeftwards(aDocPos, this_info, next)
       
  1585 		: edgeIterator.FindEdgeRightwards(aDocPos, this_info, next);
       
  1586 	if (found == RTmGraphemeEdgeIterator::ENone)
       
  1587 		{
       
  1588 		edgeIterator.Close();
       
  1589 		interpreter.Close();
       
  1590 		return EFalse;
       
  1591 		}
       
  1592 	TPoint nextPoint = this_info.iEdge;
       
  1593 	if (found == RTmGraphemeEdgeIterator::ENearestAndNext)
       
  1594 		nextPoint = next.NearestToX(nextPoint.iX)->iEdge;
       
  1595 
       
  1596 	aOrigin = go_left ? nextPoint : this_info.iEdge;
       
  1597 	aLineInfo = interpreter.LineInfo();
       
  1598 
       
  1599 	int pos = this_info.iDocPos.iPos;
       
  1600 	if (pos > interpreter.LineInfo().iStart || !interpreter.ParStart())
       
  1601 		pos--;
       
  1602 	TPtrC text;
       
  1603 	CTmTextFontCache* font = NULL;
       
  1604 	interpreter.GetText(pos,KMaxTInt,text,NULL,&font);
       
  1605 
       
  1606 	if (font)
       
  1607 		{
       
  1608 		if (aPlacement == ECursorVertical)
       
  1609 			{
       
  1610 			aAscent = font->Font().AscentInPixels();
       
  1611 			aDescent = font->Font().DescentInPixels();
       
  1612 			// In case the cursor is positioned on some super/sub or normal 
       
  1613 			// font we need to adjust the Y position of the cursor with the 
       
  1614 			// font's baseline offset so the cursor sits on the same horizon 
       
  1615 			// as the text.
       
  1616 			aOrigin.iY += font->Font().BaselineOffsetInPixels();
       
  1617 			// -1 indicates that the cursor should hang to the left: this is
       
  1618 			// for right-to-left paragraphs.
       
  1619 			aWidth = aLineInfo.iFlags & TTmLineInfo::EParRightToLeft? -1 : 1;
       
  1620 			}
       
  1621 		else
       
  1622 			{
       
  1623 			aAscent = 0;
       
  1624 			aDescent = 1;
       
  1625 			aWidth = nextPoint.iX - this_info.iEdge.iX;
       
  1626 			// The next if doesn't work to well with ECursorUnderlinePrev 
       
  1627 			// placement as it is an approximation.
       
  1628 			if (aWidth == 0) // Triggered when at start or end of text line
       
  1629 				aWidth = font->Font().HeightInPixels() / 2;
       
  1630 			if (aWidth < 0)
       
  1631 				aWidth = -aWidth;
       
  1632 			}
       
  1633 		font->Close();
       
  1634 		}
       
  1635 	else
       
  1636 		found = RTmGraphemeEdgeIterator::ENone;
       
  1637 	edgeIterator.Close();
       
  1638 	interpreter.Close();
       
  1639 	return found != RTmGraphemeEdgeIterator::ENone;
       
  1640 	}
       
  1641 
       
  1642 /**
       
  1643 Return cursor metrics suitable for the supplied document position and placement.
       
  1644 The cursor is defined like a character, with an origin, width, height and depth.
       
  1645 This allows the caller to preserve the origin while overriding the other metrics.
       
  1646 @deprecated 7.0s
       
  1647 */
       
  1648 EXPORT_C TBool CTmTextLayout::GetCursor(const TTmDocPos& aDocPos,TTmCursorPlacement aPlacement,
       
  1649 		TTmLineInfo& aLineInfo,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const
       
  1650 	{
       
  1651 	TTmDocPosSpec dp = aDocPos;
       
  1652 	return GetCursor(dp, aPlacement, aLineInfo, aOrigin, aWidth, aAscent, aDescent);
       
  1653 	}
       
  1654 
       
  1655 /**
       
  1656 Return the amount of memory used by a CTmTextLayout object,
       
  1657 The amount returned is in bytes.
       
  1658 The amount returned does not include memory used by non-owned objects.
       
  1659 */
       
  1660 EXPORT_C TInt CTmTextLayout::MemoryUsed() const
       
  1661 	{
       
  1662 	return sizeof(*this) + iCode.MemoryUsed() - sizeof(iCode);
       
  1663 	}
       
  1664 
       
  1665 /** 
       
  1666 Stops or allows text to be drawn.  Included to allow users to control visibility
       
  1667 if text is part of an invisible control.
       
  1668 */
       
  1669 EXPORT_C void CTmTextLayout::MakeVisible(TBool aVisible)
       
  1670 	{
       
  1671 	if(aVisible)
       
  1672 		{
       
  1673 		iDrawingInterpFlags &= ~RTmDrawingInterpreter::EInvisible;
       
  1674 		}
       
  1675 	else
       
  1676 		{
       
  1677 		iDrawingInterpFlags |= RTmDrawingInterpreter::EInvisible;
       
  1678 		}
       
  1679 	}
       
  1680 
       
  1681 TInt CTmTextLayout::GetDrawingInterpFlags() const
       
  1682 	{
       
  1683 	return iDrawingInterpFlags;
       
  1684 	}
       
  1685 
       
  1686 #ifdef _DEBUG
       
  1687 void CTmTextLayout::Invariant() const
       
  1688 	{
       
  1689 	int lines = Lines();
       
  1690 	if (lines > 0)
       
  1691 		{
       
  1692 		TTmLineInfo info;
       
  1693 		if (!LineNumberToLine(lines - 1,info))
       
  1694 			TmPanic(EInvariant);
       
  1695 		int end = info.iEnd;
       
  1696 		if (end != iEndChar)
       
  1697 			TmPanic(EInvariant);
       
  1698 		}
       
  1699 	}
       
  1700 #endif
       
  1701 
       
  1702 /*
       
  1703 Adjust the width of the text, taking overwidth paragraphs like non-wrapped ones into account.
       
  1704 aParam is the formatting parameters.
       
  1705 aWidthOfNewText is the width of the widest line of any new text that has been inserted and has caused the adjustment.
       
  1706 */
       
  1707 void CTmTextLayout::AdjustWidth(const TTmFormatParamBase& aParam,TInt aWidthOfNewText)
       
  1708 	{
       
  1709 	if (aParam.IsWrapping())
       
  1710 		{
       
  1711 		int wrap_width = aParam.iWrapWidth;
       
  1712 		int x_scale = 1000;
       
  1713 		int y_scale = 1000;
       
  1714 		CalculateScale(*iSource,x_scale,y_scale);
       
  1715 		if (x_scale != 1000)
       
  1716 			wrap_width = wrap_width * x_scale / 1000;
       
  1717 		if (iWidth > wrap_width || aWidthOfNewText > wrap_width)
       
  1718 			{
       
  1719 			iWidth = WidthOfWidestLine();
       
  1720 			if (iWidth < wrap_width)
       
  1721 				iWidth = wrap_width;
       
  1722 			}
       
  1723 		else
       
  1724 			iWidth = wrap_width;
       
  1725 		}
       
  1726 	else
       
  1727 		iWidth = WidthOfWidestLine();
       
  1728 	}
       
  1729 
       
  1730 /**
       
  1731 The equality operator.
       
  1732 @return True if both sides are identical.
       
  1733 */
       
  1734 EXPORT_C TBool TTmDocPos::operator==(const TTmDocPos& aPos) const
       
  1735 	{
       
  1736 	return iPos == aPos.iPos && !iLeadingEdge == !aPos.iLeadingEdge;
       
  1737 	}
       
  1738 
       
  1739 /**
       
  1740 Greater than operator.
       
  1741 @return
       
  1742 	True if the left side of the operator is further on in the document than
       
  1743 	the right hand side.
       
  1744 */
       
  1745 EXPORT_C TBool TTmDocPos::operator>(const TTmDocPos& aPos) const
       
  1746 	{
       
  1747 	return iPos > aPos.iPos || (iPos == aPos.iPos && iLeadingEdge && !aPos.iLeadingEdge);
       
  1748 	}
       
  1749 
       
  1750 /**
       
  1751 Greater than or equal to operator.
       
  1752 @return
       
  1753 	True if the left side of the operator is further on in the document than
       
  1754 	the right hand side or if both sides are identical.
       
  1755 */
       
  1756 EXPORT_C TBool TTmDocPos::operator>=(const TTmDocPos& aPos) const
       
  1757 	{
       
  1758 	return iPos > aPos.iPos || (iPos == aPos.iPos && (iLeadingEdge || !aPos.iLeadingEdge));
       
  1759 	}