summaryrefslogtreecommitdiff
path: root/sw/source/core/text/porglue.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/porglue.cxx')
-rw-r--r--sw/source/core/text/porglue.cxx318
1 files changed, 318 insertions, 0 deletions
diff --git a/sw/source/core/text/porglue.cxx b/sw/source/core/text/porglue.cxx
new file mode 100644
index 000000000000..983f5aded904
--- /dev/null
+++ b/sw/source/core/text/porglue.cxx
@@ -0,0 +1,318 @@
+/*************************************************************************
+ *
+ * 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 "swrect.hxx"
+#include "paratr.hxx" // pTabStop, ADJ*
+#include "viewopt.hxx" // SwViewOptions
+#include "errhdl.hxx" // ASSERT
+#include <SwPortionHandler.hxx>
+
+#include "txtcfg.hxx"
+#include "porglue.hxx"
+#include "inftxt.hxx"
+#include "porlay.hxx" // SwParaPortion, SetFull
+#include "porfly.hxx" // SwParaPortion, SetFull
+
+/*************************************************************************
+ * class SwGluePortion
+ *************************************************************************/
+
+SwGluePortion::SwGluePortion( const KSHORT nInitFixWidth )
+ : nFixWidth( nInitFixWidth )
+{
+ PrtWidth( nFixWidth );
+ SetWhichPor( POR_GLUE );
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwGluePortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ if( !GetLen() || nOfst > GetLen() || !Width() )
+ return SwLinePortion::GetCrsrOfst( nOfst );
+ else
+ return nOfst / (Width() / GetLen());
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwGluePortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ if( 1 >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen() )
+ return SwPosSize(*this);
+ else
+ return SwPosSize( (Width() / GetLen()) * rInf.GetLen(), Height() );
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwGluePortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ if( GetLen() && rInf.OnWin() &&
+ rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
+ {
+ rTxt.Fill( GetLen(), CH_BULLET );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::Paint()
+ *************************************************************************/
+
+void SwGluePortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( !GetLen() )
+ return;
+
+ if( rInf.GetFont()->IsPaintBlank() )
+ {
+ XubString aTxt;
+ aTxt.Fill( GetFixWidth() / GetLen(), ' ' );
+ SwTxtPaintInfo aInf( rInf, aTxt );
+ aInf.DrawText( *this, aTxt.Len(), sal_True );
+ }
+
+ if( rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
+ {
+#ifdef DBG_UTIL
+ const xub_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
+ ASSERT( CH_BLANK == cChar || CH_BULLET == cChar,
+ "SwGluePortion::Paint: blank expected" );
+#endif
+ if( 1 == GetLen() )
+ {
+ String aBullet( CH_BULLET );
+ SwPosSize aBulletSize( rInf.GetTxtSize( aBullet ) );
+ Point aPos( rInf.GetPos() );
+ aPos.X() += (Width()/2) - (aBulletSize.Width()/2);
+ SwTxtPaintInfo aInf( rInf, aBullet );
+ aInf.SetPos( aPos );
+ SwTxtPortion aBulletPor;
+ aBulletPor.Width( aBulletSize.Width() );
+ aBulletPor.Height( aBulletSize.Height() );
+ aBulletPor.SetAscent( GetAscent() );
+ aInf.DrawText( aBulletPor, aBullet.Len(), sal_True );
+ }
+ else
+ {
+ SwTxtSlot aSlot( &rInf, this, true, false );
+ rInf.DrawText( *this, rInf.GetLen(), sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwGluePortion::MoveGlue()
+ *************************************************************************/
+
+void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const short nPrtGlue )
+{
+ short nPrt = Min( nPrtGlue, GetPrtGlue() );
+ if( 0 < nPrt )
+ {
+ pTarget->AddPrtWidth( nPrt );
+ SubPrtWidth( nPrt );
+ }
+}
+
+/*************************************************************************
+ * void SwGluePortion::Join()
+ *************************************************************************/
+
+void SwGluePortion::Join( SwGluePortion *pVictim )
+{
+ // Die GluePortion wird ausgesogen und weggespuelt ...
+ AddPrtWidth( pVictim->PrtWidth() );
+ SetLen( pVictim->GetLen() + GetLen() );
+ if( Height() < pVictim->Height() )
+ Height( pVictim->Height() );
+
+ AdjFixWidth();
+ Cut( pVictim );
+ delete pVictim;
+}
+
+/*************************************************************************
+ * class SwFixPortion
+ *************************************************************************/
+
+// Wir erwarten ein framelokales SwRect !
+SwFixPortion::SwFixPortion( const SwRect &rRect )
+ :SwGluePortion( KSHORT(rRect.Width()) ), nFix( KSHORT(rRect.Left()) )
+{
+ Height( KSHORT(rRect.Height()) );
+ SetWhichPor( POR_FIX );
+}
+
+SwFixPortion::SwFixPortion(const KSHORT nFixedWidth, const KSHORT nFixedPos)
+ : SwGluePortion(nFixedWidth), nFix(nFixedPos)
+{
+ SetWhichPor( POR_FIX );
+}
+
+/*************************************************************************
+ * class SwMarginPortion
+ *************************************************************************/
+
+SwMarginPortion::SwMarginPortion( const KSHORT nFixedWidth )
+ :SwGluePortion( nFixedWidth )
+{
+ SetWhichPor( POR_MARGIN );
+}
+
+/*************************************************************************
+ * SwMarginPortion::AdjustRight()
+ *
+ * In der umschliessenden Schleife werden alle Portions durchsucht,
+ * dabei werden erst die am Ende liegenden GluePortions verarbeitet.
+ * Das Ende wird nach jeder Schleife nach vorne verlegt, bis keine
+ * GluePortions mehr vorhanden sind.
+ * Es werden immer GluePortion-Paare betrachtet (pLeft und pRight),
+ * wobei Textportions zwischen pLeft und pRight hinter pRight verschoben
+ * werden, wenn pRight genuegend Glue besitzt. Bei jeder Verschiebung
+ * wandert ein Teil des Glues von pRight nach pLeft.
+ * Im naechsten Schleifendurchlauf ist pLeft das pRight und das Spiel
+ * beginnt von vorne.
+ *************************************************************************/
+
+void SwMarginPortion::AdjustRight( const SwLineLayout *pCurr )
+{
+ SwGluePortion *pRight = 0;
+ BOOL bNoMove = 0 != pCurr->GetpKanaComp();
+ while( pRight != this )
+ {
+
+ // 1) Wir suchen den linken Glue
+ SwLinePortion *pPos = (SwLinePortion*)this;
+ SwGluePortion *pLeft = 0;
+ while( pPos )
+ {
+ DBG_LOOP;
+ if( pPos->InFixMargGrp() )
+ pLeft = (SwGluePortion*)pPos;
+ pPos = pPos->GetPortion();
+ if( pPos == pRight)
+ pPos = 0;
+ }
+
+ // Zwei nebeneinander liegende FlyPortions verschmelzen
+ if( pRight && pLeft->GetPortion() == pRight )
+ {
+ pRight->MoveAllGlue( pLeft );
+ pRight = 0;
+ }
+ KSHORT nRightGlue = pRight && 0 < pRight->GetPrtGlue()
+ ? KSHORT(pRight->GetPrtGlue()) : 0;
+ // 2) linken und rechten Glue ausgleichen
+ // Bei Tabs haengen wir nix um ...
+ if( pLeft && nRightGlue && !pRight->InTabGrp() )
+ {
+ // pPrev ist die Portion, die unmittelbar vor pRight liegt.
+ SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
+
+ if ( pRight->IsFlyPortion() && pRight->GetLen() )
+ {
+ SwFlyPortion *pFly = (SwFlyPortion *)pRight;
+ if ( pFly->GetBlankWidth() < nRightGlue )
+ {
+ // Hier entsteht eine neue TxtPortion, die dass zuvor
+ // vom Fly verschluckte Blank reaktiviert.
+ nRightGlue = nRightGlue - pFly->GetBlankWidth();
+ pFly->SubPrtWidth( pFly->GetBlankWidth() );
+ pFly->SetLen( 0 );
+ SwTxtPortion *pNewPor = new SwTxtPortion;
+ pNewPor->SetLen( 1 );
+ pNewPor->Height( pFly->Height() );
+ pNewPor->Width( pFly->GetBlankWidth() );
+ pFly->Insert( pNewPor );
+ }
+ else
+ pPrev = pLeft;
+ }
+ while( pPrev != pLeft )
+ {
+ DBG_LOOP;
+
+ if( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
+ pPrev->InHyphGrp() || pPrev->IsKernPortion() )
+ {
+ // Die Portion, die vor pRight liegt kann nicht
+ // verschoben werden, weil kein Glue mehr vorhanden ist.
+ // Wir fuehren die Abbruchbedingung herbei:
+ pPrev = pLeft;
+ }
+ else
+ {
+ nRightGlue = nRightGlue - pPrev->PrtWidth();
+ // pPrev wird hinter pRight verschoben.
+ // Dazu wird der Gluewert zwischen pRight und pLeft
+ // ausgeglichen.
+ pRight->MoveGlue( pLeft, short( pPrev->PrtWidth() ) );
+ // Jetzt wird die Verkettung gerichtet.
+ SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
+ pPrevPrev->SetPortion( pRight );
+ pPrev->SetPortion( pRight->GetPortion() );
+ pRight->SetPortion( pPrev );
+ if ( pPrev->GetPortion() && pPrev->InTxtGrp()
+ && pPrev->GetPortion()->IsHolePortion() )
+ {
+ SwHolePortion *pHolePor =
+ (SwHolePortion*)pPrev->GetPortion();
+ if ( !pHolePor->GetPortion() ||
+ !pHolePor->GetPortion()->InFixMargGrp() )
+ {
+ pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
+ pPrev->SetLen( pPrev->GetLen() + 1 );
+ pPrev->SetPortion( pHolePor->GetPortion() );
+ delete pHolePor;
+ }
+ }
+ pPrev = pPrevPrev;
+ }
+ }
+ }
+ // Wenn es keinen linken Glue mehr gibt, wird die Abbruchbedingung
+ // herbeigefuehrt.
+ pRight = pLeft ? pLeft : (SwGluePortion*)this;
+ }
+}
+
+
+