xref: /AOO42X/main/sw/source/core/text/porglue.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
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
10cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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 }
312