os/textandloc/textrendering/textformatting/tbox/CARET.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 1997-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 *
    16 */
    17 
    18 
    19 #include "FRMTLAY.H"
    20 #include "FRMLAYDT.H"
    21 #include "FRMCONST.H"
    22 
    23 #include "OstTraceDefinitions.h"
    24 #ifdef OST_TRACE_COMPILER_IN_USE
    25 #include "CARETTraces.h"
    26 #endif
    27 
    28 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    29 #include "FRMCONST_INTERNAL.H"
    30 #include "FRMCONST_PARTNER.H"
    31 #include "TAGMA_INTERNAL.H"
    32 #endif
    33 
    34 // Set the top of the line containing aDocPos to the y coordinate aYPos.
    35 TInt TCursorPosition::ViewTopOfLineL(const TTmDocPos& aDocPos,TInt& aYPos)
    36 	{
    37 	TViewYPosQualifier yPosQualifier;
    38 	yPosQualifier.SetHotSpot(TViewYPosQualifier::EFViewTopOfLine);
    39 	yPosQualifier.SetFillScreen(ETrue);
    40 	return iLayout->SetViewL(aDocPos,aYPos,yPosQualifier);
    41 	}
    42 
    43 void TCursorPosition::CheckSelection(TBool aSelect)
    44 	{
    45 	if (IsSelection() && iDocPos.iPos == iAnchor)
    46 	    {
    47 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_CHECKSELECTION, "EFSelectedRangeZeroLen" );
    48 	    }
    49 	    
    50 	__ASSERT_DEBUG(!IsSelection() || iDocPos.iPos != iAnchor,FormPanic(EFSelectedRangeZeroLen));
    51 	CheckNullSelection();
    52 	TUint drawSelectionFlags = 0;
    53 	iOldDocPos=iDocPos.iPos;
    54 	iOldAnchor=iAnchor;
    55 	if (IsPictureFrame())
    56 		{
    57 		drawSelectionFlags |= EDrawOldPictureFrame;
    58 		}
    59 	if (iFlags & ESelected)
    60 		{
    61 		if (!aSelect)
    62 			iFlags &= ~ESelected;
    63 		if (aSelect || !IsPictureFrame())
    64 			drawSelectionFlags |= EDrawHighlight;
    65 		if (aSelect && IsPictureFrame())
    66 			iAnchor=iOldDocPos;
    67 		}
    68 	else
    69 		{
    70 		if (aSelect)
    71 			{
    72 			iAnchor=iDocPos.iPos;	//Change the value of iOldDocPos so that the old highlight appears to be empty
    73 			iFlags |= ESelected;
    74 			drawSelectionFlags |= EDrawHighlight;
    75 			}
    76 		iOldDocPos=iOldAnchor=iAnchor;
    77 		}
    78 	iFlags &= ~(EDrawHighlight | EDrawOldPictureFrame | EDrawNewPictureFrame);
    79 	iFlags |= drawSelectionFlags;
    80 	}
    81 
    82 // The cursor pos has changed so the selection might be zero length
    83 void TCursorPosition::CheckNullSelection()
    84 	{
    85 	if ((iFlags & ESelected) && iDocPos.iPos == iAnchor)
    86 		iFlags &= ~ESelected;
    87 	}
    88 
    89 TBool TCursorPosition::IsPictureFrame() const
    90 	{
    91 	if (iFlags & EReturnPreviousHighlight)
    92 		return (iFlags & EDrawOldPictureFrame) != 0;
    93 	else
    94 		return (iFlags & EDrawNewPictureFrame) != 0;
    95 	}
    96 
    97 TBool TCursorPosition::IsNewPictureFrame() const
    98 	{
    99 	return (iFlags & EDrawNewPictureFrame) != 0;
   100 	}
   101 
   102 TInt TCursorPosition::SetSelectionL(const TCursorSelection& aSelection)
   103 	//
   104 	//Change the highlighted region to be that specified
   105 	//
   106 	{
   107 	TInt scroll=0;
   108  	TInt botOfWin=iLayout->BandHeight();
   109 	TInt firstVisChar;
   110 	TTmLineInfo lower_line_info;
   111 	TTmLineInfo higher_line_info;
   112 	TTmDocPos lower_doc_pos = TTmDocPos(aSelection.LowerPos(), ETrue);
   113 	TTmDocPos higher_doc_pos = TTmDocPos(aSelection.HigherPos(), EFalse);
   114 	TInt lowerPos = iLayout->PosInBand(lower_doc_pos,&lower_line_info) ? EFInside : EFAbove;
   115 	TInt higherPos = iLayout->PosInBand(higher_doc_pos,&higher_line_info) ? EFInside : EFAbove;
   116 	TInt selectionPos = EFInside;
   117 	TInt extraScroll;
   118 	TBool cursorVisible = EFalse;
   119 
   120 	if (aSelection.iCursorPos<0 || aSelection.iCursorPos>iLayout->DocumentLength())
   121 	    {
   122 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_SETSELECTIONL, "EFInvalidDocPos" );
   123 	    }
   124 	__ASSERT_DEBUG(aSelection.iCursorPos>=0 && aSelection.iCursorPos<=iLayout->DocumentLength()
   125 																		,FormPanic(EFInvalidDocPos));
   126 	iLayout->PosRangeInBand(firstVisChar);
   127 	if (lowerPos == EFInside)
   128 		{
   129 		if (lower_line_info.iOuterRect.iTl.iY < 0)
   130 			lowerPos = EFAbove;
   131 		}
   132 	else if (firstVisChar < aSelection.LowerPos())
   133 		lowerPos = EFBelow;
   134 
   135 	if (higherPos==EFInside)
   136 		{
   137 		if (higher_line_info.iOuterRect.iBr.iY > botOfWin + 1)
   138 			higherPos=EFBelow;
   139 		}
   140 	else if (firstVisChar < aSelection.HigherPos())
   141 		higherPos = EFBelow;
   142 	CheckSelection(ETrue);
   143 
   144 	iAnchor = aSelection.iAnchorPos;
   145 	if (lower_doc_pos.iPos == aSelection.iCursorPos)
   146 		iDocPos = lower_doc_pos;
   147 	else
   148 		iDocPos = higher_doc_pos;
   149 
   150 	if (lowerPos==EFAbove)
   151 		{
   152 		selectionPos=EFBelow;
   153 		if (aSelection.iCursorPos==aSelection.HigherPos() && higherPos==EFBelow)
   154 			selectionPos=EFAbove;
   155 		}
   156 	else if (higherPos==EFBelow)
   157 		selectionPos=EFAbove;
   158 
   159 	if (selectionPos == EFBelow || selectionPos == EFAbove)
   160 		{
   161 		TViewYPosQualifier yPosQualifier;
   162 		yPosQualifier.SetMakeLineFullyVisible();
   163 		TInt docPos = aSelection.LowerPos();
   164 		TInt desiredY = scroll;
   165 		if (selectionPos == EFBelow)
   166 			{
   167 			yPosQualifier.SetHotSpot(TViewYPosQualifier::EFViewTopOfLine);
   168 			yPosQualifier.SetFillScreen(TRUE);
   169 			}
   170 		else
   171 			{
   172 			desiredY = botOfWin;
   173 			docPos = aSelection.iCursorPos < aSelection.iAnchorPos?
   174 				aSelection.iAnchorPos - 1 : aSelection.iCursorPos;
   175 			yPosQualifier.SetHotSpot(TViewYPosQualifier::EFViewBottomOfLine);
   176 			}
   177 		if (aSelection.iCursorPos == docPos)
   178 			cursorVisible = ETrue;
   179 		scroll = iLayout->SetViewL(docPos, desiredY, yPosQualifier);
   180 		}
   181 
   182 	if (cursorVisible)
   183 		extraScroll=DoSetVisibleDocPosL(TTmDocPos(aSelection.iCursorPos, ETrue));
   184 	else
   185 		extraScroll=DoSetDocPosL(TTmDocPos(aSelection.iCursorPos, ETrue));
   186 	if (scroll!=CTextLayout::EFScrollRedrawWholeScreen)
   187 		scroll+=extraScroll;
   188 	return scroll;
   189 	}
   190 
   191 void TCursorPosition::SetPendingSelection(const TCursorSelection& aSelection)
   192 	{
   193 	iFlags &= ~(ESelected | EDrawHighlight | EDrawOldPictureFrame | EDrawNewPictureFrame);
   194 	iDocPos.iPos = aSelection.iCursorPos;
   195 	iDocPos.iLeadingEdge = aSelection.iCursorPos < aSelection.iAnchorPos ? ETrue : EFalse;
   196 	iAnchor = aSelection.iAnchorPos;
   197 	if (iDocPos.iPos != iAnchor)
   198 		iFlags |= ESelected;
   199 	iLayout->SetTextViewCursorPos(this); // Put in for INC092568
   200 	}
   201 
   202 void TCursorPosition::GetOldSelection(TCursorSelection& aSelection) const
   203 	{
   204 	aSelection.iAnchorPos = iOldAnchor;
   205 	aSelection.iCursorPos = iOldDocPos;
   206 	}
   207 
   208    // Return the highlighted range
   209 void TCursorPosition::GetSelection(TCursorSelection& aSelection) const
   210 	{
   211 	if (iFlags & EReturnPreviousHighlight)
   212 		GetOldSelection(aSelection);
   213 	else
   214 		{
   215 		aSelection.iCursorPos = iDocPos.iPos;
   216 		aSelection.iAnchorPos = iFlags & ESelected? iAnchor : iDocPos.iPos;
   217 		}
   218 	}
   219 
   220 /**
   221 Selection of the left end or right end of a run of text. If both ends are in 
   222 one line, the logical end that is visually in the direction specified will be 
   223 chosen. If aStart and aEnd are in different lines, then we look at whether 
   224 aEnd is choosing the end that is furthest forwards or furthest back by comparing
   225 it against the directionality of the paragraph containing aStart.
   226 @return Reference to aStart or aEnd.
   227 @internalComponent
   228 */
   229 const TTmDocPos& TCursorPosition::VisualEndOfRunL(
   230 	const TTmDocPos& aStart, const TTmDocPos& aEnd,
   231 	TVisualEnd aDirection)
   232 	{
   233 	iLayout->ExtendFormattingToCoverPosL(aStart.iPos);
   234 	iLayout->ExtendFormattingToCoverPosL(aEnd.iPos);
   235 
   236 	TTmPosInfo2 startInfo;
   237 	TTmLineInfo startLine;
   238 	iLayout->FindDocPos(aStart, startInfo, &startLine);
   239 	TTmPosInfo2 endInfo;
   240 	iLayout->FindDocPos(aEnd, endInfo);
   241 
   242 	TVisualEnd startEnd = startInfo.iEdge.iX < endInfo.iEdge.iX?
   243 		EVisualLeft : EVisualRight;
   244 
   245 	if (startInfo.iEdge.iY != endInfo.iEdge.iY)
   246 		{
   247 		// not the same line
   248 		TVisualEnd backwards = startLine.iFlags & TTmLineInfo::EParRightToLeft?
   249 			EVisualRight : EVisualLeft;
   250 		TVisualEnd forwards = backwards? EVisualLeft : EVisualRight;
   251 		startEnd = aStart < aEnd? backwards : forwards;
   252 		}
   253 	return startEnd == aDirection? aStart : aEnd;
   254 	}
   255 
   256 // Set the cursor position to aDocPos and update the stored selection according to the value of aDragSelectOn.
   257 TInt TCursorPosition::SetDocPosL(TBool aDragSelectOn,const TTmDocPos& aDocPos)
   258 	{
   259 	CheckSelection(aDragSelectOn);
   260 	return DoSetDocPosL(aDocPos);
   261 	}
   262 
   263 // Set the cursor position to aDocPos.
   264 TInt TCursorPosition::DoSetDocPosL(const TTmDocPos& aDocPos)
   265 	{
   266 	TInt scroll = 0;
   267 	if (iLayout->PosInBand(aDocPos))
   268 		scroll = DoSetVisibleDocPosL(aDocPos);
   269 	else
   270 		{
   271 		iDocPos = aDocPos; // in case the next line leaves
   272 		scroll = ViewTopOfLineL(aDocPos,scroll);
   273 		DoSetVisibleDocPosL(aDocPos);
   274 		}
   275 	return scroll;
   276 	}
   277 
   278 // Set the cursor position to the specified document position.
   279 TInt TCursorPosition::DoSetVisibleDocPosL(const TTmDocPos& aDocPos)
   280 	{
   281 	iDocPos = aDocPos;
   282 	CheckNullSelection();
   283 	TTmPosInfo2 pos_info;
   284 	iLayout->FindDocPos(aDocPos,pos_info);
   285 	TInt pixels = CheckCursorOnScreenL(pos_info.iEdge.iY);
   286 	UpdateLatentX(pos_info.iEdge.iX);
   287 	UpdateLatentY(pos_info.iEdge.iY);
   288 	return pixels;
   289 	}
   290 
   291 TInt TCursorPosition::SetXyPosL(TBool aDragSelectOn,TPoint aPos,TBool aAllowPictureFrame)
   292 	//
   293 	//Move the cursor back to the point on the screen nearest to the position specified
   294 	//and return the document position and screen position
   295 	//and update the saved X and Y positions
   296 	//
   297 	{
   298 	TPoint originalPoint = aPos;
   299 	TInt pixels=0;
   300 
   301 	CheckSelection(aDragSelectOn);
   302 	DoSetXyPos(aPos);
   303 	TRAPD(ret,pixels=CheckCursorOnScreenL(aPos.iY));
   304 	if (ret)
   305 	    {
   306 	    OstTrace0( TRACE_FATAL, TCURSORPOSITION_SETXYPOSL, "EFShouldNotLeave" );
   307 	    }
   308 	__ASSERT_ALWAYS(!ret,FormPanic(EFShouldNotLeave));
   309 	UpdateLatentX(aPos.iX);
   310 	UpdateLatentY(aPos.iY);
   311 	if (!aDragSelectOn && aAllowPictureFrame)
   312 		{
   313 		TRect pict;
   314 		TInt pos = iLayout->XyPosToDocPosL(originalPoint);
   315 		if (iLayout->PictureRectangleL(pos, pict))
   316 			{
   317 			TTmDocPos docPos(pos + 1, EFalse);
   318 			SetPictureFrame(docPos, pos, pict);
   319 			}
   320 		}
   321 	return pixels;
   322 	}
   323 
   324 /**
   325 Returns a reference to the more suitable of the positions, taking
   326 the cursor positioning hint into account.
   327 @param aPreferred
   328 	The candidate returned if the positioning hint does not decide it.
   329 @param aBackup
   330 	The alternative candidate; only returned if the positioning hint
   331 	makes it more desirable than aPreferred.
   332 @return either aPreferred or aBackup.
   333 @internalComponent
   334 */
   335 TTmPosInfo2& TCursorPosition::ChoosePosition(TTmPosInfo2& aPreferred,
   336 	TTmPosInfo2& aBackup)
   337 	{
   338 	TTmPosInfo2 posInfo;
   339 	// The following part is to find out whether the aPreferred or aBackup is
   340 	// overlapped. For overlapped position, because it could visually exist at two
   341 	// different places/XY-coordinates, the iLayout->FindDocPos may return an aPos
   342 	// with a different iEdge against the original, so that we can know which doc position
   343 	// is overlapped.
   344 	iLayout->FindDocPos(aPreferred.iDocPos, posInfo, NULL);
   345 	TBool preferredOverlapped = (aPreferred.iEdge != posInfo.iEdge);
   346 	
   347 	iLayout->FindDocPos(aBackup.iDocPos, posInfo, NULL);
   348 	TBool backupOverlapped = ( aBackup.iEdge != posInfo.iEdge);
   349 	
   350 	if(preferredOverlapped && !backupOverlapped)	
   351 		return aBackup;
   352 	if(!preferredOverlapped && backupOverlapped)
   353 		return aPreferred;
   354 	
   355 	if (iPositioningHint == EInsertStrongL2R)
   356 		{
   357 		if (!aBackup.iRightToLeft && aPreferred.iRightToLeft)
   358 			return aBackup;
   359 		}
   360 	else if (iPositioningHint == EInsertStrongR2L)
   361 		{
   362 		if (aBackup.iRightToLeft && !aPreferred.iRightToLeft)
   363 			return aBackup;
   364 		}
   365 	return aPreferred;
   366 	}
   367 
   368 /*
   369 Move the cursor to the point on the screen nearest to the position specified
   370 and return the document position and screen position.
   371 */
   372 void TCursorPosition::DoSetXyPos(TPoint& aXyPos)
   373 	{
   374 	TTmPosInfo2 leftPosInfo;
   375 	TTmPosInfo2 rightPosInfo;
   376 	TTmLineInfo lineInfo;
   377 	CTextLayout::TTagmaForwarder forwarder(*iLayout);
   378 	if (forwarder.FindXyPosWithDisambiguation(aXyPos,
   379 		leftPosInfo, rightPosInfo, lineInfo))
   380 		{
   381 		TTmPosInfo2& chosen = ChoosePosition(leftPosInfo, rightPosInfo);
   382 		iDocPos = chosen.iDocPos;
   383 		aXyPos = chosen.iEdge;
   384 		CheckNullSelection();
   385 		}
   386 	}
   387 
   388 // Set up a picture frame.
   389 void TCursorPosition::SetPictureFrame(const TTmDocPos& aDocPos,TInt aAnchor,const TRect& aPictureRect)
   390 	{
   391 	iFlags |= (ESelected | EDrawNewPictureFrame);
   392 	iDocPos = aDocPos;
   393 	iAnchor = aAnchor;
   394 	iLatentX = (aPictureRect.iTl.iX + aPictureRect.iBr.iX) / 2;
   395 	}
   396 
   397 TInt TCursorPosition::MoveL(TBool aDragSelectOn, TMovementType& aMove,
   398 	TBool aAllowPictureFrame)
   399 	{
   400 	// Get the anchor point, either old or new.
   401 	TBool oldSelection = iFlags & ESelected;
   402 	TInt anchor = oldSelection? iAnchor : iDocPos.iPos;
   403 
   404 	iLayout->ExtendFormattingToCoverPosL(iDocPos.iPos);
   405 
   406 	TMovementType move = aMove;
   407 	TInt pixels = 0;
   408 	TBool pagingMove = EFalse;
   409 	TTmPosInfo2 suggestedCursorPos;
   410 	TInt picturePos = KErrNotFound;
   411 	TTmLineInfo line;
   412 	TRect pictureRect;
   413 
   414 	// Get a value for suggestedCursorPos.
   415 	// Also scroll if aMove is EFPageUp or EFPageDown.
   416 	switch (move)
   417 		{
   418 	case EFNoMovement:
   419 		iLayout->FindDocPos(iDocPos, suggestedCursorPos);
   420 		break;
   421 	case EFLeft:
   422 	case EFRight:
   423 		// MoveL is not called if a picture frame is moved away from,
   424 		// so we will not deal with that situation.
   425 		if (IsPictureFrame())
   426 			{
   427 			suggestedCursorPos.iDocPos.iPos = iDocPos.iPos;
   428 			suggestedCursorPos.iDocPos.iLeadingEdge = ETrue;
   429 			suggestedCursorPos.iEdge.iX = iLatentX;
   430 			suggestedCursorPos.iEdge.iY = iLatentY;
   431 			if (aDragSelectOn)
   432 				{
   433 				TTmDocPos anchorPos;
   434 				anchorPos.iPos = anchor;
   435 				anchorPos.iLeadingEdge = anchor < iDocPos.iPos? ETrue : EFalse;
   436 				suggestedCursorPos.iDocPos = VisualEndOfRunL(
   437 					iDocPos, anchorPos,
   438 					move == EFLeft ? EVisualLeft : EVisualRight);
   439 				anchor = iDocPos.iPos;
   440 				}
   441 			}
   442 		else if (LeftRightL(suggestedCursorPos, line, move)
   443 			&& aAllowPictureFrame && !aDragSelectOn)
   444 			{
   445 			// Have we just moved over a picture?
   446 			TPoint c = suggestedCursorPos.iEdge;
   447 			c.iX += aMove == EFLeft? 1 : -1;
   448 			picturePos = iLayout->PictureRectangleAndPosL(c, pictureRect);
   449 			}
   450 		break;
   451 	case EFLineUp:
   452 	case EFLineDown:
   453 		UpDownL(suggestedCursorPos, line, move);
   454 		if (aAllowPictureFrame && !aDragSelectOn && move == aMove)
   455 			{
   456 			TPoint c(iLatentX, line.iBaseline);
   457 			picturePos = iLayout->PictureRectangleAndPosL(c, pictureRect);
   458 			}
   459 		break;
   460 	case EFPageUp:
   461 	case EFPageDown:
   462 		pixels = PageScrollL(move);
   463 		pagingMove = ETrue;
   464 		break;
   465 	case EFLineBeg:
   466 	case EFLineEnd:
   467 		StartEnd(suggestedCursorPos, line, move);
   468 		break;
   469 		}
   470 
   471 	// Do the scrolling, if not already done.
   472 	if (!pagingMove)
   473 		pixels = iLayout->ScrollDocPosIntoViewL(suggestedCursorPos.iDocPos);
   474 
   475 	// Work out if the cursor has not moved.
   476 	if (iDocPos == suggestedCursorPos.iDocPos
   477 		&& !IsPictureFrame() && picturePos < 0)
   478 		move = EFNoMovement;
   479 
   480 	// Set old values
   481 	iOldDocPos = iDocPos.iPos;
   482 	iOldAnchor = oldSelection? iAnchor : iOldDocPos;
   483 	if (iFlags & EDrawNewPictureFrame)
   484 		iFlags |= EDrawOldPictureFrame;
   485 	else
   486 		iFlags &= ~EDrawOldPictureFrame;
   487 	
   488 	// Finally, set everything worked out.
   489 	if (!pagingMove)
   490 		iDocPos = suggestedCursorPos.iDocPos;
   491 
   492 	if (!aDragSelectOn || anchor == suggestedCursorPos.iDocPos.iPos)
   493 		{
   494 		iFlags &= ~ESelected;
   495 		iAnchor = suggestedCursorPos.iDocPos.iPos;
   496 		}
   497 	else
   498 		{
   499 		iFlags |= ESelected;
   500 		iAnchor = anchor;
   501 		}
   502 	switch (move)
   503 		{
   504 	case EFLeft:
   505 	case EFRight:
   506 	case EFLineBeg:
   507 	case EFLineEnd:
   508 		iLatentX = suggestedCursorPos.iEdge.iX;
   509 		if (0 <= picturePos)
   510 			iLatentX = (pictureRect.iTl.iX + pictureRect.iBr.iX) >> 1;
   511 		// fall through to:
   512 	case EFLineUp:
   513 	case EFLineDown:
   514 		iLatentY = suggestedCursorPos.iEdge.iY;
   515 	default:
   516 		break;
   517 		}
   518 	if (0 <=picturePos)
   519 		{
   520 		iFlags |= (ESelected | EDrawNewPictureFrame);
   521 		iDocPos.iPos = picturePos;
   522 		iDocPos.iLeadingEdge = ETrue;
   523 		iAnchor = picturePos + 1;
   524 		}
   525 	else
   526 		iFlags &= ~EDrawNewPictureFrame;
   527 	if (oldSelection ||
   528 		((iFlags & ESelected) && !(iFlags & EDrawNewPictureFrame)))
   529 		iFlags |= EDrawHighlight;
   530 	else
   531 		iFlags &= ~EDrawHighlight;
   532 	aMove = move;
   533 	return pixels;
   534 	}
   535 
   536 void TCursorPosition::UpdateLatentPosition()
   537 	{
   538 	TPoint pos;
   539 	CalculateCursorPos(pos);
   540 	UpdateLatentY(pos.iY);
   541 	UpdateLatentX(pos.iX);
   542 	}
   543 
   544 void TCursorPosition::TextMoveVertically()
   545 	//
   546 	//Reset the Vertical Latent position
   547 	//
   548 	{
   549 	TPoint scrPos;
   550 
   551 	CalculateCursorPos(scrPos);
   552 	UpdateLatentY(scrPos.iY);
   553 	}
   554 
   555 /** Find the position one position to the left or right of the current cursor.
   556 If the cursor is already at that extreme of the line, the cursor will move
   557 to the opposite of the previous (if moving backwards) or next (if moving
   558 forwards) line. The cursor is considered to be moving forwards if it is
   559 moving in the same direction as the paragraph directionality. This may, of
   560 course, be different to the local direction of the text.
   561 
   562 @param aToLeft ETrue if moving left, EFalse if moving right.
   563 @param aPos returns the position found.
   564 @param aLine returns details of the line containing aPos.
   565 @return ETrue if the cursor moved one position within the line. */
   566 TBool TCursorPosition::LeftRightL(TTmPosInfo2& aPos, TTmLineInfo& aLine, TMovementType& aMove)
   567 	{
   568 	TTmPosInfo2 posInfo;
   569 	if (!(aMove == EFLeft || aMove == EFRight))
   570 	    {
   571 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_LEFTRIGHTL, "EFIncorrectCursorMovement" );
   572 	    }
   573 	__ASSERT_DEBUG(aMove == EFLeft || aMove == EFRight,
   574 		FormPanic(EFIncorrectCursorMovement));
   575 	TBool found = EFalse;
   576 	TTmPosInfo2 otherPosInfo;
   577 	CTextLayout::TTagmaForwarder forwarder(*iLayout);
   578 	if (aMove == EFLeft)
   579 		{
   580 		found = forwarder.GetNextPosLeftWithDisambiguation(
   581 			iDocPos, otherPosInfo, posInfo);
   582 		}
   583 	else
   584 		{
   585 		found = forwarder.GetNextPosRightWithDisambiguation(
   586 			iDocPos, posInfo, otherPosInfo);
   587 		}
   588 	if (found)
   589 		{
   590 		iLayout->FindDocPos(ChoosePosition(posInfo, otherPosInfo).iDocPos,
   591 			aPos, &aLine);
   592 		return ETrue;
   593 		}
   594 
   595 	// We have reached the extreme of the line.
   596 	// But the beginning or the end?
   597 	TTmLineInfo currentLineInfo;
   598 	iLayout->FindDocPos(iDocPos, posInfo, &currentLineInfo);
   599 	TBool toLeft = aMove == EFLeft? ETrue : EFalse;
   600 	TBool movingBackwards = currentLineInfo.iFlags & TTmLineInfo::EParRightToLeft?
   601 		!toLeft : toLeft;
   602 	TInt lineToGoToY = movingBackwards?
   603 		currentLineInfo.iOuterRect.iTl.iY - 1
   604 		: currentLineInfo.iOuterRect.iBr.iY;
   605 
   606 	iLayout->ExtendFormattingToCoverYL(lineToGoToY);
   607 	const CTmTextLayout& tm = iLayout->TagmaTextLayout();
   608 	TTmDocPos newPos;
   609 	TPoint c(0, lineToGoToY);
   610 	if (iLayout->FindXyPos(c, posInfo, &aLine))
   611 		{
   612 		// moving to next/previous line
   613 		TBool toRightEnd = aLine.iFlags & TTmLineInfo::EParRightToLeft?
   614 			!movingBackwards : movingBackwards;
   615 		tm.LineExtreme(posInfo.iDocPos, toRightEnd, newPos);
   616 		}
   617 	else
   618 		{
   619 		// We appear to have reached the end of the document.
   620 		if (movingBackwards || currentLineInfo.iStart == currentLineInfo.iEnd)
   621 			// before start of line
   622 			newPos = TTmDocPos(currentLineInfo.iStart, EFalse);
   623 		else
   624 			// after end of line (last character is paragraph delimiter)
   625 			newPos = TTmDocPos(currentLineInfo.iEnd - 1, ETrue);
   626 		}
   627 	tm.FindDocPos(newPos, aPos, aLine);
   628 	// Cursor either changed line, or did not move.
   629 	return EFalse;
   630 	}
   631 
   632 /** Find the visual start or end of the line containing the cursor.
   633 @param aToStart ETrue if finding the visual start of the line, EFalse if finding the end.
   634 @param aPos Returns the position found.
   635 @param aLine Returns details of the line containing aPos.*/
   636 void TCursorPosition::StartEnd(TTmPosInfo2& aPos, TTmLineInfo& aLine, TMovementType& aMove)
   637 	{
   638 	if (aMove != EFLineBeg && aMove != EFLineEnd)
   639 	    {
   640 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_STARTEND, "EFIncorrectCursorMovement" );
   641 	    }
   642 	__ASSERT_DEBUG(aMove == EFLineBeg || aMove == EFLineEnd,
   643 		FormPanic(EFIncorrectCursorMovement));
   644 	iLayout->FindDocPos(iDocPos, aPos, &aLine);
   645 	TBool toBeginning = aMove == EFLineBeg? ETrue : EFalse;
   646 	TBool toRight = aLine.iFlags & TTmLineInfo::EParRightToLeft?
   647 		toBeginning : !toBeginning;
   648 	TTmDocPos newPos;
   649 	iLayout->TagmaTextLayout().LineExtreme(iDocPos, toRight, newPos);
   650 	iLayout->FindDocPos(newPos, aPos, &aLine);
   651 	}
   652 
   653 /** Find a position in the previous or next line close to the current cursor
   654 position.
   655 
   656 @param aUp ETrue if moving up, EFalse if moving down.
   657 @param aPos returns the position found.
   658 @param aLine returns details of the line containing aPos. */
   659 void TCursorPosition::UpDownL(TTmPosInfo2& aPos, TTmLineInfo& aLine, TMovementType& aMove)
   660 	{
   661 	if (aMove != EFLineUp && aMove != EFLineDown)
   662 	    {
   663 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_UPDOWNL, "EFIncorrectCursorMovement" );
   664 	    }
   665 	__ASSERT_DEBUG(aMove == EFLineUp || aMove == EFLineDown,
   666 		FormPanic(EFIncorrectCursorMovement));
   667 	iLayout->FindDocPos(iDocPos, aPos, &aLine);
   668 	TPoint c(iLatentX, aMove == EFLineUp?
   669 		aLine.iOuterRect.iTl.iY - 1
   670 		: aLine.iOuterRect.iBr.iY);
   671 	
   672 	// Ensure formatting extends to the new cursor position above or
   673 	// below the current line. Solves the problem where scrolling down
   674 	// at the bottom of a view to the next paragraph needed two
   675 	// down cursor key presses.
   676 	iLayout->ExtendFormattingToCoverYL(c.iY);
   677 
   678 	TTmPosInfo2 otherPosInfo;
   679 	CTextLayout::TTagmaForwarder forwarder(*iLayout);
   680 	if (!forwarder.FindXyPosWithDisambiguation(c,
   681 		otherPosInfo, aPos, aLine))
   682 		{
   683 		TBool toStart;
   684 		if (aMove == EFLineUp)
   685 			{
   686 			toStart = ETrue;
   687 			aMove = EFLineBeg;
   688 			}
   689 		else
   690 			{
   691 			toStart = EFalse;
   692 			aMove = EFLineEnd;
   693 			}
   694 		TBool toRight = aLine.iFlags & TTmLineInfo::EParRightToLeft?
   695 			toStart : !toStart;
   696 		TTmDocPos newPos;
   697 		iLayout->TagmaTextLayout().LineExtreme(aPos.iDocPos, toRight, newPos);
   698 		iLayout->FindDocPos(newPos, aPos, &aLine);
   699 		
   700 		// as FindXyPosWithDisambiguation returned EFalse, there is no 
   701 		// "otherPosInfo" so no need to ChoosePosition() just return
   702 		return;
   703 		}
   704 	aPos = ChoosePosition(aPos, otherPosInfo);
   705 	}
   706 
   707 // Move the display one page and put the cursor back in the same place (as far as possible).
   708 TInt TCursorPosition::PageScrollL(TMovementType& aMove)
   709 	{
   710 	if (aMove!=EFPageUp && aMove!=EFPageDown)
   711 	    {
   712 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_PAGESCROLLL, "EFIncorrectCursorMovement" );
   713 	    }
   714 	__ASSERT_DEBUG(aMove==EFPageUp || aMove==EFPageDown,FormPanic(EFIncorrectCursorMovement));
   715 	TPoint scrPos;
   716 	TInt pixelsScrolled;
   717 	TTmDocPos docPos=iDocPos;
   718 
   719 	if (!iLayout->PosInBand(iDocPos,scrPos))
   720 		{
   721 		if (aMove==EFPageUp)
   722 			iLatentY=0;
   723 		else
   724 			iLatentY=(iLayout->BandHeight()-1);
   725 		}
   726 	if (aMove==EFPageUp)
   727 		iLayout->PageUpL(iLatentY,pixelsScrolled);
   728 	else
   729 		iLayout->PageDownL(iLatentY,pixelsScrolled);
   730 	scrPos.SetXY(iLatentX,iLatentY);
   731 	DoSetXyPos(scrPos);
   732 	if (docPos.iPos == iDocPos.iPos && pixelsScrolled == 0) // Cursor in first or last line
   733 		{
   734 		TPoint pos;
   735 		CalculateCursorPos(pos);
   736 		TInt y = pos.iY;
   737 		if (aMove == EFPageUp)
   738 			DoSetDocPosL(TTmDocPos(0, ETrue));
   739 		else
   740 			DoSetDocPosL(TTmDocPos(iLayout->DocumentLength(), EFalse));
   741 		CalculateCursorPos(pos);
   742 		// If the line didn't change change the movement type to reflect this.
   743 		if (pos.iY == y)
   744 			aMove = aMove == EFPageUp? EFLineBeg : EFLineEnd;
   745 		}
   746 
   747 	return pixelsScrolled;
   748 	}
   749 
   750 /*
   751 Find the position of the line on the screen
   752 Scroll it completely on if it is partly off.
   753 */
   754 TInt TCursorPosition::CheckCursorOnScreenL(TInt& aY)
   755 	{
   756 	TRect cursorLine;
   757 	const TInt botRow=iLayout->BandHeight();
   758 	TInt linesToScroll=0;
   759 	TInt pixels=0;
   760 
   761 	iLayout->GetLineRect(aY,cursorLine);
   762 	if (cursorLine.iTl.iY>aY || cursorLine.iBr.iY<aY)
   763 	    {
   764 	    OstTrace0( TRACE_DUMP, TCURSORPOSITION_CHECKCURSORONSCREENL, "EFPixelNotInFormattedLine" );
   765 	    }
   766 	__ASSERT_DEBUG(cursorLine.iTl.iY<=aY && cursorLine.iBr.iY>=aY,FormPanic(EFPixelNotInFormattedLine));
   767 	if (cursorLine.iTl.iY<0 && cursorLine.iBr.iY<botRow)
   768 		linesToScroll=1;
   769 	else if (cursorLine.iBr.iY>botRow && cursorLine.iTl.iY>0)
   770 		linesToScroll=-1;
   771 	if (linesToScroll!=0)
   772 		{
   773 		pixels=iLayout->ScrollLinesL(linesToScroll);
   774 
   775 		aY+=pixels;
   776 		}
   777 	if (aY<0 && aY>=botRow)
   778 	    {
   779 	    OstTrace0( TRACE_DUMP, DUP1_TCURSORPOSITION_CHECKCURSORONSCREENL, "EFCursorOffDisplay" );
   780 	    }
   781 	__ASSERT_DEBUG(aY>=0 || aY<botRow,FormPanic(EFCursorOffDisplay));
   782 	if (!(cursorLine.Height()>=botRow || cursorLine.iBr.iY>=botRow 
   783 	        || (cursorLine.iTl.iY+pixels>=0 && cursorLine.iBr.iY+pixels<=botRow)) )
   784 	    {
   785 	    OstTrace0( TRACE_DUMP, DUP2_TCURSORPOSITION_CHECKCURSORONSCREENL, "EFCursorOffDisplay" );
   786 	    }
   787 	__ASSERT_DEBUG(cursorLine.Height()>=botRow || cursorLine.iBr.iY>=botRow 
   788 		|| (cursorLine.iTl.iY+pixels>=0 && cursorLine.iBr.iY+pixels<=botRow),FormPanic(EFCursorOffDisplay));
   789 	return pixels;
   790 	}
   791 
   792 TBool TCursorPosition::GetCursor(TTmCursorPlacement aPlacement,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const
   793 	{
   794 	TRect line_rect;
   795 	TBool result = iLayout->GetCursor(iDocPos,aPlacement,line_rect,aOrigin,aWidth,aAscent,aDescent);
   796 	return result;
   797 	}