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