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