xref: /aoo41x/main/sw/source/core/text/porglue.cxx (revision efeef26f)
1*efeef26fSAndrew Rist /**************************************************************
2*efeef26fSAndrew Rist  *
3*efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*efeef26fSAndrew Rist  * distributed with this work for additional information
6*efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*efeef26fSAndrew Rist  *
11*efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17*efeef26fSAndrew Rist  * specific language governing permissions and limitations
18*efeef26fSAndrew Rist  * under the License.
19*efeef26fSAndrew Rist  *
20*efeef26fSAndrew Rist  *************************************************************/
21*efeef26fSAndrew Rist 
22*efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "swrect.hxx"
30cdf0e10cSrcweir #include "paratr.hxx" 	// pTabStop, ADJ*
31cdf0e10cSrcweir #include "viewopt.hxx"	// SwViewOptions
32cdf0e10cSrcweir #include "errhdl.hxx" 	// ASSERT
33cdf0e10cSrcweir #include <SwPortionHandler.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "txtcfg.hxx"
36cdf0e10cSrcweir #include "porglue.hxx"
37cdf0e10cSrcweir #include "inftxt.hxx"
38cdf0e10cSrcweir #include "porlay.hxx" 	// SwParaPortion, SetFull
39cdf0e10cSrcweir #include "porfly.hxx" 	// SwParaPortion, SetFull
40cdf0e10cSrcweir 
41cdf0e10cSrcweir /*************************************************************************
42cdf0e10cSrcweir  *						class SwGluePortion
43cdf0e10cSrcweir  *************************************************************************/
44cdf0e10cSrcweir 
SwGluePortion(const KSHORT nInitFixWidth)45cdf0e10cSrcweir SwGluePortion::SwGluePortion( const KSHORT nInitFixWidth )
46cdf0e10cSrcweir 	: nFixWidth( nInitFixWidth )
47cdf0e10cSrcweir {
48cdf0e10cSrcweir 	PrtWidth( nFixWidth );
49cdf0e10cSrcweir 	SetWhichPor( POR_GLUE );
50cdf0e10cSrcweir }
51cdf0e10cSrcweir 
52cdf0e10cSrcweir /*************************************************************************
53cdf0e10cSrcweir  *				  virtual SwGluePortion::GetCrsrOfst()
54cdf0e10cSrcweir  *************************************************************************/
55cdf0e10cSrcweir 
GetCrsrOfst(const KSHORT nOfst) const56cdf0e10cSrcweir xub_StrLen SwGluePortion::GetCrsrOfst( const KSHORT nOfst ) const
57cdf0e10cSrcweir {
58cdf0e10cSrcweir 	if( !GetLen() || nOfst > GetLen() || !Width() )
59cdf0e10cSrcweir 		return SwLinePortion::GetCrsrOfst( nOfst );
60cdf0e10cSrcweir 	else
61cdf0e10cSrcweir 		return nOfst / (Width() / GetLen());
62cdf0e10cSrcweir }
63cdf0e10cSrcweir 
64cdf0e10cSrcweir /*************************************************************************
65cdf0e10cSrcweir  *				  virtual SwGluePortion::GetTxtSize()
66cdf0e10cSrcweir  *************************************************************************/
67cdf0e10cSrcweir 
GetTxtSize(const SwTxtSizeInfo & rInf) const68cdf0e10cSrcweir SwPosSize SwGluePortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
69cdf0e10cSrcweir {
70cdf0e10cSrcweir 	if( 1 >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen() )
71cdf0e10cSrcweir 		return SwPosSize(*this);
72cdf0e10cSrcweir 	else
73cdf0e10cSrcweir 		return SwPosSize( (Width() / GetLen()) * rInf.GetLen(), Height() );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir /*************************************************************************
77cdf0e10cSrcweir  *				virtual SwGluePortion::GetExpTxt()
78cdf0e10cSrcweir  *************************************************************************/
79cdf0e10cSrcweir 
GetExpTxt(const SwTxtSizeInfo & rInf,XubString & rTxt) const80cdf0e10cSrcweir sal_Bool SwGluePortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
81cdf0e10cSrcweir {
82cdf0e10cSrcweir 	if( GetLen() && rInf.OnWin() &&
83cdf0e10cSrcweir 		rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
84cdf0e10cSrcweir 	{
85cdf0e10cSrcweir 		rTxt.Fill( GetLen(), CH_BULLET );
86cdf0e10cSrcweir 		return sal_True;
87cdf0e10cSrcweir 	}
88cdf0e10cSrcweir 	return sal_False;
89cdf0e10cSrcweir }
90cdf0e10cSrcweir 
91cdf0e10cSrcweir /*************************************************************************
92cdf0e10cSrcweir  *				  virtual SwGluePortion::Paint()
93cdf0e10cSrcweir  *************************************************************************/
94cdf0e10cSrcweir 
Paint(const SwTxtPaintInfo & rInf) const95cdf0e10cSrcweir void SwGluePortion::Paint( const SwTxtPaintInfo &rInf ) const
96cdf0e10cSrcweir {
97cdf0e10cSrcweir 	if( !GetLen() )
98cdf0e10cSrcweir 		return;
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 	if( rInf.GetFont()->IsPaintBlank() )
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir 		XubString aTxt;
103cdf0e10cSrcweir 		aTxt.Fill( GetFixWidth() / GetLen(), ' ' );
104cdf0e10cSrcweir 		SwTxtPaintInfo aInf( rInf, aTxt );
105cdf0e10cSrcweir 		aInf.DrawText( *this, aTxt.Len(), sal_True );
106cdf0e10cSrcweir 	}
107cdf0e10cSrcweir 
108cdf0e10cSrcweir 	if( rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
109cdf0e10cSrcweir 	{
110cdf0e10cSrcweir #ifdef DBG_UTIL
111cdf0e10cSrcweir 		const xub_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
112cdf0e10cSrcweir 		ASSERT( CH_BLANK  == cChar || CH_BULLET == cChar,
113cdf0e10cSrcweir 				"SwGluePortion::Paint: blank expected" );
114cdf0e10cSrcweir #endif
115cdf0e10cSrcweir 		if( 1 == GetLen() )
116cdf0e10cSrcweir 		{
117cdf0e10cSrcweir 			String aBullet( CH_BULLET );
118cdf0e10cSrcweir 			SwPosSize aBulletSize( rInf.GetTxtSize( aBullet ) );
119cdf0e10cSrcweir 			Point aPos( rInf.GetPos() );
120cdf0e10cSrcweir 			aPos.X() += (Width()/2) - (aBulletSize.Width()/2);
121cdf0e10cSrcweir 			SwTxtPaintInfo aInf( rInf, aBullet );
122cdf0e10cSrcweir 			aInf.SetPos( aPos );
123cdf0e10cSrcweir 			SwTxtPortion aBulletPor;
124cdf0e10cSrcweir 			aBulletPor.Width( aBulletSize.Width() );
125cdf0e10cSrcweir 			aBulletPor.Height( aBulletSize.Height() );
126cdf0e10cSrcweir 			aBulletPor.SetAscent( GetAscent() );
127cdf0e10cSrcweir 			aInf.DrawText( aBulletPor, aBullet.Len(), sal_True );
128cdf0e10cSrcweir 		}
129cdf0e10cSrcweir 		else
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir             SwTxtSlot aSlot( &rInf, this, true, false );
132cdf0e10cSrcweir 			rInf.DrawText( *this, rInf.GetLen(), sal_True );
133cdf0e10cSrcweir 		}
134cdf0e10cSrcweir 	}
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir /*************************************************************************
138cdf0e10cSrcweir  *						SwGluePortion::MoveGlue()
139cdf0e10cSrcweir  *************************************************************************/
140cdf0e10cSrcweir 
MoveGlue(SwGluePortion * pTarget,const short nPrtGlue)141cdf0e10cSrcweir void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const short nPrtGlue )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir 	short nPrt = Min( nPrtGlue, GetPrtGlue() );
144cdf0e10cSrcweir 	if( 0 < nPrt )
145cdf0e10cSrcweir 	{
146cdf0e10cSrcweir 		pTarget->AddPrtWidth( nPrt );
147cdf0e10cSrcweir 		SubPrtWidth( nPrt );
148cdf0e10cSrcweir 	}
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir /*************************************************************************
152cdf0e10cSrcweir  *				  void SwGluePortion::Join()
153cdf0e10cSrcweir  *************************************************************************/
154cdf0e10cSrcweir 
Join(SwGluePortion * pVictim)155cdf0e10cSrcweir void SwGluePortion::Join( SwGluePortion *pVictim )
156cdf0e10cSrcweir {
157cdf0e10cSrcweir 	// Die GluePortion wird ausgesogen und weggespuelt ...
158cdf0e10cSrcweir 	AddPrtWidth( pVictim->PrtWidth() );
159cdf0e10cSrcweir 	SetLen( pVictim->GetLen() + GetLen() );
160cdf0e10cSrcweir 	if( Height() < pVictim->Height() )
161cdf0e10cSrcweir 		Height( pVictim->Height() );
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 	AdjFixWidth();
164cdf0e10cSrcweir 	Cut( pVictim );
165cdf0e10cSrcweir 	delete pVictim;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir 
168cdf0e10cSrcweir /*************************************************************************
169cdf0e10cSrcweir  *				  class SwFixPortion
170cdf0e10cSrcweir  *************************************************************************/
171cdf0e10cSrcweir 
172cdf0e10cSrcweir // Wir erwarten ein framelokales SwRect !
SwFixPortion(const SwRect & rRect)173cdf0e10cSrcweir SwFixPortion::SwFixPortion( const SwRect &rRect )
174cdf0e10cSrcweir 	   :SwGluePortion( KSHORT(rRect.Width()) ), nFix( KSHORT(rRect.Left()) )
175cdf0e10cSrcweir {
176cdf0e10cSrcweir 	Height( KSHORT(rRect.Height()) );
177cdf0e10cSrcweir 	SetWhichPor( POR_FIX );
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
SwFixPortion(const KSHORT nFixedWidth,const KSHORT nFixedPos)180cdf0e10cSrcweir SwFixPortion::SwFixPortion(const KSHORT nFixedWidth, const KSHORT nFixedPos)
181cdf0e10cSrcweir        : SwGluePortion(nFixedWidth), nFix(nFixedPos)
182cdf0e10cSrcweir {
183cdf0e10cSrcweir 	SetWhichPor( POR_FIX );
184cdf0e10cSrcweir }
185cdf0e10cSrcweir 
186cdf0e10cSrcweir /*************************************************************************
187cdf0e10cSrcweir  *				  class SwMarginPortion
188cdf0e10cSrcweir  *************************************************************************/
189cdf0e10cSrcweir 
SwMarginPortion(const KSHORT nFixedWidth)190cdf0e10cSrcweir SwMarginPortion::SwMarginPortion( const KSHORT nFixedWidth )
191cdf0e10cSrcweir     :SwGluePortion( nFixedWidth )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir 	SetWhichPor( POR_MARGIN );
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
196cdf0e10cSrcweir /*************************************************************************
197cdf0e10cSrcweir  *				  SwMarginPortion::AdjustRight()
198cdf0e10cSrcweir  *
199cdf0e10cSrcweir  * In der umschliessenden Schleife werden alle Portions durchsucht,
200cdf0e10cSrcweir  * dabei werden erst die am Ende liegenden GluePortions verarbeitet.
201cdf0e10cSrcweir  * Das Ende wird nach jeder Schleife nach vorne verlegt, bis keine
202cdf0e10cSrcweir  * GluePortions mehr vorhanden sind.
203cdf0e10cSrcweir  * Es werden immer GluePortion-Paare betrachtet (pLeft und pRight),
204cdf0e10cSrcweir  * wobei Textportions zwischen pLeft und pRight hinter pRight verschoben
205cdf0e10cSrcweir  * werden, wenn pRight genuegend Glue besitzt. Bei jeder Verschiebung
206cdf0e10cSrcweir  * wandert ein Teil des Glues von pRight nach pLeft.
207cdf0e10cSrcweir  * Im naechsten Schleifendurchlauf ist pLeft das pRight und das Spiel
208cdf0e10cSrcweir  * beginnt von vorne.
209cdf0e10cSrcweir  *************************************************************************/
210cdf0e10cSrcweir 
AdjustRight(const SwLineLayout * pCurr)211cdf0e10cSrcweir void SwMarginPortion::AdjustRight( const SwLineLayout *pCurr )
212cdf0e10cSrcweir {
213cdf0e10cSrcweir 	SwGluePortion *pRight = 0;
214cdf0e10cSrcweir 	sal_Bool bNoMove = 0 != pCurr->GetpKanaComp();
215cdf0e10cSrcweir 	while( pRight != this )
216cdf0e10cSrcweir 	{
217cdf0e10cSrcweir 
218cdf0e10cSrcweir 		// 1) Wir suchen den linken Glue
219cdf0e10cSrcweir 		SwLinePortion *pPos = (SwLinePortion*)this;
220cdf0e10cSrcweir 		SwGluePortion *pLeft = 0;
221cdf0e10cSrcweir 		while( pPos )
222cdf0e10cSrcweir 		{
223cdf0e10cSrcweir 			DBG_LOOP;
224cdf0e10cSrcweir 			if( pPos->InFixMargGrp() )
225cdf0e10cSrcweir 				pLeft = (SwGluePortion*)pPos;
226cdf0e10cSrcweir 			pPos = pPos->GetPortion();
227cdf0e10cSrcweir 			if( pPos == pRight)
228cdf0e10cSrcweir 				pPos = 0;
229cdf0e10cSrcweir 		}
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 		// Zwei nebeneinander liegende FlyPortions verschmelzen
232cdf0e10cSrcweir 		if( pRight && pLeft->GetPortion() == pRight )
233cdf0e10cSrcweir 		{
234cdf0e10cSrcweir 			pRight->MoveAllGlue( pLeft );
235cdf0e10cSrcweir 			pRight = 0;
236cdf0e10cSrcweir 		}
237cdf0e10cSrcweir 		KSHORT nRightGlue = pRight && 0 < pRight->GetPrtGlue()
238cdf0e10cSrcweir 						  ? KSHORT(pRight->GetPrtGlue()) : 0;
239cdf0e10cSrcweir 		// 2) linken und rechten Glue ausgleichen
240cdf0e10cSrcweir 		//	  Bei Tabs haengen wir nix um ...
241cdf0e10cSrcweir 		if( pLeft && nRightGlue && !pRight->InTabGrp() )
242cdf0e10cSrcweir 		{
243cdf0e10cSrcweir 			// pPrev ist die Portion, die unmittelbar vor pRight liegt.
244cdf0e10cSrcweir 			SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 			if ( pRight->IsFlyPortion() && pRight->GetLen() )
247cdf0e10cSrcweir 			{
248cdf0e10cSrcweir 				SwFlyPortion *pFly = (SwFlyPortion *)pRight;
249cdf0e10cSrcweir 				if ( pFly->GetBlankWidth() < nRightGlue )
250cdf0e10cSrcweir 				{
251cdf0e10cSrcweir 					// Hier entsteht eine neue TxtPortion, die dass zuvor
252cdf0e10cSrcweir 					// vom Fly verschluckte Blank reaktiviert.
253cdf0e10cSrcweir 					nRightGlue = nRightGlue - pFly->GetBlankWidth();
254cdf0e10cSrcweir 					pFly->SubPrtWidth( pFly->GetBlankWidth() );
255cdf0e10cSrcweir 					pFly->SetLen( 0 );
256cdf0e10cSrcweir 					SwTxtPortion *pNewPor = new SwTxtPortion;
257cdf0e10cSrcweir 					pNewPor->SetLen( 1 );
258cdf0e10cSrcweir 					pNewPor->Height( pFly->Height() );
259cdf0e10cSrcweir 					pNewPor->Width( pFly->GetBlankWidth() );
260cdf0e10cSrcweir 					pFly->Insert( pNewPor );
261cdf0e10cSrcweir 				}
262cdf0e10cSrcweir 				else
263cdf0e10cSrcweir 					pPrev = pLeft;
264cdf0e10cSrcweir 			}
265cdf0e10cSrcweir 			while( pPrev != pLeft )
266cdf0e10cSrcweir 			{
267cdf0e10cSrcweir 				DBG_LOOP;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 				if( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
270cdf0e10cSrcweir 					pPrev->InHyphGrp() || pPrev->IsKernPortion() )
271cdf0e10cSrcweir 				{
272cdf0e10cSrcweir 					// Die Portion, die vor pRight liegt kann nicht
273cdf0e10cSrcweir 					// verschoben werden, weil kein Glue mehr vorhanden ist.
274cdf0e10cSrcweir 					// Wir fuehren die Abbruchbedingung herbei:
275cdf0e10cSrcweir 					pPrev = pLeft;
276cdf0e10cSrcweir 				}
277cdf0e10cSrcweir 				else
278cdf0e10cSrcweir 				{
279cdf0e10cSrcweir 					nRightGlue = nRightGlue - pPrev->PrtWidth();
280cdf0e10cSrcweir 					// pPrev wird hinter pRight verschoben.
281cdf0e10cSrcweir 					// Dazu wird der Gluewert zwischen pRight und pLeft
282cdf0e10cSrcweir 					// ausgeglichen.
283cdf0e10cSrcweir 					pRight->MoveGlue( pLeft, short( pPrev->PrtWidth() ) );
284cdf0e10cSrcweir 					// Jetzt wird die Verkettung gerichtet.
285cdf0e10cSrcweir 					SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
286cdf0e10cSrcweir 					pPrevPrev->SetPortion( pRight );
287cdf0e10cSrcweir 					pPrev->SetPortion( pRight->GetPortion() );
288cdf0e10cSrcweir 					pRight->SetPortion( pPrev );
289cdf0e10cSrcweir 					if ( pPrev->GetPortion() && pPrev->InTxtGrp()
290cdf0e10cSrcweir 						 && pPrev->GetPortion()->IsHolePortion() )
291cdf0e10cSrcweir 					{
292cdf0e10cSrcweir 						SwHolePortion *pHolePor =
293cdf0e10cSrcweir 							(SwHolePortion*)pPrev->GetPortion();
294cdf0e10cSrcweir 						if ( !pHolePor->GetPortion() ||
295cdf0e10cSrcweir 							 !pHolePor->GetPortion()->InFixMargGrp() )
296cdf0e10cSrcweir 						{
297cdf0e10cSrcweir 							pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
298cdf0e10cSrcweir 							pPrev->SetLen( pPrev->GetLen() + 1 );
299cdf0e10cSrcweir 							pPrev->SetPortion( pHolePor->GetPortion() );
300cdf0e10cSrcweir 							delete pHolePor;
301cdf0e10cSrcweir 						}
302cdf0e10cSrcweir 					}
303cdf0e10cSrcweir 					pPrev = pPrevPrev;
304cdf0e10cSrcweir 				}
305cdf0e10cSrcweir 			}
306cdf0e10cSrcweir 		}
307cdf0e10cSrcweir 		// Wenn es keinen linken Glue mehr gibt, wird die Abbruchbedingung
308cdf0e10cSrcweir 		// herbeigefuehrt.
309cdf0e10cSrcweir 		pRight = pLeft ? pLeft : (SwGluePortion*)this;
310cdf0e10cSrcweir 	}
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 
315