update dev300-m58
[ooovba.git] / sw / source / core / text / itrtxt.cxx
blob5919ff1b1a2fbf97ff915ffdcbd7636ca26fc707
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itrtxt.cxx,v $
10 * $Revision: 1.34 $
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"
35 #include "ndtxt.hxx"
36 #include "flyfrm.hxx"
37 #include "paratr.hxx"
38 #include "errhdl.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>
46 #include <porfld.hxx>
48 #include "txtcfg.hxx"
49 #include "itrtxt.hxx"
50 #include "txtfrm.hxx"
51 #include "porfly.hxx"
53 #if OSL_DEBUG_LEVEL > 1
54 # include "txtfrm.hxx" // GetFrmID,
55 #endif
57 /*************************************************************************
58 * SwTxtIter::CtorInitTxtIter()
59 *************************************************************************/
61 void SwTxtIter::CtorInitTxtIter( SwTxtFrm *pNewFrm, SwTxtInfo *pNewInf )
63 #ifdef DBGTXT
64 // nStopAt laesst sich vom CV bearbeiten.
65 static MSHORT nStopAt = 0;
66 if( nStopAt == pNewFrm->GetFrmId() )
68 int i = pNewFrm->GetFrmId();
70 #endif
72 SwTxtNode *pNode = pNewFrm->GetTxtNode();
74 ASSERT( pNewFrm->GetPara(), "No paragraph" );
76 CtorInitAttrIter( *pNode, pNewFrm->GetPara()->GetScriptInfo(), pNewFrm );
78 pFrm = pNewFrm;
79 pInf = pNewInf;
80 // --> OD 2008-01-17 #newlistlevelattrs#
81 aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
82 // <--
83 nFrameStart = pFrm->Frm().Pos().Y() + pFrm->Prt().Pos().Y();
84 SwTxtIter::Init();
85 if( pNode->GetSwAttrSet().GetRegister().GetValue() )
86 bRegisterOn = pFrm->FillRegister( nRegStart, nRegDiff );
87 else
88 bRegisterOn = sal_False;
91 /*************************************************************************
92 * SwTxtIter::Init()
93 *************************************************************************/
95 void SwTxtIter::Init()
97 pCurr = pInf->GetParaPortion();
98 nStart = pInf->GetTxtStart();
99 nY = nFrameStart;
100 bPrev = sal_True;
101 pPrev = 0;
102 nLineNr = 1;
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()
121 pPrev = 0;
122 bPrev = sal_True;
123 SwLineLayout *pLay = pInf->GetParaPortion();
124 if( pCurr == pLay )
125 return 0;
126 while( pLay->GetNext() != pCurr )
127 pLay = pLay->GetNext();
128 return pPrev = pLay;
131 /*************************************************************************
132 * SwTxtIter::GetPrev()
133 *************************************************************************/
135 const SwLineLayout *SwTxtIter::GetPrev()
137 if(! bPrev)
138 _GetPrev();
139 return pPrev;
142 /*************************************************************************
143 * SwTxtIter::Prev()
144 *************************************************************************/
146 const SwLineLayout *SwTxtIter::Prev()
148 if( !bPrev )
149 _GetPrev();
150 if( pPrev )
152 bPrev = sal_False;
153 pCurr = pPrev;
154 nStart = nStart - pCurr->GetLen();
155 nY = nY - GetLineHeight();
156 if( !pCurr->IsDummy() && !(--nLineNr) )
157 ++nLineNr;
158 return pCurr;
160 else
161 return 0;
164 /*************************************************************************
165 * SwTxtIter::Next()
166 *************************************************************************/
168 const SwLineLayout *SwTxtIter::Next()
170 if(pCurr->GetNext())
172 pPrev = pCurr;
173 bPrev = sal_True;
174 nStart = nStart + pCurr->GetLen();
175 nY += GetLineHeight();
176 if( pCurr->GetLen() || ( nLineNr>1 && !pCurr->IsDummy() ) )
177 ++nLineNr;
178 return pCurr = pCurr->GetNext();
180 else
181 return 0;
184 /*************************************************************************
185 * SwTxtIter::NextLine()
186 *************************************************************************/
188 const SwLineLayout *SwTxtIter::NextLine()
190 const SwLineLayout *pNext = Next();
191 while( pNext && pNext->IsDummy() && pNext->GetNext() )
193 DBG_LOOP;
194 pNext = Next();
196 return pNext;
199 /*************************************************************************
200 * SwTxtIter::GetNextLine()
201 *************************************************************************/
203 const SwLineLayout *SwTxtIter::GetNextLine() const
205 const SwLineLayout *pNext = pCurr->GetNext();
206 while( pNext && pNext->IsDummy() && pNext->GetNext() )
208 DBG_LOOP;
209 pNext = pNext->GetNext();
211 return (SwLineLayout*)pNext;
214 /*************************************************************************
215 * SwTxtIter::GetPrevLine()
216 *************************************************************************/
218 const SwLineLayout *SwTxtIter::GetPrevLine()
220 const SwLineLayout *pRoot = pInf->GetParaPortion();
221 if( pRoot == pCurr )
222 return 0;
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() )
235 pLay = pTmp;
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();
251 if( !pMyPrev )
252 return 0;
254 const SwLineLayout *pLast = pMyPrev;
255 while( pMyPrev && pMyPrev->IsDummy() )
257 DBG_LOOP;
258 pLast = pMyPrev;
259 pMyPrev = Prev();
261 return (SwLineLayout*)(pMyPrev ? pMyPrev : pLast);
264 /*************************************************************************
265 * SwTxtIter::Bottom()
266 *************************************************************************/
268 void SwTxtIter::Bottom()
270 while( Next() )
272 DBG_LOOP;
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() &&
299 GetPrev()->GetLen();
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
314 if ( pPor )
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();
325 if ( bHasGrid )
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;
334 else
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.
346 //for text refactor
347 const USHORT nLineNetto = rLine.Height() - nRubyHeight;
348 //const USHORT nLineNetto = ( nPorHeight > nGridWidth ) ?
349 // rLine.Height() - nRubyHeight :
350 // nGridWidth;
351 nOfst += ( nLineNetto - nPorHeight ) / 2;
352 if ( bRubyTop )
353 nOfst = nOfst + nRubyHeight;
357 else
359 switch ( GetLineInfo().GetVertAlign() ) {
360 case SvxParaVertAlignItem::TOP :
361 nOfst = nOfst + nPorAscent;
362 break;
363 case SvxParaVertAlignItem::CENTER :
364 ASSERT( rLine.Height() >= nPorHeight, "Portion height > Line height");
365 nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
366 break;
367 case SvxParaVertAlignItem::BOTTOM :
368 nOfst += rLine.Height() - nPorHeight + nPorAscent;
369 break;
370 case SvxParaVertAlignItem::AUTOMATIC :
371 if ( bAutoToCentered || GetInfo().GetTxtFrm()->IsVertical() )
373 nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
374 break;
376 case SvxParaVertAlignItem::BASELINE :
377 // base line
378 nOfst = nOfst + rLine.GetAscent();
379 break;
383 return nOfst;
386 /*************************************************************************
387 * SwTxtIter::TwipsToLine()
388 *************************************************************************/
390 const SwLineLayout *SwTxtIter::TwipsToLine( const SwTwips y)
392 while( nY + GetLineHeight() <= y && Next() )
394 while( nY > y && Prev() )
396 return pCurr;
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() )
410 break;
411 pPor = pPor->GetPortion();
413 return bRet;
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();
425 if( pDel )
427 pCurr->SetNext( 0 );
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
442 while ( pLine )
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 );
465 delete pDel;
467 if( pCurr->IsDummy() &&
468 !pCurr->GetLen() &&
469 nStart < GetTxtFrm()->GetTxt().Len() )
470 pCurr->SetRealHeight( 1 );
471 if( GetHints() )
472 pFrm->RemoveFtn( nEnd );
475 /*************************************************************************
476 * SwTxtIter::CntHyphens()
477 *************************************************************************/
479 void SwTxtIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
481 nEndCnt = 0;
482 nMidCnt = 0;
483 if ( bPrev && pPrev && !pPrev->IsEndHyph() && !pPrev->IsMidHyph() )
484 return;
485 SwLineLayout *pLay = pInf->GetParaPortion();
486 if( pCurr == pLay )
487 return;
488 while( pLay != pCurr )
490 DBG_LOOP;
491 if ( pLay->IsEndHyph() )
492 nEndCnt++;
493 else
494 nEndCnt = 0;
495 if ( pLay->IsMidHyph() )
496 nMidCnt++;
497 else
498 nMidCnt = 0;
499 pLay = pLay->GetNext();
503 /*************************************************************************
504 * SwHookOut
506 * Change current output device to formatting device, this has to be done before
507 * formatting.
508 *************************************************************************/
510 SwHookOut::SwHookOut( SwTxtSizeInfo& rInfo ) :
511 pInf( &rInfo ),
512 pOut( rInfo.GetOut() ),
513 bOnWin( rInfo.OnWin() )
515 ASSERT( rInfo.GetRefDev(), "No reference device for text formatting" )
517 // set new values
518 rInfo.SetOut( rInfo.GetRefDev() );
519 rInfo.SetOnWin( sal_False );
522 SwHookOut::~SwHookOut()
524 pInf->SetOut( pOut );
525 pInf->SetOnWin( bOnWin );