1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itrtxt.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
39 #include <vcl/outdev.hxx>
40 #include <svx/paravertalignitem.hxx>
42 #include "pormulti.hxx"
43 #include <pagefrm.hxx>
44 #include <pagedesc.hxx> // SwPageDesc
45 #include <tgrditem.hxx>
53 #if OSL_DEBUG_LEVEL > 1
54 # include "txtfrm.hxx" // GetFrmID,
57 /*************************************************************************
58 * SwTxtIter::CtorInitTxtIter()
59 *************************************************************************/
61 void SwTxtIter::CtorInitTxtIter( SwTxtFrm
*pNewFrm
, SwTxtInfo
*pNewInf
)
64 // nStopAt laesst sich vom CV bearbeiten.
65 static MSHORT nStopAt
= 0;
66 if( nStopAt
== pNewFrm
->GetFrmId() )
68 int i
= pNewFrm
->GetFrmId();
72 SwTxtNode
*pNode
= pNewFrm
->GetTxtNode();
74 ASSERT( pNewFrm
->GetPara(), "No paragraph" );
76 CtorInitAttrIter( *pNode
, pNewFrm
->GetPara()->GetScriptInfo(), pNewFrm
);
80 // --> OD 2008-01-17 #newlistlevelattrs#
81 aLineInf
.CtorInitLineInfo( pNode
->GetSwAttrSet(), *pNode
);
83 nFrameStart
= pFrm
->Frm().Pos().Y() + pFrm
->Prt().Pos().Y();
85 if( pNode
->GetSwAttrSet().GetRegister().GetValue() )
86 bRegisterOn
= pFrm
->FillRegister( nRegStart
, nRegDiff
);
88 bRegisterOn
= sal_False
;
91 /*************************************************************************
93 *************************************************************************/
95 void SwTxtIter::Init()
97 pCurr
= pInf
->GetParaPortion();
98 nStart
= pInf
->GetTxtStart();
105 /*************************************************************************
106 * SwTxtIter::_GetHeightAndAscent()
107 *************************************************************************/
109 void SwTxtIter::CalcAscentAndHeight( KSHORT
&rAscent
, KSHORT
&rHeight
) const
111 rHeight
= GetLineHeight();
112 rAscent
= pCurr
->GetAscent() + rHeight
- pCurr
->Height();
115 /*************************************************************************
116 * SwTxtIter::_GetPrev()
117 *************************************************************************/
119 SwLineLayout
*SwTxtIter::_GetPrev()
123 SwLineLayout
*pLay
= pInf
->GetParaPortion();
126 while( pLay
->GetNext() != pCurr
)
127 pLay
= pLay
->GetNext();
131 /*************************************************************************
132 * SwTxtIter::GetPrev()
133 *************************************************************************/
135 const SwLineLayout
*SwTxtIter::GetPrev()
142 /*************************************************************************
144 *************************************************************************/
146 const SwLineLayout
*SwTxtIter::Prev()
154 nStart
= nStart
- pCurr
->GetLen();
155 nY
= nY
- GetLineHeight();
156 if( !pCurr
->IsDummy() && !(--nLineNr
) )
164 /*************************************************************************
166 *************************************************************************/
168 const SwLineLayout
*SwTxtIter::Next()
174 nStart
= nStart
+ pCurr
->GetLen();
175 nY
+= GetLineHeight();
176 if( pCurr
->GetLen() || ( nLineNr
>1 && !pCurr
->IsDummy() ) )
178 return pCurr
= pCurr
->GetNext();
184 /*************************************************************************
185 * SwTxtIter::NextLine()
186 *************************************************************************/
188 const SwLineLayout
*SwTxtIter::NextLine()
190 const SwLineLayout
*pNext
= Next();
191 while( pNext
&& pNext
->IsDummy() && pNext
->GetNext() )
199 /*************************************************************************
200 * SwTxtIter::GetNextLine()
201 *************************************************************************/
203 const SwLineLayout
*SwTxtIter::GetNextLine() const
205 const SwLineLayout
*pNext
= pCurr
->GetNext();
206 while( pNext
&& pNext
->IsDummy() && pNext
->GetNext() )
209 pNext
= pNext
->GetNext();
211 return (SwLineLayout
*)pNext
;
214 /*************************************************************************
215 * SwTxtIter::GetPrevLine()
216 *************************************************************************/
218 const SwLineLayout
*SwTxtIter::GetPrevLine()
220 const SwLineLayout
*pRoot
= pInf
->GetParaPortion();
223 const SwLineLayout
*pLay
= pRoot
;
225 while( pLay
->GetNext() != pCurr
)
226 pLay
= pLay
->GetNext();
228 if( pLay
->IsDummy() )
230 const SwLineLayout
*pTmp
= pRoot
;
231 pLay
= pRoot
->IsDummy() ? 0 : pRoot
;
232 while( pTmp
->GetNext() != pCurr
)
234 if( !pTmp
->IsDummy() )
236 pTmp
= pTmp
->GetNext();
240 // Wenn sich nichts getan hat, dann gibt es nur noch Dummys
241 return (SwLineLayout
*)pLay
;
244 /*************************************************************************
245 * SwTxtIter::PrevLine()
246 *************************************************************************/
248 const SwLineLayout
*SwTxtIter::PrevLine()
250 const SwLineLayout
*pMyPrev
= Prev();
254 const SwLineLayout
*pLast
= pMyPrev
;
255 while( pMyPrev
&& pMyPrev
->IsDummy() )
261 return (SwLineLayout
*)(pMyPrev
? pMyPrev
: pLast
);
264 /*************************************************************************
265 * SwTxtIter::Bottom()
266 *************************************************************************/
268 void SwTxtIter::Bottom()
276 /*************************************************************************
277 * SwTxtIter::CharToLine()
278 *************************************************************************/
280 void SwTxtIter::CharToLine(const xub_StrLen nChar
)
282 while( nStart
+ pCurr
->GetLen() <= nChar
&& Next() )
284 while( nStart
> nChar
&& Prev() )
288 /*************************************************************************
289 * SwTxtIter::CharCrsrToLine()
290 *************************************************************************/
292 // 1170: beruecksichtigt Mehrdeutigkeiten:
293 const SwLineLayout
*SwTxtCursor::CharCrsrToLine( const xub_StrLen nPosition
)
295 CharToLine( nPosition
);
296 if( nPosition
!= nStart
)
297 bRightMargin
= sal_False
;
298 sal_Bool bPrevious
= bRightMargin
&& pCurr
->GetLen() && GetPrev() &&
300 if( bPrevious
&& nPosition
&& CH_BREAK
== GetInfo().GetChar( nPosition
-1 ) )
301 bPrevious
= sal_False
;
302 return bPrevious
? PrevLine() : pCurr
;
305 /*************************************************************************
306 * SwTxtCrsr::AdjustBaseLine()
307 *************************************************************************/
309 USHORT
SwTxtCursor::AdjustBaseLine( const SwLineLayout
& rLine
,
310 const SwLinePortion
* pPor
,
311 USHORT nPorHeight
, USHORT nPorAscent
,
312 const sal_Bool bAutoToCentered
) const
316 nPorHeight
= pPor
->Height();
317 nPorAscent
= pPor
->GetAscent();
320 USHORT nOfst
= rLine
.GetRealHeight() - rLine
.Height();
322 GETGRID( pFrm
->FindPageFrm() )
323 const sal_Bool bHasGrid
= pGrid
&& GetInfo().SnapToGrid();
327 const USHORT nRubyHeight
= pGrid
->GetRubyHeight();
328 const sal_Bool bRubyTop
= ! pGrid
->GetRubyTextBelow();
330 if ( GetInfo().IsMulti() )
331 // we are inside the GetCharRect recursion for multi portions
332 // we center the portion in its surrounding line
333 nOfst
= ( pCurr
->Height() - nPorHeight
) / 2 + nPorAscent
;
336 // We have to take care for ruby portions.
337 // The ruby portion is NOT centered
338 nOfst
= nOfst
+ nPorAscent
;
340 if ( ! pPor
|| ! pPor
->IsMultiPortion() ||
341 ! ((SwMultiPortion
*)pPor
)->IsRuby() )
343 // Portions which are bigger than on grid distance are
344 // centered inside the whole line.
347 const USHORT nLineNetto
= rLine
.Height() - nRubyHeight
;
348 //const USHORT nLineNetto = ( nPorHeight > nGridWidth ) ?
349 // rLine.Height() - nRubyHeight :
351 nOfst
+= ( nLineNetto
- nPorHeight
) / 2;
353 nOfst
= nOfst
+ nRubyHeight
;
359 switch ( GetLineInfo().GetVertAlign() ) {
360 case SvxParaVertAlignItem::TOP
:
361 nOfst
= nOfst
+ nPorAscent
;
363 case SvxParaVertAlignItem::CENTER
:
364 ASSERT( rLine
.Height() >= nPorHeight
, "Portion height > Line height");
365 nOfst
+= ( rLine
.Height() - nPorHeight
) / 2 + nPorAscent
;
367 case SvxParaVertAlignItem::BOTTOM
:
368 nOfst
+= rLine
.Height() - nPorHeight
+ nPorAscent
;
370 case SvxParaVertAlignItem::AUTOMATIC
:
371 if ( bAutoToCentered
|| GetInfo().GetTxtFrm()->IsVertical() )
373 nOfst
+= ( rLine
.Height() - nPorHeight
) / 2 + nPorAscent
;
376 case SvxParaVertAlignItem::BASELINE
:
378 nOfst
= nOfst
+ rLine
.GetAscent();
386 /*************************************************************************
387 * SwTxtIter::TwipsToLine()
388 *************************************************************************/
390 const SwLineLayout
*SwTxtIter::TwipsToLine( const SwTwips y
)
392 while( nY
+ GetLineHeight() <= y
&& Next() )
394 while( nY
> y
&& Prev() )
400 // Local helper function to check, if pCurr needs a field rest portion:
402 sal_Bool
lcl_NeedsFieldRest( const SwLineLayout
* pCurr
)
404 const SwLinePortion
*pPor
= pCurr
->GetPortion();
405 sal_Bool bRet
= sal_False
;
406 while( pPor
&& !bRet
)
408 bRet
= pPor
->InFldGrp() && ((SwFldPortion
*)pPor
)->HasFollow();
409 if( !pPor
->GetPortion() || !pPor
->GetPortion()->InFldGrp() )
411 pPor
= pPor
->GetPortion();
416 /*************************************************************************
417 * SwTxtIter::TruncLines()
418 *************************************************************************/
420 void SwTxtIter::TruncLines( sal_Bool bNoteFollow
)
422 SwLineLayout
*pDel
= pCurr
->GetNext();
423 const xub_StrLen nEnd
= nStart
+ pCurr
->GetLen();
428 if( GetHints() && bNoteFollow
)
430 GetInfo().GetParaPortion()->SetFollowField( pDel
->IsRest() ||
431 lcl_NeedsFieldRest( pCurr
) );
433 // bug 88534: wrong positioning of flys
434 SwTxtFrm
* pFollow
= GetTxtFrm()->GetFollow();
435 if ( pFollow
&& ! pFollow
->IsLocked() &&
436 nEnd
== pFollow
->GetOfst() )
438 xub_StrLen nRangeEnd
= nEnd
;
439 SwLineLayout
* pLine
= pDel
;
441 // determine range to be searched for flys anchored as characters
444 nRangeEnd
= nRangeEnd
+ pLine
->GetLen();
445 pLine
= pLine
->GetNext();
448 SwpHints
* pTmpHints
= GetTxtFrm()->GetTxtNode()->GetpSwpHints();
450 // examine hints in range nEnd - (nEnd + nRangeChar)
451 for( USHORT i
= 0; i
< pTmpHints
->Count(); i
++ )
453 const SwTxtAttr
* pHt
= pTmpHints
->GetTextHint( i
);
454 if( RES_TXTATR_FLYCNT
== pHt
->Which() )
456 // check, if hint is in our range
457 const USHORT nTmpPos
= *pHt
->GetStart();
458 if ( nEnd
<= nTmpPos
&& nTmpPos
< nRangeEnd
)
459 pFollow
->_InvalidateRange(
460 SwCharRange( nTmpPos
, nTmpPos
), 0 );
467 if( pCurr
->IsDummy() &&
469 nStart
< GetTxtFrm()->GetTxt().Len() )
470 pCurr
->SetRealHeight( 1 );
472 pFrm
->RemoveFtn( nEnd
);
475 /*************************************************************************
476 * SwTxtIter::CntHyphens()
477 *************************************************************************/
479 void SwTxtIter::CntHyphens( sal_uInt8
&nEndCnt
, sal_uInt8
&nMidCnt
) const
483 if ( bPrev
&& pPrev
&& !pPrev
->IsEndHyph() && !pPrev
->IsMidHyph() )
485 SwLineLayout
*pLay
= pInf
->GetParaPortion();
488 while( pLay
!= pCurr
)
491 if ( pLay
->IsEndHyph() )
495 if ( pLay
->IsMidHyph() )
499 pLay
= pLay
->GetNext();
503 /*************************************************************************
506 * Change current output device to formatting device, this has to be done before
508 *************************************************************************/
510 SwHookOut::SwHookOut( SwTxtSizeInfo
& rInfo
) :
512 pOut( rInfo
.GetOut() ),
513 bOnWin( rInfo
.OnWin() )
515 ASSERT( rInfo
.GetRefDev(), "No reference device for text formatting" )
518 rInfo
.SetOut( rInfo
.GetRefDev() );
519 rInfo
.SetOnWin( sal_False
);
522 SwHookOut::~SwHookOut()
524 pInf
->SetOut( pOut
);
525 pInf
->SetOnWin( bOnWin
);