|
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, ¤tLineInfo); |
|
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 } |