LibreOffice Module sw (master) 1
frmcrsr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <ndtxt.hxx>
21#include <pam.hxx>
22#include <frmatr.hxx>
23#include <frmtool.hxx>
24#include <viewopt.hxx>
25#include <paratr.hxx>
26#include <rootfrm.hxx>
27#include <pagefrm.hxx>
28#include <colfrm.hxx>
29#include <swtypes.hxx>
30#include <editeng/lrspitem.hxx>
31#include <editeng/tstpitem.hxx>
32#include <editeng/ulspitem.hxx>
33#include <editeng/lspcitem.hxx>
34#include "pormulti.hxx"
35#include <doc.hxx>
37#include <sortedobjs.hxx>
38
39#include <unicode/ubidi.h>
40
41#include <txtfrm.hxx>
42#include "inftxt.hxx"
43#include "itrtxt.hxx"
44#include <crstate.hxx>
45#include <viewsh.hxx>
46#include <swfntcch.hxx>
47#include <flyfrm.hxx>
48
49#define MIN_OFFSET_STEP 10
50
51using namespace ::com::sun::star;
52
53/*
54 * - SurvivalKit: For how long do we get past the last char of the line.
55 * - RightMargin abstains from adjusting position with -1
56 * - GetCharRect returns a GetEndCharRect for CursorMoveState::RightMargin
57 * - GetEndCharRect sets bRightMargin to true
58 * - SwTextCursor::bRightMargin is set to false by CharCursorToLine
59 */
60
61namespace
62{
63
64SwTextFrame *GetAdjFrameAtPos( SwTextFrame *pFrame, const SwPosition &rPos,
65 const bool bRightMargin, const bool bNoScroll = true )
66{
67 // RightMargin in the last master line
68 TextFrameIndex const nOffset = pFrame->MapModelToViewPos(rPos);
69 SwTextFrame *pFrameAtPos = pFrame;
70 if( !bNoScroll || pFrame->GetFollow() )
71 {
72 pFrameAtPos = pFrame->GetFrameAtPos( rPos );
73 if (nOffset < pFrameAtPos->GetOffset() &&
74 !pFrameAtPos->IsFollow() )
75 {
76 assert(pFrameAtPos->MapModelToViewPos(rPos) == nOffset);
77 TextFrameIndex nNew(nOffset);
79 nNew = TextFrameIndex(0);
80 else
82 sw_ChangeOffset( pFrameAtPos, nNew );
83 }
84 }
85 while( pFrame != pFrameAtPos )
86 {
87 pFrame = pFrameAtPos;
88 pFrame->GetFormatted();
89 pFrameAtPos = pFrame->GetFrameAtPos( rPos );
90 }
91
92 if( nOffset && bRightMargin )
93 {
94 while (pFrameAtPos &&
95 pFrameAtPos->MapViewToModelPos(pFrameAtPos->GetOffset()) == rPos &&
96 pFrameAtPos->IsFollow() )
97 {
98 pFrameAtPos->GetFormatted();
99 pFrameAtPos = pFrameAtPos->FindMaster();
100 }
101 OSL_ENSURE( pFrameAtPos, "+GetCharRect: no frame with my rightmargin" );
102 }
103 return pFrameAtPos ? pFrameAtPos : pFrame;
104}
105
106}
107
109{
110 // Do not scroll in areas and outside of flies
111 OSL_ENSURE( !pFrame->IsFollow(), "Illegal Scrolling by Follow!" );
112 if( pFrame->GetOffset() != nNew && !pFrame->IsInSct() )
113 {
114 SwFlyFrame *pFly = pFrame->FindFlyFrame();
115 // Attention: if e.g. in a column frame the size is still invalid
116 // we must not scroll around just like that
117 if ( ( pFly && pFly->isFrameAreaDefinitionValid() &&
118 !pFly->GetNextLink() && !pFly->GetPrevLink() ) ||
119 ( !pFly && pFrame->IsInTab() ) )
120 {
121 SwViewShell* pVsh = pFrame->getRootFrame()->GetCurrShell();
122 if( pVsh )
123 {
124 if( pVsh->GetRingContainer().size() > 1 ||
125 ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() ) )
126 {
127 if( !pFrame->GetOffset() )
128 return false;
129 nNew = TextFrameIndex(0);
130 }
131 pFrame->SetOffset( nNew );
132 pFrame->SetPara( nullptr );
133 pFrame->GetFormatted();
134 if( pFrame->getFrameArea().HasArea() )
135 pFrame->getRootFrame()->GetCurrShell()->InvalidateWindows( pFrame->getFrameArea() );
136 return true;
137 }
138 }
139 }
140 return false;
141}
142
144{
145 SwTextFrame* pRet = this;
146 while( pRet->HasFollow() && nWhere >= pRet->GetFollow()->GetOffset() )
147 pRet = pRet->GetFollow();
148 return *pRet;
149}
150
152{
154 SwTextFrame *pFoll = this;
155 while( pFoll->GetFollow() )
156 {
157 if (nPos > pFoll->GetFollow()->GetOffset())
158 pFoll = pFoll->GetFollow();
159 else
160 {
161 if (nPos == pFoll->GetFollow()->GetOffset()
163 pFoll = pFoll->GetFollow();
164 else
165 break;
166 }
167 }
168 return pFoll;
169}
170
171/*
172 * GetCharRect() returns the char's char line described by aPos.
173 * GetModelPositionForViewPoint() does the reverse: It goes from a document coordinate to
174 * a Pam.
175 * Both are virtual in the frame base class and thus are redefined here.
176 */
177
179 SwCursorMoveState *pCMS, bool bAllowFarAway ) const
180{
181 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTextFrame::GetCharRect with swapped frame" );
182
183 if( IsLocked() || IsHiddenNow() )
184 return false;
185
186 // Find the right frame first. We need to keep in mind that:
187 // - the cached information could be invalid (GetPara() == 0)
188 // - we could have a Follow
189 // - the Follow chain grows dynamically; the one we end up in
190 // needs to be formatted
191
192 // Optimisation: reading ahead saves us a GetAdjFrameAtPos
193 const bool bRightMargin = pCMS && ( CursorMoveState::RightMargin == pCMS->m_eState );
194 const bool bNoScroll = pCMS && pCMS->m_bNoScroll;
195 SwTextFrame *pFrame = GetAdjFrameAtPos( const_cast<SwTextFrame*>(this), rPos, bRightMargin,
196 bNoScroll );
197 pFrame->GetFormatted();
198
199 const SwFrame* pTmpFrame = pFrame->GetUpper();
200 if (pTmpFrame->getFrameArea().Top() == FAR_AWAY && !bAllowFarAway)
201 return false;
202
203 SwRectFnSet aRectFnSet(pFrame);
204 const SwTwips nUpperMaxY = aRectFnSet.GetPrtBottom(*pTmpFrame);
205 const SwTwips nFrameMaxY = aRectFnSet.GetPrtBottom(*pFrame);
206
207 // nMaxY is an absolute value
208 SwTwips nMaxY = aRectFnSet.IsVert() ?
209 ( aRectFnSet.IsVertL2R() ? std::min( nFrameMaxY, nUpperMaxY ) : std::max( nFrameMaxY, nUpperMaxY ) ) :
210 std::min( nFrameMaxY, nUpperMaxY );
211
212 bool bRet = false;
213
214 if ( pFrame->IsEmpty() || ! aRectFnSet.GetHeight(pFrame->getFramePrintArea()) )
215 {
216 Point aPnt1 = pFrame->getFrameArea().Pos() + pFrame->getFramePrintArea().Pos();
217 SwTextNode const*const pTextNd(GetTextNodeForParaProps());
218 short nFirstOffset;
219 pTextNd->GetFirstLineOfsWithNum( nFirstOffset );
220
221 Point aPnt2;
222 if ( aRectFnSet.IsVert() )
223 {
224 if( nFirstOffset > 0 )
225 aPnt1.AdjustY(nFirstOffset );
226 if ( aPnt1.X() < nMaxY && !aRectFnSet.IsVertL2R() )
227 aPnt1.setX( nMaxY );
228 aPnt2.setX( aPnt1.X() + pFrame->getFramePrintArea().Width() );
229 aPnt2.setY( aPnt1.Y() );
230 if( aPnt2.X() < nMaxY )
231 aPnt2.setX( nMaxY );
232 }
233 else
234 {
235 if( nFirstOffset > 0 )
236 aPnt1.AdjustX(nFirstOffset );
237
238 if( aPnt1.Y() > nMaxY )
239 aPnt1.setY( nMaxY );
240 aPnt2.setX( aPnt1.X() );
241 aPnt2.setY( aPnt1.Y() + pFrame->getFramePrintArea().Height() );
242 if( aPnt2.Y() > nMaxY )
243 aPnt2.setY( nMaxY );
244 }
245
246 rOrig = SwRect( aPnt1, aPnt2 );
247
248 if ( pCMS )
249 {
250 pCMS->m_aRealHeight.setX( 0 );
251 pCMS->m_aRealHeight.setY( aRectFnSet.IsVert() ? -rOrig.Width() : rOrig.Height() );
252 }
253
254 if ( pFrame->IsRightToLeft() )
255 pFrame->SwitchLTRtoRTL( rOrig );
256
257 bRet = true;
258 }
259 else
260 {
261 if( !pFrame->HasPara() )
262 return false;
263
264 SwFrameSwapper aSwapper( pFrame, true );
265 if ( aRectFnSet.IsVert() )
266 nMaxY = pFrame->SwitchVerticalToHorizontal( nMaxY );
267
268 bool bGoOn = true;
269 TextFrameIndex const nOffset = MapModelToViewPos(rPos);
270 assert(nOffset != TextFrameIndex(COMPLETE_STRING)); // not going to end well
271 TextFrameIndex nNextOfst;
272
273 do
274 {
275 {
276 SwTextSizeInfo aInf( pFrame );
277 SwTextCursor aLine( pFrame, &aInf );
278 nNextOfst = aLine.GetEnd();
279 // See comment in AdjustFrame
280 // Include the line's last char?
281 if (bRightMargin)
282 aLine.GetEndCharRect( &rOrig, nOffset, pCMS, nMaxY );
283 else
284 aLine.GetCharRect( &rOrig, nOffset, pCMS, nMaxY );
285 bRet = true;
286 }
287
288 if ( pFrame->IsRightToLeft() )
289 pFrame->SwitchLTRtoRTL( rOrig );
290
291 if ( aRectFnSet.IsVert() )
292 pFrame->SwitchHorizontalToVertical( rOrig );
293
294 if( pFrame->IsUndersized() && pCMS && !pFrame->GetNext() &&
295 aRectFnSet.GetBottom(rOrig) == nUpperMaxY &&
296 pFrame->GetOffset() < nOffset &&
297 !pFrame->IsFollow() && !bNoScroll &&
298 TextFrameIndex(pFrame->GetText().getLength()) != nNextOfst)
299 {
300 bGoOn = sw_ChangeOffset( pFrame, nNextOfst );
301 }
302 else
303 bGoOn = false;
304 } while ( bGoOn );
305
306 if ( pCMS )
307 {
308 if ( pFrame->IsRightToLeft() )
309 {
310 if( pCMS->m_b2Lines && pCMS->m_p2Lines)
311 {
312 pFrame->SwitchLTRtoRTL( pCMS->m_p2Lines->aLine );
313 pFrame->SwitchLTRtoRTL( pCMS->m_p2Lines->aPortion );
314 }
315 }
316
317 if ( aRectFnSet.IsVert() )
318 {
319 if ( pCMS->m_bRealHeight )
320 {
321 pCMS->m_aRealHeight.setY( -pCMS->m_aRealHeight.Y() );
322 if ( pCMS->m_aRealHeight.Y() < 0 )
323 {
324 // writing direction is from top to bottom
325 pCMS->m_aRealHeight.setX( rOrig.Width() -
326 pCMS->m_aRealHeight.X() +
327 pCMS->m_aRealHeight.Y() );
328 }
329 }
330 if( pCMS->m_b2Lines && pCMS->m_p2Lines)
331 {
332 pFrame->SwitchHorizontalToVertical( pCMS->m_p2Lines->aLine );
333 pFrame->SwitchHorizontalToVertical( pCMS->m_p2Lines->aPortion );
334 }
335 }
336
337 }
338 }
339 if( bRet )
340 {
341 SwPageFrame *pPage = pFrame->FindPageFrame();
342 OSL_ENSURE( pPage, "Text escaped from page?" );
343 const SwTwips nOrigTop = aRectFnSet.GetTop(rOrig);
344 const SwTwips nPageTop = aRectFnSet.GetTop(pPage->getFrameArea());
345 const SwTwips nPageBott = aRectFnSet.GetBottom(pPage->getFrameArea());
346
347 // We have the following situation: if the frame is in an invalid
348 // sectionframe, it's possible that the frame is outside the page.
349 // If we restrict the cursor position to the page area, we enforce
350 // the formatting of the page, of the section frame and the frame itself.
351 if( aRectFnSet.YDiff( nPageTop, nOrigTop ) > 0 )
352 aRectFnSet.SetTop( rOrig, nPageTop );
353
354 if ( aRectFnSet.YDiff( nOrigTop, nPageBott ) > 0 )
355 aRectFnSet.SetTop( rOrig, nPageBott );
356 }
357
358 return bRet;
359}
360
361/*
362 * GetAutoPos() looks up the char's char line which is described by rPos
363 * and is used by the auto-positioned frame.
364 */
365
366bool SwTextFrame::GetAutoPos( SwRect& rOrig, const SwPosition &rPos ) const
367{
368 if( IsHiddenNow() )
369 return false;
370
371 TextFrameIndex const nOffset = MapModelToViewPos(rPos);
372 SwTextFrame* pFrame = &(const_cast<SwTextFrame*>(this)->GetFrameAtOfst( nOffset ));
373
374 pFrame->GetFormatted();
375 const SwFrame* pTmpFrame = pFrame->GetUpper();
376
377 SwRectFnSet aRectFnSet(pTmpFrame);
378 SwTwips nUpperMaxY = aRectFnSet.GetPrtBottom(*pTmpFrame);
379
380 // nMaxY is in absolute value
381 SwTwips nMaxY;
382 if ( aRectFnSet.IsVert() )
383 {
384 if ( aRectFnSet.IsVertL2R() )
385 nMaxY = std::min( SwTwips(aRectFnSet.GetPrtBottom(*pFrame)), nUpperMaxY );
386 else
387 nMaxY = std::max( SwTwips(aRectFnSet.GetPrtBottom(*pFrame)), nUpperMaxY );
388 }
389 else
390 nMaxY = std::min( SwTwips(aRectFnSet.GetPrtBottom(*pFrame)), nUpperMaxY );
391 if ( pFrame->IsEmpty() || ! aRectFnSet.GetHeight(pFrame->getFramePrintArea()) )
392 {
393 Point aPnt1 = pFrame->getFrameArea().Pos() + pFrame->getFramePrintArea().Pos();
394 Point aPnt2;
395 if ( aRectFnSet.IsVert() )
396 {
397 if ( aPnt1.X() < nMaxY && !aRectFnSet.IsVertL2R() )
398 aPnt1.setX( nMaxY );
399
400 aPnt2.setX( aPnt1.X() + pFrame->getFramePrintArea().Width() );
401 aPnt2.setY( aPnt1.Y() );
402 if( aPnt2.X() < nMaxY )
403 aPnt2.setX( nMaxY );
404 }
405 else
406 {
407 if( aPnt1.Y() > nMaxY )
408 aPnt1.setY( nMaxY );
409 aPnt2.setX( aPnt1.X() );
410 aPnt2.setY( aPnt1.Y() + pFrame->getFramePrintArea().Height() );
411 if( aPnt2.Y() > nMaxY )
412 aPnt2.setY( nMaxY );
413 }
414 rOrig = SwRect( aPnt1, aPnt2 );
415 return true;
416 }
417 else
418 {
419 if( !pFrame->HasPara() )
420 return false;
421
422 SwFrameSwapper aSwapper( pFrame, true );
423 if ( aRectFnSet.IsVert() )
424 nMaxY = pFrame->SwitchVerticalToHorizontal( nMaxY );
425
426 SwTextSizeInfo aInf( pFrame );
427 SwTextCursor aLine( pFrame, &aInf );
429 aTmpState.m_bRealHeight = true;
430 aLine.GetCharRect( &rOrig, nOffset, &aTmpState, nMaxY );
431 if( aTmpState.m_aRealHeight.X() >= 0 )
432 {
433 rOrig.Pos().AdjustY(aTmpState.m_aRealHeight.X() );
434 rOrig.Height( aTmpState.m_aRealHeight.Y() );
435 }
436
437 if ( pFrame->IsRightToLeft() )
438 pFrame->SwitchLTRtoRTL( rOrig );
439
440 if ( aRectFnSet.IsVert() )
441 pFrame->SwitchHorizontalToVertical( rOrig );
442
443 return true;
444 }
445}
446
454 const SwPosition& _rPos ) const
455{
456 bool bRet = true;
457
458 // get position offset
459 TextFrameIndex const nOffset = MapModelToViewPos(_rPos);
460
461 if (TextFrameIndex(GetText().getLength()) < nOffset)
462 {
463 bRet = false;
464 }
465 else
466 {
467 SwRectFnSet aRectFnSet(this);
468 if ( IsEmpty() || !aRectFnSet.GetHeight(getFramePrintArea()) )
469 {
470 // consider upper space amount considered
471 // for previous frame and the page grid.
472 _onTopOfLine = aRectFnSet.GetPrtTop(*this);
473 }
474 else
475 {
476 // determine formatted text frame that contains the requested position
477 SwTextFrame* pFrame = &(const_cast<SwTextFrame*>(this)->GetFrameAtOfst( nOffset ));
478 pFrame->GetFormatted();
479 aRectFnSet.Refresh(pFrame);
480 // If proportional line spacing is applied
481 // to the text frame, the top of the anchor character is also the
482 // top of the line.
483 // Otherwise the line layout determines the top of the line
484 const SvxLineSpacingItem& rSpace = GetAttrSet()->GetLineSpacing();
485 if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop )
486 {
487 SwRect aCharRect;
488 if ( GetAutoPos( aCharRect, _rPos ) )
489 {
490 _onTopOfLine = aRectFnSet.GetTop(aCharRect);
491 }
492 else
493 {
494 bRet = false;
495 }
496 }
497 else
498 {
499 // assure that text frame is in a horizontal layout
500 SwFrameSwapper aSwapper( pFrame, true );
501 // determine text line that contains the requested position
502 SwTextSizeInfo aInf( pFrame );
503 SwTextCursor aLine( pFrame, &aInf );
504 aLine.CharCursorToLine( nOffset );
505 // determine top of line
506 _onTopOfLine = aLine.Y();
507 if ( aRectFnSet.IsVert() )
508 {
509 _onTopOfLine = pFrame->SwitchHorizontalToVertical( _onTopOfLine );
510 }
511 }
512 }
513 }
514
515 return bRet;
516}
517
518// Minimum distance of non-empty lines is a little less than 2 cm
519#define FILL_MIN_DIST 1100
520
522{
526 const Point& rPoint;
528 bool bFirstLine : 1;
529 bool bInner : 1;
530 bool bColumn : 1;
531 bool bEmpty : 1;
532 SwFillData( const SwCursorMoveState *pC, SwPosition* pP, const SwRect& rR,
533 const Point& rPt ) : aFrame( rR ), pCMS( pC ), pPos( pP ), rPoint( rPt ),
534 nLineWidth( 0 ), bFirstLine( true ), bInner( false ), bColumn( false ),
535 bEmpty( true ){}
536 SwFillMode Mode() const { return pCMS->m_pFill->eMode; }
537 tools::Long X() const { return rPoint.X(); }
538 tools::Long Y() const { return rPoint.Y(); }
539 tools::Long Left() const { return aFrame.Left(); }
540 tools::Long Right() const { return aFrame.Right(); }
541 tools::Long Bottom() const { return aFrame.Bottom(); }
542 SwFillCursorPos &Fill() const { return *pCMS->m_pFill; }
543 void SetTab( sal_uInt16 nNew ) { pCMS->m_pFill->nTabCnt = nNew; }
544 void SetSpace( sal_uInt16 nNew ) { pCMS->m_pFill->nSpaceCnt = nNew; }
545 void SetSpaceOnly( sal_uInt16 nNew ) { pCMS->m_pFill->nSpaceOnlyCnt = nNew; }
546 void SetOrient( const sal_Int16 eNew ){ pCMS->m_pFill->eOrient = eNew; }
547};
548
550 const bool bChgFrame, SwCursorMoveState* pCMS ) const
551{
552 // GetModelPositionForViewPoint_ is called by GetModelPositionForViewPoint and GetKeyCursorOfst.
553 // Never just a return false.
554
555 if( IsLocked() || IsHiddenNow() )
556 return false;
557
558 const_cast<SwTextFrame*>(this)->GetFormatted();
559
560 Point aOldPoint( rPoint );
561
562 if ( IsVertical() )
563 {
564 SwitchVerticalToHorizontal( const_cast<Point&>(rPoint) );
565 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
566 }
567
568 if ( IsRightToLeft() )
569 SwitchRTLtoLTR( const_cast<Point&>(rPoint) );
570
571 std::unique_ptr<SwFillData> pFillData;
572 if ( pCMS && pCMS->m_pFill )
573 pFillData.reset(new SwFillData( pCMS, pPos, getFrameArea(), rPoint ));
574
575 if ( IsEmpty() )
576 {
578 if( pCMS && pCMS->m_bFieldInfo )
579 {
580 SwTwips nDiff = rPoint.X() - getFrameArea().Left() - getFramePrintArea().Left();
581 if( nDiff > 50 || nDiff < 0 )
582 pCMS->m_bPosCorr = true;
583 }
584 }
585 else
586 {
587 SwTextSizeInfo aInf( const_cast<SwTextFrame*>(this) );
588 SwTextCursor aLine( const_cast<SwTextFrame*>(this), &aInf );
589
590 // See comment in AdjustFrame()
592 aLine.TwipsToLine( rPoint.Y() );
593 while( aLine.Y() + aLine.GetLineHeight() > nMaxY )
594 {
595 if( !aLine.Prev() )
596 break;
597 }
598
599 if( aLine.GetDropLines() >= aLine.GetLineNr() && 1 != aLine.GetLineNr()
600 && rPoint.X() < aLine.FirstLeft() + aLine.GetDropLeft() )
601 while( aLine.GetLineNr() > 1 )
602 aLine.Prev();
603
604 TextFrameIndex nOffset = aLine.GetModelPositionForViewPoint(pPos, rPoint, bChgFrame, pCMS);
605
606 if( pCMS && pCMS->m_eState == CursorMoveState::NONE && aLine.GetEnd() == nOffset )
608
609 // pPos is a pure IN parameter and must not be evaluated.
610 // pIter->GetModelPositionForViewPoint returns from a nesting with COMPLETE_STRING.
611 // If SwTextIter::GetModelPositionForViewPoint calls GetModelPositionForViewPoint further by itself
612 // nNode changes the position.
613 // In such cases, pPos must not be calculated.
614 if (TextFrameIndex(COMPLETE_STRING) != nOffset)
615 {
616 *pPos = MapViewToModelPos(nOffset);
617 if( pFillData )
618 {
619 if (TextFrameIndex(GetText().getLength()) > nOffset ||
620 rPoint.Y() < getFrameArea().Top() )
621 pFillData->bInner = true;
622 pFillData->bFirstLine = aLine.GetLineNr() < 2;
623 if (GetText().getLength())
624 {
625 pFillData->bEmpty = false;
626 pFillData->nLineWidth = aLine.GetCurr()->Width();
627 }
628 }
629 }
630 }
631 bool bChgFillData = false;
632 if( pFillData && FindPageFrame()->getFrameArea().Contains( aOldPoint ) )
633 {
634 FillCursorPos( *pFillData );
635 bChgFillData = true;
636 }
637
638 if ( IsVertical() )
639 {
640 if ( bChgFillData )
641 SwitchHorizontalToVertical( pFillData->Fill().aCursor.Pos() );
642 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
643 }
644
645 if ( IsRightToLeft() && bChgFillData )
646 {
647 SwitchLTRtoRTL( pFillData->Fill().aCursor.Pos() );
648 const sal_Int16 eOrient = pFillData->pCMS->m_pFill->eOrient;
649
650 if ( text::HoriOrientation::LEFT == eOrient )
651 pFillData->SetOrient( text::HoriOrientation::RIGHT );
652 else if ( text::HoriOrientation::RIGHT == eOrient )
653 pFillData->SetOrient( text::HoriOrientation::LEFT );
654 }
655
656 const_cast<Point&>(rPoint) = aOldPoint;
657
658 return true;
659}
660
662 SwCursorMoveState* pCMS, bool ) const
663{
664 const bool bChgFrame = !(pCMS && CursorMoveState::UpDown == pCMS->m_eState);
665 return GetModelPositionForViewPoint_( pPos, rPoint, bChgFrame, pCMS );
666}
667
668/*
669 * Layout-oriented cursor movement to the line start.
670 */
671
673{
674 assert(GetMergedPara() || &pPam->GetPointNode() == static_cast<SwContentNode const*>(GetDep()));
675
676 SwTextFrame *pFrame = GetAdjFrameAtPos( const_cast<SwTextFrame*>(this), *pPam->GetPoint(),
678 pFrame->GetFormatted();
679 TextFrameIndex nIndx;
680 if ( pFrame->IsEmpty() )
681 nIndx = TextFrameIndex(0);
682 else
683 {
684 SwTextSizeInfo aInf( pFrame );
685 SwTextCursor aLine( pFrame, &aInf );
686
687 aLine.CharCursorToLine(pFrame->MapModelToViewPos(*pPam->GetPoint()));
688 nIndx = aLine.GetStart();
689 if( pFrame->GetOffset() && !pFrame->IsFollow() && !aLine.GetPrev() )
690 {
692 nIndx = TextFrameIndex(0);
693 }
694 }
695 *pPam->GetPoint() = pFrame->MapViewToModelPos(nIndx);
697 return true;
698}
699
700/*
701 * To the line end: That's the position before the last char of the line.
702 * Exception: In the last line, it should be able to place the cursor after
703 * the last char in order to append text.
704 */
705
706bool SwTextFrame::RightMargin(SwPaM *pPam, bool bAPI) const
707{
708 assert(GetMergedPara() || &pPam->GetPointNode() == static_cast<SwContentNode const*>(GetDep()));
709
710 SwTextFrame *pFrame = GetAdjFrameAtPos( const_cast<SwTextFrame*>(this), *pPam->GetPoint(),
712 pFrame->GetFormatted();
714 if (!IsEmpty())
715 {
716 SwTextSizeInfo aInf( pFrame );
717 SwTextCursor aLine( pFrame, &aInf );
718
720 nRightMargin = aLine.GetStart() + aLine.GetCurr()->GetLen();
721
722 // We skip hard line breaks
723 if( aLine.GetCurr()->GetLen() &&
724 CH_BREAK == aInf.GetText()[sal_Int32(nRightMargin) - 1])
725 --nRightMargin;
726 else if( !bAPI && (aLine.GetNext() || pFrame->GetFollow()) )
727 {
728 while( nRightMargin > aLine.GetStart() &&
729 ' ' == aInf.GetText()[sal_Int32(nRightMargin) - 1])
730 --nRightMargin;
731 }
732 }
733 *pPam->GetPoint() = pFrame->MapViewToModelPos(nRightMargin);
735 return true;
736}
737
738// The following two methods try to put the Cursor into the next/successive
739// line. If we do not have a preceding/successive line we forward the call
740// to the base class.
741// The Cursor's horizontal justification is done afterwards by the CursorShell.
742
743namespace {
744
745class SwSetToRightMargin
746{
747 bool m_bRight;
748
749public:
750 SwSetToRightMargin()
751 : m_bRight(false)
752 {
753 }
754 ~SwSetToRightMargin() { SwTextCursor::SetRightMargin(m_bRight); }
755 void SetRight(const bool bNew) { m_bRight = bNew; }
756};
757
758}
759
760bool SwTextFrame::UnitUp_( SwPaM *pPam, const SwTwips nOffset,
761 bool bSetInReadOnly ) const
762{
763 // Set the RightMargin if needed
764 SwSetToRightMargin aSet;
765
766 if( IsInTab() &&
769 {
770 // If the PaM is located within different boxes, we have a table selection,
771 // which is handled by the base class.
772 return SwContentFrame::UnitUp( pPam, nOffset, bSetInReadOnly );
773 }
774
775 const_cast<SwTextFrame*>(this)->GetFormatted();
777 SwRect aCharBox;
778
779 if( !IsEmpty() && !IsHiddenNow() )
780 {
782 do
783 {
784 if (nFormat != TextFrameIndex(COMPLETE_STRING) && !IsFollow())
785 sw_ChangeOffset( const_cast<SwTextFrame*>(this), nFormat );
786
787 SwTextSizeInfo aInf( const_cast<SwTextFrame*>(this) );
788 SwTextCursor aLine( const_cast<SwTextFrame*>(this), &aInf );
789
790 // Optimize away flys with no flow and IsDummy()
791 if( nPos )
792 aLine.CharCursorToLine( nPos );
793 else
794 aLine.Top();
795
796 const SwLineLayout *pPrevLine = aLine.GetPrevLine();
797 const TextFrameIndex nStart = aLine.GetStart();
798 aLine.GetCharRect( &aCharBox, nPos );
799
800 bool bSecondOfDouble = ( aInf.IsMulti() && ! aInf.IsFirstMulti() );
801 bool bPrevLine = ( pPrevLine && pPrevLine != aLine.GetCurr() );
802
803 if( !pPrevLine && !bSecondOfDouble && GetOffset() && !IsFollow() )
804 {
805 nFormat = GetOffset();
806 TextFrameIndex nDiff = aLine.GetLength();
807 if( !nDiff )
809 if( nFormat > nDiff )
810 nFormat = nFormat - nDiff;
811 else
812 nFormat = TextFrameIndex(0);
813 continue;
814 }
815
816 // We select the target line for the cursor, in case we are in a
817 // double line portion, prev line = curr line
818 if( bPrevLine && !bSecondOfDouble )
819 {
820 aLine.PrevLine();
821 while ( aLine.GetStart() == nStart &&
822 nullptr != ( pPrevLine = aLine.GetPrevLine() ) &&
823 pPrevLine != aLine.GetCurr() )
824 aLine.PrevLine();
825 }
826
827 if ( bPrevLine || bSecondOfDouble )
828 {
829 aCharBox.Width( aCharBox.SSize().Width() / 2 );
830 aCharBox.Pos().setX( aCharBox.Pos().X() - 150 );
831
832 // See comment in SwTextFrame::GetModelPositionForViewPoint()
833#if OSL_DEBUG_LEVEL > 0
834 const SwNodeOffset nOldNode = pPam->GetPoint()->GetNodeIndex();
835#endif
836 // The node should not be changed
838 aCharBox.Pos(), false );
839#if OSL_DEBUG_LEVEL > 0
840 OSL_ENSURE( nOldNode == pPam->GetPoint()->GetNodeIndex(),
841 "SwTextFrame::UnitUp: illegal node change" );
842#endif
843
844 // We make sure that we move up.
845 if( nTmpOfst >= nStart && nStart && !bSecondOfDouble )
846 {
847 nTmpOfst = nStart;
848 aSet.SetRight( true );
849 }
850 *pPam->GetPoint() = MapViewToModelPos(nTmpOfst);
851 return true;
852 }
853
854 if ( IsFollow() )
855 {
856 aLine.GetCharRect( &aCharBox, nPos );
857 aCharBox.Width( aCharBox.SSize().Width() / 2 );
858 }
859 break;
860 } while ( true );
861 }
862 /* If 'this' is a follow and a prev failed, we need to go to the
863 * last line of the master, which is us.
864 * Or: If we are a follow with follow, we need to get the master.
865 */
866 if ( IsFollow() )
867 {
868 const SwTextFrame *pTmpPrev = FindMaster();
869 TextFrameIndex nOffs = GetOffset();
870 if( pTmpPrev )
871 {
873 const bool bProtectedAllowed = pSh && pSh->GetViewOptions()->IsCursorInProtectedArea();
874 const SwTextFrame *pPrevPrev = pTmpPrev;
875 // We skip protected frames and frames without content here
876 while( pPrevPrev && ( pPrevPrev->GetOffset() == nOffs ||
877 ( !bProtectedAllowed && pPrevPrev->IsProtected() ) ) )
878 {
879 pTmpPrev = pPrevPrev;
880 nOffs = pTmpPrev->GetOffset();
881 if ( pPrevPrev->IsFollow() )
882 pPrevPrev = pTmpPrev->FindMaster();
883 else
884 pPrevPrev = nullptr;
885 }
886 if ( !pPrevPrev )
887 return pTmpPrev->SwContentFrame::UnitUp( pPam, nOffset, bSetInReadOnly );
888 aCharBox.Pos().setY( pPrevPrev->getFrameArea().Bottom() - 1 );
889 return pPrevPrev->GetKeyCursorOfst( pPam->GetPoint(), aCharBox.Pos() );
890 }
891 }
892 return SwContentFrame::UnitUp( pPam, nOffset, bSetInReadOnly );
893}
894
895// Used for Bidi. nPos is the logical position in the string, bLeft indicates
896// if left arrow or right arrow was pressed. The return values are:
897// nPos: the new visual position
898// bLeft: whether the break iterator has to add or subtract from the
899// current position
900static void lcl_VisualMoveRecursion(const SwLineLayout& rCurrLine, TextFrameIndex nIdx,
901 TextFrameIndex & nPos, bool& bRight,
902 sal_uInt8& nCursorLevel, sal_uInt8 nDefaultDir )
903{
904 const SwLinePortion* pPor = rCurrLine.GetFirstPortion();
905 const SwLinePortion* pLast = nullptr;
906
907 // What's the current portion?
908 while ( pPor && nIdx + pPor->GetLen() <= nPos )
909 {
910 nIdx = nIdx + pPor->GetLen();
911 pLast = pPor;
912 pPor = pPor->GetNextPortion();
913 }
914
915 if ( bRight )
916 {
917 bool bRecurse = pPor && pPor->IsMultiPortion() &&
918 static_cast<const SwMultiPortion*>(pPor)->IsBidi();
919
920 // 1. special case: at beginning of bidi portion
921 if ( bRecurse && nIdx == nPos )
922 {
923 nPos = nPos + pPor->GetLen();
924
925 // leave bidi portion
926 if ( nCursorLevel != nDefaultDir )
927 {
928 bRecurse = false;
929 }
930 else
931 // special case:
932 // buffer: abcXYZ123 in LTR paragraph
933 // view: abc123ZYX
934 // cursor is between c and X in the buffer and cursor level = 0
935 nCursorLevel++;
936 }
937
938 // 2. special case: at beginning of portion after bidi portion
939 else if ( pLast && pLast->IsMultiPortion() &&
940 static_cast<const SwMultiPortion*>(pLast)->IsBidi() && nIdx == nPos )
941 {
942 // enter bidi portion
943 if ( nCursorLevel != nDefaultDir )
944 {
945 bRecurse = true;
946 nIdx = nIdx - pLast->GetLen();
947 pPor = pLast;
948 }
949 }
950
951 // Recursion
952 if ( bRecurse )
953 {
954 const SwLineLayout& rLine = static_cast<const SwMultiPortion*>(pPor)->GetRoot();
955 TextFrameIndex nTmpPos = nPos - nIdx;
956 bool bTmpForward = ! bRight;
957 sal_uInt8 nTmpCursorLevel = nCursorLevel;
958 lcl_VisualMoveRecursion(rLine, TextFrameIndex(0), nTmpPos, bTmpForward,
959 nTmpCursorLevel, nDefaultDir + 1 );
960
961 nPos = nTmpPos + nIdx;
962 bRight = bTmpForward;
963 nCursorLevel = nTmpCursorLevel;
964 }
965
966 // go forward
967 else
968 {
969 bRight = true;
970 nCursorLevel = nDefaultDir;
971 }
972
973 }
974 else
975 {
976 bool bRecurse = pPor && pPor->IsMultiPortion() && static_cast<const SwMultiPortion*>(pPor)->IsBidi();
977
978 // 1. special case: at beginning of bidi portion
979 if ( bRecurse && nIdx == nPos )
980 {
981 // leave bidi portion
982 if ( nCursorLevel == nDefaultDir )
983 {
984 bRecurse = false;
985 }
986 }
987
988 // 2. special case: at beginning of portion after bidi portion
989 else if ( pLast && pLast->IsMultiPortion() &&
990 static_cast<const SwMultiPortion*>(pLast)->IsBidi() && nIdx == nPos )
991 {
992 nPos = nPos - pLast->GetLen();
993
994 // enter bidi portion
995 if ( nCursorLevel % 2 == nDefaultDir % 2 )
996 {
997 bRecurse = true;
998 nIdx = nIdx - pLast->GetLen();
999 pPor = pLast;
1000
1001 // special case:
1002 // buffer: abcXYZ123 in LTR paragraph
1003 // view: abc123ZYX
1004 // cursor is behind 3 in the buffer and cursor level = 2
1005 if ( nDefaultDir + 2 == nCursorLevel )
1006 nPos = nPos + pLast->GetLen();
1007 }
1008 }
1009
1010 // go forward
1011 if ( bRecurse )
1012 {
1013 const SwLineLayout& rLine = static_cast<const SwMultiPortion*>(pPor)->GetRoot();
1014 TextFrameIndex nTmpPos = nPos - nIdx;
1015 bool bTmpForward = ! bRight;
1016 sal_uInt8 nTmpCursorLevel = nCursorLevel;
1017 lcl_VisualMoveRecursion(rLine, TextFrameIndex(0), nTmpPos, bTmpForward,
1018 nTmpCursorLevel, nDefaultDir + 1 );
1019
1020 // special case:
1021 // buffer: abcXYZ123 in LTR paragraph
1022 // view: abc123ZYX
1023 // cursor is between Z and 1 in the buffer and cursor level = 2
1024 if ( nTmpPos == pPor->GetLen() && nTmpCursorLevel == nDefaultDir + 1 )
1025 {
1026 nTmpPos = nTmpPos - pPor->GetLen();
1027 nTmpCursorLevel = nDefaultDir;
1028 bTmpForward = ! bTmpForward;
1029 }
1030
1031 nPos = nTmpPos + nIdx;
1032 bRight = bTmpForward;
1033 nCursorLevel = nTmpCursorLevel;
1034 }
1035
1036 // go backward
1037 else
1038 {
1039 bRight = false;
1040 nCursorLevel = nDefaultDir;
1041 }
1042 }
1043}
1044
1046 bool& bForward, bool bInsertCursor )
1047{
1048 if( IsEmpty() || IsHiddenNow() )
1049 return;
1050
1051 GetFormatted();
1052
1053 SwTextSizeInfo aInf(this);
1054 SwTextCursor aLine(this, &aInf);
1055
1056 if( nPos )
1057 aLine.CharCursorToLine( nPos );
1058 else
1059 aLine.Top();
1060
1061 const SwLineLayout* pLine = aLine.GetCurr();
1062 const TextFrameIndex nStt = aLine.GetStart();
1063 const TextFrameIndex nLen = pLine->GetLen();
1064
1065 // We have to distinguish between an insert and overwrite cursor:
1066 // The insert cursor position depends on the cursor level:
1067 // buffer: abcXYZdef in LTR paragraph
1068 // display: abcZYXdef
1069 // If cursor is between c and X in the buffer and cursor level is 0,
1070 // the cursor blinks between c and Z and -> sets the cursor between Z and Y.
1071 // If the cursor level is 1, the cursor blinks between X and d and
1072 // -> sets the cursor between d and e.
1073 // The overwrite cursor simply travels to the next visual character.
1074 if ( bInsertCursor )
1075 {
1076 lcl_VisualMoveRecursion( *pLine, nStt, nPos, bForward,
1077 nCursorLevel, IsRightToLeft() ? 1 : 0 );
1078 return;
1079 }
1080
1081 const sal_uInt8 nDefaultDir = static_cast<sal_uInt8>(IsRightToLeft() ? UBIDI_RTL : UBIDI_LTR);
1082 const bool bVisualRight = ( nDefaultDir == UBIDI_LTR && bForward ) ||
1083 ( nDefaultDir == UBIDI_RTL && ! bForward );
1084
1085 // Bidi functions from icu 2.0
1086
1087 const sal_Unicode* pLineString = GetText().getStr();
1088
1089 UErrorCode nError = U_ZERO_ERROR;
1090 UBiDi* pBidi = ubidi_openSized( sal_Int32(nLen), 0, &nError );
1091 ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString),
1092 sal_Int32(nLen), nDefaultDir, nullptr, &nError );
1093
1094 TextFrameIndex nTmpPos(0);
1095 bool bOutOfBounds = false;
1096
1097 if ( nPos < nStt + nLen )
1098 {
1099 nTmpPos = TextFrameIndex(ubidi_getVisualIndex( pBidi, sal_Int32(nPos), &nError ));
1100
1101 // visual indices are always LTR aligned
1102 if ( bVisualRight )
1103 {
1104 if (nTmpPos + TextFrameIndex(1) < nStt + nLen)
1105 ++nTmpPos;
1106 else
1107 {
1108 nPos = nDefaultDir == UBIDI_RTL ? TextFrameIndex(0) : nStt + nLen;
1109 bOutOfBounds = true;
1110 }
1111 }
1112 else
1113 {
1114 if ( nTmpPos )
1115 --nTmpPos;
1116 else
1117 {
1118 nPos = nDefaultDir == UBIDI_RTL ? nStt + nLen : TextFrameIndex(0);
1119 bOutOfBounds = true;
1120 }
1121 }
1122 }
1123 else
1124 {
1125 nTmpPos = nDefaultDir == UBIDI_LTR ? nPos - TextFrameIndex(1) : TextFrameIndex(0);
1126 }
1127
1128 if ( ! bOutOfBounds )
1129 {
1130 nPos = TextFrameIndex(ubidi_getLogicalIndex( pBidi, sal_Int32(nTmpPos), &nError ));
1131
1132 if ( bForward )
1133 {
1134 if ( nPos )
1135 --nPos;
1136 else
1137 {
1138 ++nPos;
1139 bForward = ! bForward;
1140 }
1141 }
1142 else
1143 ++nPos;
1144 }
1145
1146 ubidi_close( pBidi );
1147}
1148
1149bool SwTextFrame::UnitDown_(SwPaM *pPam, const SwTwips nOffset,
1150 bool bSetInReadOnly ) const
1151{
1152
1153 if ( IsInTab() &&
1154 pPam->GetPointNode().StartOfSectionNode() !=
1156 {
1157 // If the PaM is located within different boxes, we have a table selection,
1158 // which is handled by the base class.
1159 return SwContentFrame::UnitDown( pPam, nOffset, bSetInReadOnly );
1160 }
1161 const_cast<SwTextFrame*>(this)->GetFormatted();
1163 SwRect aCharBox;
1164 const SwContentFrame *pTmpFollow = nullptr;
1165
1166 if ( IsVertical() )
1167 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
1168
1169 if ( !IsEmpty() && !IsHiddenNow() )
1170 {
1172 do
1173 {
1174 if (nFormat != TextFrameIndex(COMPLETE_STRING) && !IsFollow() &&
1175 !sw_ChangeOffset( const_cast<SwTextFrame*>(this), nFormat ) )
1176 break;
1177
1178 SwTextSizeInfo aInf( const_cast<SwTextFrame*>(this) );
1179 SwTextCursor aLine( const_cast<SwTextFrame*>(this), &aInf );
1180 nFormat = aLine.GetEnd();
1181
1182 aLine.CharCursorToLine( nPos );
1183
1184 const SwLineLayout* pNextLine = aLine.GetNextLine();
1185 const TextFrameIndex nStart = aLine.GetStart();
1186 aLine.GetCharRect( &aCharBox, nPos );
1187
1188 bool bFirstOfDouble = ( aInf.IsMulti() && aInf.IsFirstMulti() );
1189
1190 if( pNextLine || bFirstOfDouble )
1191 {
1192 aCharBox.Width( aCharBox.SSize().Width() / 2 );
1193#if OSL_DEBUG_LEVEL > 0
1194 // See comment in SwTextFrame::GetModelPositionForViewPoint()
1195 const SwNodeOffset nOldNode = pPam->GetPoint()->GetNodeIndex();
1196#endif
1197 if ( pNextLine && ! bFirstOfDouble )
1198 aLine.NextLine();
1199
1200 TextFrameIndex nTmpOfst = aLine.GetModelPositionForViewPoint( pPam->GetPoint(),
1201 aCharBox.Pos(), false );
1202#if OSL_DEBUG_LEVEL > 0
1203 OSL_ENSURE( nOldNode == pPam->GetPoint()->GetNodeIndex(),
1204 "SwTextFrame::UnitDown: illegal node change" );
1205#endif
1206
1207 // We make sure that we move down.
1208 if( nTmpOfst <= nStart && ! bFirstOfDouble )
1209 nTmpOfst = nStart + TextFrameIndex(1);
1210 *pPam->GetPoint() = MapViewToModelPos(nTmpOfst);
1211
1212 if ( IsVertical() )
1213 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
1214
1215 return true;
1216 }
1217 pTmpFollow = GetFollow();
1218 if( nullptr != pTmpFollow )
1219 { // Skip protected follows
1220 const SwContentFrame* pTmp = pTmpFollow;
1222 if( !pSh || !pSh->GetViewOptions()->IsCursorInProtectedArea() )
1223 {
1224 while( pTmpFollow && pTmpFollow->IsProtected() )
1225 {
1226 pTmp = pTmpFollow;
1227 pTmpFollow = pTmpFollow->GetFollow();
1228 }
1229 }
1230 if( !pTmpFollow ) // Only protected ones left
1231 {
1232 if ( IsVertical() )
1233 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
1234 return pTmp->SwContentFrame::UnitDown( pPam, nOffset, bSetInReadOnly );
1235 }
1236
1237 aLine.GetCharRect( &aCharBox, nPos );
1238 aCharBox.Width( aCharBox.SSize().Width() / 2 );
1239 }
1240 else if( !IsFollow() )
1241 {
1242 TextFrameIndex nTmpLen(aInf.GetText().getLength());
1243 if( aLine.GetEnd() < nTmpLen )
1244 {
1245 if( nFormat <= GetOffset() )
1246 {
1248 nTmpLen );
1249 if( nFormat <= GetOffset() )
1250 break;
1251 }
1252 continue;
1253 }
1254 }
1255 break;
1256 } while( true );
1257 }
1258 else
1259 pTmpFollow = GetFollow();
1260
1261 if ( IsVertical() )
1262 const_cast<SwTextFrame*>(this)->SwapWidthAndHeight();
1263
1264 // We take a shortcut for follows
1265 if( pTmpFollow )
1266 {
1267 aCharBox.Pos().setY( pTmpFollow->getFrameArea().Top() + 1 );
1268 return static_cast<const SwTextFrame*>(pTmpFollow)->GetKeyCursorOfst( pPam->GetPoint(),
1269 aCharBox.Pos() );
1270 }
1271 return SwContentFrame::UnitDown( pPam, nOffset, bSetInReadOnly );
1272}
1273
1274bool SwTextFrame::UnitUp(SwPaM *pPam, const SwTwips nOffset,
1275 bool bSetInReadOnly ) const
1276{
1277 /* We call ContentNode::GertFrame() in CursorSh::Up().
1278 * This _always returns the master.
1279 * In order to not mess with cursor travelling, we correct here
1280 * in SwTextFrame.
1281 * We calculate UnitUp for pFrame. pFrame is either a master (= this) or a
1282 * follow (!= this).
1283 */
1284 const SwTextFrame *pFrame = GetAdjFrameAtPos( const_cast<SwTextFrame*>(this), *(pPam->GetPoint()),
1286 const bool bRet = pFrame->UnitUp_( pPam, nOffset, bSetInReadOnly );
1287
1288 // No SwTextCursor::SetRightMargin( false );
1289 // Instead we have a SwSetToRightMargin in UnitUp_
1290 return bRet;
1291}
1292
1293bool SwTextFrame::UnitDown(SwPaM *pPam, const SwTwips nOffset,
1294 bool bSetInReadOnly ) const
1295{
1296 const SwTextFrame *pFrame = GetAdjFrameAtPos(const_cast<SwTextFrame*>(this), *(pPam->GetPoint()),
1298 const bool bRet = pFrame->UnitDown_( pPam, nOffset, bSetInReadOnly );
1300 return bRet;
1301}
1302
1304{
1305 if( !rFill.bColumn && GetUpper()->IsColBodyFrame() ) // ColumnFrames now with BodyFrame
1306 {
1307 const SwColumnFrame* pTmp =
1308 static_cast<const SwColumnFrame*>(GetUpper()->GetUpper()->GetUpper()->Lower()); // The 1st column
1309 // The first SwFrame in BodyFrame of the first column
1310 const SwFrame* pFrame = static_cast<const SwLayoutFrame*>(pTmp->Lower())->Lower();
1311 sal_uInt16 nNextCol = 0;
1312 // In which column do we end up in?
1313 while( rFill.X() > pTmp->getFrameArea().Right() && pTmp->GetNext() )
1314 {
1315 pTmp = static_cast<const SwColumnFrame*>(pTmp->GetNext());
1316 if( static_cast<const SwLayoutFrame*>(pTmp->Lower())->Lower() ) // ColumnFrames now with BodyFrame
1317 {
1318 pFrame = static_cast<const SwLayoutFrame*>(pTmp->Lower())->Lower();
1319 nNextCol = 0;
1320 }
1321 else
1322 ++nNextCol; // Empty columns require column breaks
1323 }
1324 if( pTmp != GetUpper()->GetUpper() ) // Did we end up in another column?
1325 {
1326 if( !pFrame )
1327 return;
1328 if( nNextCol )
1329 {
1330 while( pFrame->GetNext() )
1331 pFrame = pFrame->GetNext();
1332 }
1333 else
1334 {
1335 while( pFrame->GetNext() && pFrame->getFrameArea().Bottom() < rFill.Y() )
1336 pFrame = pFrame->GetNext();
1337 }
1338 // No filling, if the last frame in the targeted column does
1339 // not contain a paragraph, but e.g. a table
1340 if( pFrame->IsTextFrame() )
1341 {
1342 rFill.Fill().nColumnCnt = nNextCol;
1343 rFill.bColumn = true;
1344 if( rFill.pPos )
1345 {
1346 SwTextFrame const*const pTextFrame(static_cast<const SwTextFrame*>(pFrame));
1347 *rFill.pPos = pTextFrame->MapViewToModelPos(
1348 TextFrameIndex(pTextFrame->GetText().getLength()));
1349 }
1350 if( nNextCol )
1351 {
1352 rFill.aFrame = pTmp->getFramePrintArea();
1353 rFill.aFrame += pTmp->getFrameArea().Pos();
1354 }
1355 else
1356 rFill.aFrame = pFrame->getFrameArea();
1357 static_cast<const SwTextFrame*>(pFrame)->FillCursorPos( rFill );
1358 }
1359 return;
1360 }
1361 }
1362 std::unique_ptr<SwFont> pFnt;
1365 SwTwips nDiff = rFill.Y() - getFrameArea().Bottom();
1366 if( nDiff < nFirst )
1367 nDiff = -1;
1368 else
1369 pColl = &pColl->GetNextTextFormatColl();
1370 SwAttrSet aSet(const_cast<SwDoc&>(GetDoc()).GetAttrPool(), aTextFormatCollSetRange );
1371 const SwAttrSet* pSet = &pColl->GetAttrSet();
1373 if (GetTextNodeForParaProps()->HasSwAttrSet())
1374 {
1375 // sw_redlinehide: pSet is mostly used for para props, but there are
1376 // accesses to char props via pFnt - why does it use only the node's
1377 // props for this, and not hints?
1378 aSet.Put( *GetTextNodeForParaProps()->GetpSwAttrSet() );
1379 aSet.SetParent( pSet );
1380 pSet = &aSet;
1381 pFnt.reset(new SwFont( pSet, &GetDoc().getIDocumentSettingAccess() ));
1382 }
1383 else
1384 {
1385 SwFontAccess aFontAccess( pColl, pSh );
1386 pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
1387 pFnt->CheckFontCacheId( pSh, pFnt->GetActual() );
1388 }
1389 OutputDevice* pOut = pSh->GetOut();
1390 if( !pSh->GetViewOptions()->getBrowseMode() || pSh->GetViewOptions()->IsPrtFormat() )
1392
1393 pFnt->SetFntChg( true );
1394 pFnt->ChgPhysFnt( pSh, *pOut );
1395
1396 SwTwips nLineHeight = pFnt->GetHeight( pSh, *pOut );
1397
1398 bool bFill = false;
1399 if( nLineHeight )
1400 {
1401 bFill = true;
1402 const SvxULSpaceItem &rUL = pSet->GetULSpace();
1403 SwTwips nDist = std::max( rUL.GetLower(), rUL.GetUpper() );
1404 if( rFill.Fill().nColumnCnt )
1405 {
1406 rFill.aFrame.Height( nLineHeight );
1407 nDiff = rFill.Y() - rFill.Bottom();
1408 nFirst = 0;
1409 }
1410 else if( nDist < nFirst )
1411 nFirst = nFirst - nDist;
1412 else
1413 nFirst = 0;
1414 nDist = std::max( nDist, SwTwips(GetLineSpace()) );
1415 nDist += nLineHeight;
1416 nDiff -= nFirst;
1417
1418 if( nDiff > 0 )
1419 {
1420 nDiff /= nDist;
1421 rFill.Fill().nParaCnt = o3tl::narrowing<sal_uInt16>(nDiff + 1);
1422 rFill.nLineWidth = 0;
1423 rFill.bInner = false;
1424 rFill.bEmpty = true;
1425 rFill.SetOrient( text::HoriOrientation::LEFT );
1426 }
1427 else
1428 nDiff = -1;
1429 if( rFill.bInner )
1430 bFill = false;
1431 else
1432 {
1433 const SvxTabStopItem &rRuler = pSet->GetTabStops();
1434 const SvxLRSpaceItem &rLRSpace = pSet->GetLRSpace();
1435
1436 SwRect &rRect = rFill.Fill().aCursor;
1437 rRect.Top( rFill.Bottom() + (nDiff+1) * nDist - nLineHeight );
1438 if( nFirst && nDiff > -1 )
1439 rRect.Top( rRect.Top() + nFirst );
1440 rRect.Height( nLineHeight );
1441 SwTwips nLeft = rFill.Left() + rLRSpace.GetLeft() +
1443 SwTwips nRight = rFill.Right() - rLRSpace.GetRight();
1444 SwTwips nCenter = ( nLeft + nRight ) / 2;
1445 rRect.Left( nLeft );
1446 if( SwFillMode::Margin == rFill.Mode() )
1447 {
1448 if( rFill.bEmpty )
1449 {
1450 rFill.SetOrient( text::HoriOrientation::LEFT );
1451 if( rFill.X() < nCenter )
1452 {
1453 if( rFill.X() > ( nLeft + 2 * nCenter ) / 3 )
1454 {
1455 rFill.SetOrient( text::HoriOrientation::CENTER );
1456 rRect.Left( nCenter );
1457 }
1458 }
1459 else if( rFill.X() > ( nRight + 2 * nCenter ) / 3 )
1460 {
1461 rFill.SetOrient( text::HoriOrientation::RIGHT );
1462 rRect.Left( nRight );
1463 }
1464 else
1465 {
1466 rFill.SetOrient( text::HoriOrientation::CENTER );
1467 rRect.Left( nCenter );
1468 }
1469 }
1470 else
1471 bFill = false;
1472 }
1473 else
1474 {
1475 SwTwips nSpace = 0;
1476 if( SwFillMode::Tab != rFill.Mode() )
1477 {
1478 SwDrawTextInfo aDrawInf( pSh, *pOut, " ", 0, 2 );
1479 nSpace = pFnt->GetTextSize_( aDrawInf ).Width()/2;
1480 }
1481 if( rFill.X() >= nRight )
1482 {
1483 if( SwFillMode::Indent != rFill.Mode() && ( rFill.bEmpty ||
1484 rFill.X() > rFill.nLineWidth + FILL_MIN_DIST ) )
1485 {
1486 rFill.SetOrient( text::HoriOrientation::RIGHT );
1487 rRect.Left( nRight );
1488 }
1489 else
1490 bFill = false;
1491 }
1492 else if( SwFillMode::Indent == rFill.Mode() )
1493 {
1494 SwTwips nIndent = rFill.X();
1495 if( !rFill.bEmpty || nIndent > nRight )
1496 bFill = false;
1497 else
1498 {
1499 nIndent -= rFill.Left();
1500 if( nIndent >= 0 && nSpace )
1501 {
1502 nIndent /= nSpace;
1503 nIndent *= nSpace;
1504 rFill.SetTab( sal_uInt16( nIndent ) );
1505 rRect.Left( nIndent + rFill.Left() );
1506 }
1507 else
1508 bFill = false;
1509 }
1510 }
1511 else if( rFill.X() > nLeft )
1512 {
1513 SwTwips nTextLeft = rFill.Left() + rLRSpace.GetTextLeft() +
1515 rFill.nLineWidth += rFill.bFirstLine ? nLeft : nTextLeft;
1516 SwTwips nLeftTab;
1517 SwTwips nRightTab = nLeft;
1518 sal_uInt16 nSpaceCnt = 0;
1519 sal_uInt16 nSpaceOnlyCnt = 0;
1520 sal_uInt16 nTabCnt = 0;
1521 sal_uInt16 nIdx = 0;
1522 do
1523 {
1524 nLeftTab = nRightTab;
1525 if( nIdx < rRuler.Count() )
1526 {
1527 const SvxTabStop &rTabStop = rRuler.operator[](nIdx);
1528 nRightTab = nTextLeft + rTabStop.GetTabPos();
1529 if( nLeftTab < nTextLeft && nRightTab > nTextLeft )
1530 nRightTab = nTextLeft;
1531 else
1532 ++nIdx;
1533 if( nRightTab > rFill.nLineWidth )
1534 ++nTabCnt;
1535 }
1536 else
1537 {
1538 const SvxTabStopItem& rTab =
1540 const SwTwips nDefTabDist = rTab[0].GetTabPos();
1541 nRightTab = nLeftTab - nTextLeft;
1542 nRightTab /= nDefTabDist;
1543 nRightTab = nRightTab * nDefTabDist + nTextLeft;
1544 while ( nRightTab <= nLeftTab )
1545 nRightTab += nDefTabDist;
1546 if( nRightTab > rFill.nLineWidth )
1547 ++nTabCnt;
1548 while ( nRightTab < rFill.X() )
1549 {
1550 nRightTab += nDefTabDist;
1551 if( nRightTab > rFill.nLineWidth )
1552 ++nTabCnt;
1553 }
1554 if( nLeftTab < nRightTab - nDefTabDist )
1555 nLeftTab = nRightTab - nDefTabDist;
1556 }
1557 if( nRightTab > nRight )
1558 nRightTab = nRight;
1559 }
1560 while( rFill.X() > nRightTab );
1561 --nTabCnt;
1562 if( SwFillMode::TabSpace == rFill.Mode() )
1563 {
1564 if( nSpace > 0 )
1565 {
1566 if( !nTabCnt )
1567 nLeftTab = rFill.nLineWidth;
1568 while( nLeftTab < rFill.X() )
1569 {
1570 nLeftTab += nSpace;
1571 ++nSpaceCnt;
1572 }
1573 if( nSpaceCnt )
1574 {
1575 nLeftTab -= nSpace;
1576 --nSpaceCnt;
1577 }
1578 if( rFill.X() - nLeftTab > nRightTab - rFill.X() )
1579 {
1580 nSpaceCnt = 0;
1581 ++nTabCnt;
1582 rRect.Left( nRightTab );
1583 }
1584 else
1585 {
1586 if( rFill.X() - nLeftTab > nSpace/2 )
1587 {
1588 ++nSpaceCnt;
1589 rRect.Left( nLeftTab + nSpace );
1590 }
1591 else
1592 rRect.Left( nLeftTab );
1593 }
1594 }
1595 else if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
1596 rRect.Left( nLeftTab );
1597 else
1598 {
1599 if( nRightTab >= nRight )
1600 {
1601 rFill.SetOrient( text::HoriOrientation::RIGHT );
1602 rRect.Left( nRight );
1603 nTabCnt = 0;
1604 nSpaceCnt = 0;
1605 }
1606 else
1607 {
1608 rRect.Left( nRightTab );
1609 ++nTabCnt;
1610 }
1611 }
1612 }
1613 else if( SwFillMode::Space == rFill.Mode() )
1614 {
1615 SwTwips nLeftSpace = nLeft;
1616 while( nLeftSpace < rFill.X() )
1617 {
1618 nLeftSpace += nSpace;
1619 ++nSpaceOnlyCnt;
1620 }
1621 rRect.Left( nLeftSpace );
1622 }
1623 else
1624 {
1625 if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
1626 rRect.Left( nLeftTab );
1627 else
1628 {
1629 if( nRightTab >= nRight )
1630 {
1631 rFill.SetOrient( text::HoriOrientation::RIGHT );
1632 rRect.Left( nRight );
1633 nTabCnt = 0;
1634 nSpaceCnt = 0;
1635 }
1636 else
1637 {
1638 rRect.Left( nRightTab );
1639 ++nTabCnt;
1640 }
1641 }
1642 }
1643 rFill.SetTab( nTabCnt );
1644 rFill.SetSpace( nSpaceCnt );
1645 rFill.SetSpaceOnly( nSpaceOnlyCnt );
1646 if( bFill )
1647 {
1648 if( std::abs( rFill.X() - nCenter ) <=
1649 std::abs( rFill.X() - rRect.Left() ) )
1650 {
1651 rFill.SetOrient( text::HoriOrientation::CENTER );
1652 rFill.SetTab( 0 );
1653 rFill.SetSpace( 0 );
1654 rFill.SetSpaceOnly( 0 );
1655 rRect.Left( nCenter );
1656 }
1657 if( !rFill.bEmpty )
1658 rFill.nLineWidth += FILL_MIN_DIST;
1659 if( rRect.Left() < rFill.nLineWidth )
1660 bFill = false;
1661 }
1662 }
1663 }
1664 // Do we extend over the page's/column's/etc. lower edge?
1665 const SwFrame* pUp = GetUpper();
1666 if( pUp->IsInSct() )
1667 {
1668 if( pUp->IsSctFrame() )
1669 pUp = pUp->GetUpper();
1670 else if( pUp->IsColBodyFrame() &&
1671 pUp->GetUpper()->GetUpper()->IsSctFrame() )
1672 pUp = pUp->GetUpper()->GetUpper()->GetUpper();
1673 }
1674 SwRectFnSet aRectFnSet(this);
1675 SwTwips nLimit = aRectFnSet.GetPrtBottom(*pUp);
1676 SwTwips nRectBottom = rRect.Bottom();
1677 if ( aRectFnSet.IsVert() )
1678 nRectBottom = SwitchHorizontalToVertical( nRectBottom );
1679
1680 if( aRectFnSet.YDiff( nLimit, nRectBottom ) < 0 )
1681 bFill = false;
1682 else
1683 rRect.Width( 1 );
1684 }
1685 }
1686 const_cast<SwCursorMoveState*>(rFill.pCMS)->m_bFillRet = bFill;
1687}
1688
1689/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
virtual OutputDevice * getReferenceDevice(bool bCreate) const =0
Returns the current reference device.
const SfxPoolItem & GetDefaultItem(sal_uInt16 nWhich) const
void SetParent(const SfxItemSet *pNew)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
tools::Long GetRight() const
tools::Long GetTextLeft() const
tools::Long GetLeft() const
SvxInterLineSpaceRule GetInterLineSpaceRule() const
sal_uInt16 Count() const
sal_Int32 & GetTabPos()
sal_uInt16 GetUpper() const
sal_uInt16 GetLower() const
SwAttrPool * GetPool() const
Definition: swatrset.hxx:183
const SvxTabStopItem & GetTabStops(bool=true) const
Definition: paratr.hxx:204
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:44
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:46
const SvxLineSpacingItem & GetLineSpacing(bool=true) const
Definition: paratr.hxx:192
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:58
virtual bool UnitUp(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:962
const SwContentFrame * GetFollow() const
Definition: cntfrm.hxx:135
virtual bool UnitDown(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:967
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:737
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:743
Definition: doc.hxx:192
IDocumentDeviceAccess const & getIDocumentDeviceAccess() const
Definition: doc.cxx:239
bool HasFollow() const
Definition: flowfrm.hxx:166
bool IsFollow() const
Definition: flowfrm.hxx:167
bool IsUndersized() const
Definition: flowfrm.hxx:159
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
SwFlyFrame * GetPrevLink() const
Definition: flyfrm.hxx:194
SwFlyFrame * GetNextLink() const
Definition: flyfrm.hxx:195
SwFontObj * Get()
Definition: swfntcch.cxx:56
SwFont & GetFont()
Definition: swfntcch.hxx:58
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
const SwRect & getFrameArea() const
Definition: frame.hxx:179
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:171
const SwRect & getFramePrintArea() const
Definition: frame.hxx:180
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:928
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsTextFrame() const
Definition: frame.hxx:1234
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1111
SwFrame * GetNext()
Definition: frame.hxx:676
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:564
bool IsInTab() const
Definition: frame.hxx:955
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1638
bool IsRightToLeft() const
Definition: frame.hxx:987
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame,...
Definition: findfrm.cxx:731
SwLayoutFrame * GetUpper()
Definition: frame.hxx:678
bool IsVertical() const
Definition: frame.hxx:973
SwRootFrame * getRootFrame()
Definition: frame.hxx:679
bool IsSctFrame() const
Definition: frame.hxx:1214
SwPageFrame * FindPageFrame()
Definition: frame.hxx:680
sw::BroadcastingModify * GetDep()
use these so we can grep for SwFrame's GetRegisteredIn accesses beware that SwTextFrame may return sw...
Definition: frame.hxx:476
bool IsColBodyFrame() const
These SwFrame inlines are here, so that frame.hxx does not need to include layfrm....
Definition: layfrm.hxx:210
bool IsInSct() const
Definition: frame.hxx:967
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
const SwFrame * Lower() const
Definition: layfrm.hxx:101
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:79
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:841
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:52
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:75
TextFrameIndex GetLen() const
Definition: porlin.hxx:77
bool IsMultiPortion() const
Definition: porlin.hxx:143
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:137
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
SwNode & GetPointNode() const
Definition: pam.hxx:283
SwNode & GetMarkNode() const
Definition: pam.hxx:284
const SwPosition * GetPoint() const
Definition: pam.hxx:261
A page of the document layout.
Definition: pagefrm.hxx:58
SwTwips Width() const
Definition: possiz.hxx:51
bool IsVert() const
Definition: frame.hxx:1366
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1381
tools::Long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1376
bool IsVertL2R() const
Definition: frame.hxx:1367
tools::Long YDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1422
tools::Long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1408
tools::Long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1377
void SetTop(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1385
void Refresh(const SwFrame *pFrame)
Definition: frame.hxx:1358
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1409
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Height(tools::Long nNew)
Definition: swrect.hxx:193
bool HasArea() const
Definition: swrect.hxx:300
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
void Right(const tools::Long nRight)
Definition: swrect.hxx:202
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:211
void Pos(const Point &rNew)
Definition: swrect.hxx:171
void SSize(const Size &rNew)
Definition: swrect.hxx:180
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
void Width(tools::Long nNew)
Definition: swrect.hxx:189
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:206
size_t size() const
Definition: sortedobjs.cxx:43
const SwLineLayout * CharCursorToLine(TextFrameIndex const nPos)
Definition: itrtxt.cxx:203
TextFrameIndex GetModelPositionForViewPoint(SwPosition *pPos, const Point &rPoint, bool bChgNode, SwCursorMoveState *=nullptr) const
Definition: itrcrsr.cxx:1324
void GetCharRect(SwRect *, TextFrameIndex, SwCursorMoveState *=nullptr, const tools::Long nMax=0)
Definition: itrcrsr.cxx:1226
void GetEndCharRect(SwRect *, TextFrameIndex, SwCursorMoveState *=nullptr, const tools::Long nMax=0)
Definition: itrcrsr.cxx:425
static bool IsRightMargin()
Definition: itrtxt.hxx:296
static void SetRightMargin(const bool bNew)
Definition: itrtxt.hxx:295
Represents the style of a paragraph.
Definition: fmtcol.hxx:59
SwTextFormatColl & GetNextTextFormatColl() const
Definition: fmtcol.hxx:104
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:165
SwTextFrame * GetFormatted(bool bForceQuickFormat=false)
In case the SwLineLayout was cleared out of the s_pTextCache, recreate it.
Definition: txtfrm.cxx:3396
SwTextFrame * GetFrameAtPos(const SwPosition &rPos)
Definition: frmcrsr.cxx:151
bool GetModelPositionForViewPoint_(SwPosition *pPos, const Point &rPoint, const bool bChgFrame, SwCursorMoveState *=nullptr) const
Definition: frmcrsr.cxx:549
SwDoc & GetDoc()
Definition: txtfrm.hxx:466
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout.
Definition: txtfrm.cxx:580
void PrepareVisualMove(TextFrameIndex &nPos, sal_uInt8 &nCursorLevel, bool &bRight, bool bInsertCursor)
Prepares the cursor position for a visual cursor move (BiDi).
Definition: frmcrsr.cxx:1045
virtual bool RightMargin(SwPaM *, bool bAPI=false) const override
Definition: frmcrsr.cxx:706
void SetOffset(TextFrameIndex nNewOfst)
Definition: txtfrm.hxx:871
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:861
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1246
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:444
bool HasPara() const
Definition: txtfrm.hxx:825
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:683
bool IsSwapped() const
Definition: txtfrm.hxx:541
virtual bool UnitDown(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const override
Definition: frmcrsr.cxx:1293
void SwitchRTLtoLTR(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from RTL to LTR layout.
Definition: txtfrm.hxx:741
bool GetAutoPos(SwRect &, const SwPosition &) const
A slimmer version of GetCharRect for autopositioning Frames.
Definition: frmcrsr.cxx:366
bool UnitUp_(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: frmcrsr.cxx:760
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:456
void SetPara(SwParaPortion *pNew, bool bDelete=true)
Definition: txtcache.cxx:129
bool GetKeyCursorOfst(SwPosition *pPos, const Point &rPoint) const
Makes sure that the Frame is not switched (e.g.
Definition: txtfrm.hxx:408
bool GetTopOfLine(SwTwips &_onTopOfLine, const SwPosition &_rPos) const
Determine top of line for given position in the text frame.
Definition: frmcrsr.cxx:453
bool IsLocked() const
Definition: txtfrm.hxx:523
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout.
Definition: txtfrm.cxx:473
tools::Long GetLineSpace(const bool _bNoPropLineSpacing=false) const
Returns the additional line spacing for the next paragraph.
Definition: txtfrm.cxx:3720
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1267
virtual bool LeftMargin(SwPaM *) const override
Layout oriented cursor travelling: Left border, right border, previous Line, following Line,...
Definition: frmcrsr.cxx:672
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1360
SwTextFrame & GetFrameAtOfst(TextFrameIndex nOfst)
Definition: frmcrsr.cxx:143
virtual bool GetCharRect(SwRect &rRect, const SwPosition &rPos, SwCursorMoveState *pCMS=nullptr, bool bAllowFarAway=true) const override
Returns the view rectangle for the rPos model position.
Definition: frmcrsr.cxx:178
friend bool sw_ChangeOffset(SwTextFrame *pFrame, TextFrameIndex nNew)
Definition: frmcrsr.cxx:108
virtual bool UnitUp(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const override
Definition: frmcrsr.cxx:1274
void SwapWidthAndHeight()
Swaps width and height of the text frame.
Definition: txtfrm.cxx:420
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1293
bool UnitDown_(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: frmcrsr.cxx:1149
void FillCursorPos(SwFillData &rFill) const
Definition: frmcrsr.cxx:1303
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1303
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
In nOffset returns the offset of the char within the set text buffer, which is closest to the positio...
Definition: frmcrsr.cxx:661
bool IsEmpty() const
Definition: txtfrm.hxx:527
const SwLineLayout * NextLine()
Definition: itrtxt.cxx:125
TextFrameIndex GetLength() const
Definition: itrtxt.hxx:86
TextFrameIndex GetEnd() const
Definition: itrtxt.hxx:89
SwTwips Y() const
Definition: itrtxt.hxx:90
const SwLineLayout * GetNext() const
Definition: itrtxt.hxx:84
TextFrameIndex GetStart() const
Definition: itrtxt.hxx:88
const SwLineLayout * PrevLine()
Definition: itrtxt.cxx:171
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:342
const SwLineLayout * GetPrevLine()
Definition: itrtxt.cxx:145
void Top()
Definition: itrtxt.hxx:99
SwTwips GetLineHeight() const
Definition: itrtxt.hxx:116
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
const SwLineLayout * Prev()
Definition: itrtxt.cxx:90
sal_uInt16 GetLineNr() const
Definition: itrtxt.hxx:87
const SwLineLayout * GetNextLine() const
Definition: itrtxt.cxx:135
const SwLineLayout * GetPrev()
Definition: itrtxt.cxx:83
sal_uInt16 GetDropLeft() const
Definition: itrtxt.hxx:204
sal_uInt16 GetDropLines() const
Definition: itrtxt.hxx:202
SwTwips FirstLeft() const
Definition: itrtxt.hxx:182
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:89
tools::Long GetLeftMarginWithNum(bool bTextLeft=false) const
Returns the additional indents of this text node and its numbering.
Definition: ndtxt.cxx:3246
bool GetFirstLineOfsWithNum(short &rFirstOffset) const
Returns the combined first line indent of this text node and its numbering.
Definition: ndtxt.cxx:3289
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:871
bool IsFirstMulti() const
Definition: inftxt.hxx:206
const OUString & GetText() const
Definition: inftxt.hxx:240
bool IsMulti() const
Definition: inftxt.hxx:204
bool IsPrtFormat() const
Definition: viewopt.hxx:541
bool getBrowseMode() const
Definition: viewopt.hxx:472
bool IsCursorInProtectedArea() const
Definition: viewopt.hxx:409
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:347
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:436
void InvalidateWindows(const SwRect &rRect)
Definition: viewsh.cxx:556
size_t size() const
Definition: ring.hxx:173
ring_container GetRingContainer()
Definition: ring.hxx:240
SwFillMode
Definition: crstate.hxx:29
@ Indent
by left paragraph indentation
@ Tab
default, fill with tabs
@ Margin
only align left, center, right
@ Space
fill with spaces
@ TabSpace
fill with spaces and tabs
@ SetOnlyText
stay with the cursor inside text
@ UpDown
Cursor Up/Down.
@ RightMargin
at right margin
#define MIN_OFFSET_STEP
Definition: frmcrsr.cxx:49
#define FILL_MIN_DIST
Definition: frmcrsr.cxx:519
bool sw_ChangeOffset(SwTextFrame *pFrame, TextFrameIndex nNew)
Definition: frmcrsr.cxx:108
static void lcl_VisualMoveRecursion(const SwLineLayout &rCurrLine, TextFrameIndex nIdx, TextFrameIndex &nPos, bool &bRight, sal_uInt8 &nCursorLevel, sal_uInt8 nDefaultDir)
Definition: frmcrsr.cxx:900
#define FAR_AWAY
Definition: frmtool.hxx:53
constexpr TypedWhichId< SvxTabStopItem > RES_PARATR_TABSTOP(68)
WhichRangesContainer const aTextFormatCollSetRange(svl::Items< RES_CHRATR_BEGIN, RES_CHRATR_END-1, RES_PARATR_BEGIN, RES_PARATR_END-1, RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_LEVEL, RES_FRMATR_BEGIN, RES_FRMATR_END-1, RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, XATTR_FILL_FIRST, XATTR_FILL_LAST >)
sal_uInt16 nPos
tools::Long const nRightMargin
double getLength(const B2DPolygon &rCandidate)
long Long
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
SwFillCursorPos * m_pFill
for automatic filling with tabs etc
Definition: crstate.hxx:134
bool m_bPosCorr
Point had to be corrected.
Definition: crstate.hxx:143
bool m_b2Lines
Check 2line portions and fill p2Lines.
Definition: crstate.hxx:150
bool m_bNoScroll
No scrolling of undersized textframes.
Definition: crstate.hxx:151
CursorMoveState m_eState
Definition: crstate.hxx:138
bool m_bRealHeight
should the real height be calculated?
Definition: crstate.hxx:141
std::unique_ptr< Sw2LinesPos > m_p2Lines
for selections inside/around 2line portions
Definition: crstate.hxx:135
bool m_bFieldInfo
should be fields recognized?
Definition: crstate.hxx:142
Point m_aRealHeight
contains then the position/height of the cursor
Definition: crstate.hxx:137
sal_uInt16 nColumnCnt
number of necessary column breaks
Definition: crstate.hxx:44
SwFillMode eMode
desired fill-up rule
Definition: crstate.hxx:46
sal_Int16 eOrient
paragraph alignment
Definition: crstate.hxx:45
sal_uInt16 nSpaceOnlyCnt
number of spaces to insert ("only spaces, no tabs" mode)
Definition: crstate.hxx:43
SwRect aCursor
position and size of the ShadowCursor
Definition: crstate.hxx:39
sal_uInt16 nSpaceCnt
number of spaces to insert
Definition: crstate.hxx:42
sal_uInt16 nTabCnt
number of tabs respectively size of indentation
Definition: crstate.hxx:41
sal_uInt16 nParaCnt
number of paragraphs to insert
Definition: crstate.hxx:40
bool bFirstLine
Definition: frmcrsr.cxx:528
SwTwips nLineWidth
Definition: frmcrsr.cxx:527
tools::Long Y() const
Definition: frmcrsr.cxx:538
void SetSpace(sal_uInt16 nNew)
Definition: frmcrsr.cxx:544
SwFillMode Mode() const
Definition: frmcrsr.cxx:536
bool bInner
Definition: frmcrsr.cxx:529
bool bEmpty
Definition: frmcrsr.cxx:531
SwRect aFrame
Definition: frmcrsr.cxx:523
void SetSpaceOnly(sal_uInt16 nNew)
Definition: frmcrsr.cxx:545
tools::Long X() const
Definition: frmcrsr.cxx:537
const SwCursorMoveState * pCMS
Definition: frmcrsr.cxx:524
SwPosition * pPos
Definition: frmcrsr.cxx:525
SwFillCursorPos & Fill() const
Definition: frmcrsr.cxx:542
const Point & rPoint
Definition: frmcrsr.cxx:526
void SetOrient(const sal_Int16 eNew)
Definition: frmcrsr.cxx:546
bool bColumn
Definition: frmcrsr.cxx:530
tools::Long Bottom() const
Definition: frmcrsr.cxx:541
SwFillData(const SwCursorMoveState *pC, SwPosition *pP, const SwRect &rR, const Point &rPt)
Definition: frmcrsr.cxx:532
void SetTab(sal_uInt16 nNew)
Definition: frmcrsr.cxx:543
tools::Long Left() const
Definition: frmcrsr.cxx:539
tools::Long Right() const
Definition: frmcrsr.cxx:540
Marks a position in the document model.
Definition: pam.hxx:37
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:77
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
tools::Long SwTwips
Definition: swtypes.hxx:51
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
oslFileHandle & pOut