summaryrefslogtreecommitdiff
path: root/sw/source/core/text/itrtxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/itrtxt.cxx')
-rw-r--r--sw/source/core/text/itrtxt.cxx513
1 files changed, 513 insertions, 0 deletions
diff --git a/sw/source/core/text/itrtxt.cxx b/sw/source/core/text/itrtxt.cxx
new file mode 100644
index 000000000000..93cba310f3be
--- /dev/null
+++ b/sw/source/core/text/itrtxt.cxx
@@ -0,0 +1,513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "ndtxt.hxx"
+#include "flyfrm.hxx"
+#include "paratr.hxx"
+#include <vcl/outdev.hxx>
+#include <editeng/paravertalignitem.hxx>
+
+#include "pormulti.hxx"
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <porfld.hxx>
+
+#include "itrtxt.hxx"
+#include "txtfrm.hxx"
+#include "porfly.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include "txtfrm.hxx" // GetFrmID,
+#endif
+
+/*************************************************************************
+ * SwTxtIter::CtorInitTxtIter()
+ *************************************************************************/
+
+void SwTxtIter::CtorInitTxtIter( SwTxtFrm *pNewFrm, SwTxtInfo *pNewInf )
+{
+ SwTxtNode *pNode = pNewFrm->GetTxtNode();
+
+ OSL_ENSURE( pNewFrm->GetPara(), "No paragraph" );
+
+ CtorInitAttrIter( *pNode, pNewFrm->GetPara()->GetScriptInfo(), pNewFrm );
+
+ pFrm = pNewFrm;
+ pInf = pNewInf;
+ aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
+ nFrameStart = pFrm->Frm().Pos().Y() + pFrm->Prt().Pos().Y();
+ SwTxtIter::Init();
+ if( pNode->GetSwAttrSet().GetRegister().GetValue() )
+ bRegisterOn = pFrm->FillRegister( nRegStart, nRegDiff );
+ else
+ bRegisterOn = sal_False;
+}
+
+/*************************************************************************
+ * SwTxtIter::Init()
+ *************************************************************************/
+
+void SwTxtIter::Init()
+{
+ pCurr = pInf->GetParaPortion();
+ nStart = pInf->GetTxtStart();
+ nY = nFrameStart;
+ bPrev = sal_True;
+ pPrev = 0;
+ nLineNr = 1;
+}
+
+/*************************************************************************
+ * SwTxtIter::_GetHeightAndAscent()
+ *************************************************************************/
+
+void SwTxtIter::CalcAscentAndHeight( KSHORT &rAscent, KSHORT &rHeight ) const
+{
+ rHeight = GetLineHeight();
+ rAscent = pCurr->GetAscent() + rHeight - pCurr->Height();
+}
+
+/*************************************************************************
+ * SwTxtIter::_GetPrev()
+ *************************************************************************/
+
+SwLineLayout *SwTxtIter::_GetPrev()
+{
+ pPrev = 0;
+ bPrev = sal_True;
+ SwLineLayout *pLay = pInf->GetParaPortion();
+ if( pCurr == pLay )
+ return 0;
+ while( pLay->GetNext() != pCurr )
+ pLay = pLay->GetNext();
+ return pPrev = pLay;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetPrev()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetPrev()
+{
+ if(! bPrev)
+ _GetPrev();
+ return pPrev;
+}
+
+/*************************************************************************
+ * SwTxtIter::Prev()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::Prev()
+{
+ if( !bPrev )
+ _GetPrev();
+ if( pPrev )
+ {
+ bPrev = sal_False;
+ pCurr = pPrev;
+ nStart = nStart - pCurr->GetLen();
+ nY = nY - GetLineHeight();
+ if( !pCurr->IsDummy() && !(--nLineNr) )
+ ++nLineNr;
+ return pCurr;
+ }
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtIter::Next()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::Next()
+{
+ if(pCurr->GetNext())
+ {
+ pPrev = pCurr;
+ bPrev = sal_True;
+ nStart = nStart + pCurr->GetLen();
+ nY += GetLineHeight();
+ if( pCurr->GetLen() || ( nLineNr>1 && !pCurr->IsDummy() ) )
+ ++nLineNr;
+ return pCurr = pCurr->GetNext();
+ }
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtIter::NextLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::NextLine()
+{
+ const SwLineLayout *pNext = Next();
+ while( pNext && pNext->IsDummy() && pNext->GetNext() )
+ {
+ pNext = Next();
+ }
+ return pNext;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetNextLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetNextLine() const
+{
+ const SwLineLayout *pNext = pCurr->GetNext();
+ while( pNext && pNext->IsDummy() && pNext->GetNext() )
+ {
+ pNext = pNext->GetNext();
+ }
+ return (SwLineLayout*)pNext;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetPrevLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetPrevLine()
+{
+ const SwLineLayout *pRoot = pInf->GetParaPortion();
+ if( pRoot == pCurr )
+ return 0;
+ const SwLineLayout *pLay = pRoot;
+
+ while( pLay->GetNext() != pCurr )
+ pLay = pLay->GetNext();
+
+ if( pLay->IsDummy() )
+ {
+ const SwLineLayout *pTmp = pRoot;
+ pLay = pRoot->IsDummy() ? 0 : pRoot;
+ while( pTmp->GetNext() != pCurr )
+ {
+ if( !pTmp->IsDummy() )
+ pLay = pTmp;
+ pTmp = pTmp->GetNext();
+ }
+ }
+
+ // Wenn sich nichts getan hat, dann gibt es nur noch Dummys
+ return (SwLineLayout*)pLay;
+}
+
+/*************************************************************************
+ * SwTxtIter::PrevLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::PrevLine()
+{
+ const SwLineLayout *pMyPrev = Prev();
+ if( !pMyPrev )
+ return 0;
+
+ const SwLineLayout *pLast = pMyPrev;
+ while( pMyPrev && pMyPrev->IsDummy() )
+ {
+ pLast = pMyPrev;
+ pMyPrev = Prev();
+ }
+ return (SwLineLayout*)(pMyPrev ? pMyPrev : pLast);
+}
+
+/*************************************************************************
+ * SwTxtIter::Bottom()
+ *************************************************************************/
+
+void SwTxtIter::Bottom()
+{
+ while( Next() )
+ {
+ // nothing
+ }
+}
+
+/*************************************************************************
+ * SwTxtIter::CharToLine()
+ *************************************************************************/
+
+void SwTxtIter::CharToLine(const xub_StrLen nChar)
+{
+ while( nStart + pCurr->GetLen() <= nChar && Next() )
+ ;
+ while( nStart > nChar && Prev() )
+ ;
+}
+
+/*************************************************************************
+ * SwTxtIter::CharCrsrToLine()
+ *************************************************************************/
+
+// 1170: beruecksichtigt Mehrdeutigkeiten:
+const SwLineLayout *SwTxtCursor::CharCrsrToLine( const xub_StrLen nPosition )
+{
+ CharToLine( nPosition );
+ if( nPosition != nStart )
+ bRightMargin = sal_False;
+ sal_Bool bPrevious = bRightMargin && pCurr->GetLen() && GetPrev() &&
+ GetPrev()->GetLen();
+ if( bPrevious && nPosition && CH_BREAK == GetInfo().GetChar( nPosition-1 ) )
+ bPrevious = sal_False;
+ return bPrevious ? PrevLine() : pCurr;
+}
+
+/*************************************************************************
+ * SwTxtCrsr::AdjustBaseLine()
+ *************************************************************************/
+
+sal_uInt16 SwTxtCursor::AdjustBaseLine( const SwLineLayout& rLine,
+ const SwLinePortion* pPor,
+ sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
+ const sal_Bool bAutoToCentered ) const
+{
+ if ( pPor )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+
+ sal_uInt16 nOfst = rLine.GetRealHeight() - rLine.Height();
+
+ GETGRID( pFrm->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
+
+ if ( bHasGrid )
+ {
+ const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
+ const sal_Bool bRubyTop = ! pGrid->GetRubyTextBelow();
+
+ if ( GetInfo().IsMulti() )
+ // we are inside the GetCharRect recursion for multi portions
+ // we center the portion in its surrounding line
+ nOfst = ( pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
+ else
+ {
+ // We have to take care for ruby portions.
+ // The ruby portion is NOT centered
+ nOfst = nOfst + nPorAscent;
+
+ if ( ! pPor || ! pPor->IsMultiPortion() ||
+ ! ((SwMultiPortion*)pPor)->IsRuby() )
+ {
+ // Portions which are bigger than on grid distance are
+ // centered inside the whole line.
+
+ //for text refactor
+ const sal_uInt16 nLineNetto = rLine.Height() - nRubyHeight;
+ //const sal_uInt16 nLineNetto = ( nPorHeight > nGridWidth ) ?
+ // rLine.Height() - nRubyHeight :
+ // nGridWidth;
+ nOfst += ( nLineNetto - nPorHeight ) / 2;
+ if ( bRubyTop )
+ nOfst = nOfst + nRubyHeight;
+ }
+ }
+ }
+ else
+ {
+ switch ( GetLineInfo().GetVertAlign() ) {
+ case SvxParaVertAlignItem::TOP :
+ nOfst = nOfst + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::CENTER :
+ OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
+ nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::BOTTOM :
+ nOfst += rLine.Height() - nPorHeight + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::AUTOMATIC :
+ if ( bAutoToCentered || GetInfo().GetTxtFrm()->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( GetInfo().GetTxtFrm()->IsVertLR() )
+ nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
+ else
+ nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
+ break;
+ }
+ case SvxParaVertAlignItem::BASELINE :
+ // base line
+ nOfst = nOfst + rLine.GetAscent();
+ break;
+ }
+ }
+
+ return nOfst;
+}
+
+/*************************************************************************
+ * SwTxtIter::TwipsToLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::TwipsToLine( const SwTwips y)
+{
+ while( nY + GetLineHeight() <= y && Next() )
+ ;
+ while( nY > y && Prev() )
+ ;
+ return pCurr;
+}
+
+//
+// Local helper function to check, if pCurr needs a field rest portion:
+//
+sal_Bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
+{
+ const SwLinePortion *pPor = pCurr->GetPortion();
+ sal_Bool bRet = sal_False;
+ while( pPor && !bRet )
+ {
+ bRet = pPor->InFldGrp() && ((SwFldPortion*)pPor)->HasFollow();
+ if( !pPor->GetPortion() || !pPor->GetPortion()->InFldGrp() )
+ break;
+ pPor = pPor->GetPortion();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtIter::TruncLines()
+ *************************************************************************/
+
+void SwTxtIter::TruncLines( sal_Bool bNoteFollow )
+{
+ SwLineLayout *pDel = pCurr->GetNext();
+ const xub_StrLen nEnd = nStart + pCurr->GetLen();
+
+ if( pDel )
+ {
+ pCurr->SetNext( 0 );
+ if( GetHints() && bNoteFollow )
+ {
+ GetInfo().GetParaPortion()->SetFollowField( pDel->IsRest() ||
+ lcl_NeedsFieldRest( pCurr ) );
+
+ // bug 88534: wrong positioning of flys
+ SwTxtFrm* pFollow = GetTxtFrm()->GetFollow();
+ if ( pFollow && ! pFollow->IsLocked() &&
+ nEnd == pFollow->GetOfst() )
+ {
+ xub_StrLen nRangeEnd = nEnd;
+ SwLineLayout* pLine = pDel;
+
+ // determine range to be searched for flys anchored as characters
+ while ( pLine )
+ {
+ nRangeEnd = nRangeEnd + pLine->GetLen();
+ pLine = pLine->GetNext();
+ }
+
+ SwpHints* pTmpHints = GetTxtFrm()->GetTxtNode()->GetpSwpHints();
+
+ // examine hints in range nEnd - (nEnd + nRangeChar)
+ for( sal_uInt16 i = 0; i < pTmpHints->Count(); i++ )
+ {
+ const SwTxtAttr* pHt = pTmpHints->GetTextHint( i );
+ if( RES_TXTATR_FLYCNT == pHt->Which() )
+ {
+ // check, if hint is in our range
+ const sal_uInt16 nTmpPos = *pHt->GetStart();
+ if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
+ pFollow->_InvalidateRange(
+ SwCharRange( nTmpPos, nTmpPos ), 0 );
+ }
+ }
+ }
+ }
+ delete pDel;
+ }
+ if( pCurr->IsDummy() &&
+ !pCurr->GetLen() &&
+ nStart < GetTxtFrm()->GetTxt().Len() )
+ pCurr->SetRealHeight( 1 );
+ if( GetHints() )
+ pFrm->RemoveFtn( nEnd );
+}
+
+/*************************************************************************
+ * SwTxtIter::CntHyphens()
+ *************************************************************************/
+
+void SwTxtIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
+{
+ nEndCnt = 0;
+ nMidCnt = 0;
+ if ( bPrev && pPrev && !pPrev->IsEndHyph() && !pPrev->IsMidHyph() )
+ return;
+ SwLineLayout *pLay = pInf->GetParaPortion();
+ if( pCurr == pLay )
+ return;
+ while( pLay != pCurr )
+ {
+ if ( pLay->IsEndHyph() )
+ nEndCnt++;
+ else
+ nEndCnt = 0;
+ if ( pLay->IsMidHyph() )
+ nMidCnt++;
+ else
+ nMidCnt = 0;
+ pLay = pLay->GetNext();
+ }
+}
+
+/*************************************************************************
+ * SwHookOut
+ *
+ * Change current output device to formatting device, this has to be done before
+ * formatting.
+ *************************************************************************/
+
+SwHookOut::SwHookOut( SwTxtSizeInfo& rInfo ) :
+ pInf( &rInfo ),
+ pOut( rInfo.GetOut() ),
+ bOnWin( rInfo.OnWin() )
+{
+ OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
+
+ // set new values
+ rInfo.SetOut( rInfo.GetRefDev() );
+ rInfo.SetOnWin( sal_False );
+}
+
+SwHookOut::~SwHookOut()
+{
+ pInf->SetOut( pOut );
+ pInf->SetOnWin( bOnWin );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */