update dev300-m58
[ooovba.git] / sw / source / core / text / porglue.cxx
blobb5a137289394c5797fe6d24d73c7eb1002c9b40d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: porglue.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #include "swrect.hxx"
37 #include "paratr.hxx" // pTabStop, ADJ*
38 #include "viewopt.hxx" // SwViewOptions
39 #include "errhdl.hxx" // ASSERT
40 #include <SwPortionHandler.hxx>
42 #include "txtcfg.hxx"
43 #include "porglue.hxx"
44 #include "inftxt.hxx"
45 #include "porlay.hxx" // SwParaPortion, SetFull
46 #include "porfly.hxx" // SwParaPortion, SetFull
48 /*************************************************************************
49 * class SwGluePortion
50 *************************************************************************/
52 SwGluePortion::SwGluePortion( const KSHORT nInitFixWidth )
53 : nFixWidth( nInitFixWidth )
55 PrtWidth( nFixWidth );
56 SetWhichPor( POR_GLUE );
59 /*************************************************************************
60 * virtual SwGluePortion::GetCrsrOfst()
61 *************************************************************************/
63 xub_StrLen SwGluePortion::GetCrsrOfst( const KSHORT nOfst ) const
65 if( !GetLen() || nOfst > GetLen() || !Width() )
66 return SwLinePortion::GetCrsrOfst( nOfst );
67 else
68 return nOfst / (Width() / GetLen());
71 /*************************************************************************
72 * virtual SwGluePortion::GetTxtSize()
73 *************************************************************************/
75 SwPosSize SwGluePortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
77 if( 1 >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen() )
78 return SwPosSize(*this);
79 else
80 return SwPosSize( (Width() / GetLen()) * rInf.GetLen(), Height() );
83 /*************************************************************************
84 * virtual SwGluePortion::GetExpTxt()
85 *************************************************************************/
87 sal_Bool SwGluePortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
89 if( GetLen() && rInf.OnWin() &&
90 rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
92 rTxt.Fill( GetLen(), CH_BULLET );
93 return sal_True;
95 return sal_False;
98 /*************************************************************************
99 * virtual SwGluePortion::Paint()
100 *************************************************************************/
102 void SwGluePortion::Paint( const SwTxtPaintInfo &rInf ) const
104 if( !GetLen() )
105 return;
107 if( rInf.GetFont()->IsPaintBlank() )
109 XubString aTxt;
110 aTxt.Fill( GetFixWidth() / GetLen(), ' ' );
111 SwTxtPaintInfo aInf( rInf, aTxt );
112 aInf.DrawText( *this, aTxt.Len(), sal_True );
115 if( rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
117 #ifndef PRODUCT
118 const xub_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
119 ASSERT( CH_BLANK == cChar || CH_BULLET == cChar,
120 "SwGluePortion::Paint: blank expected" );
121 #endif
122 if( 1 == GetLen() )
124 String aBullet( CH_BULLET );
125 SwPosSize aBulletSize( rInf.GetTxtSize( aBullet ) );
126 Point aPos( rInf.GetPos() );
127 aPos.X() += (Width()/2) - (aBulletSize.Width()/2);
128 SwTxtPaintInfo aInf( rInf, aBullet );
129 aInf.SetPos( aPos );
130 SwTxtPortion aBulletPor;
131 aBulletPor.Width( aBulletSize.Width() );
132 aBulletPor.Height( aBulletSize.Height() );
133 aBulletPor.SetAscent( GetAscent() );
134 aInf.DrawText( aBulletPor, aBullet.Len(), sal_True );
136 else
138 SwTxtSlot aSlot( &rInf, this, true, false );
139 rInf.DrawText( *this, rInf.GetLen(), sal_True );
144 /*************************************************************************
145 * SwGluePortion::MoveGlue()
146 *************************************************************************/
148 void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const short nPrtGlue )
150 short nPrt = Min( nPrtGlue, GetPrtGlue() );
151 if( 0 < nPrt )
153 pTarget->AddPrtWidth( nPrt );
154 SubPrtWidth( nPrt );
158 /*************************************************************************
159 * void SwGluePortion::Join()
160 *************************************************************************/
162 void SwGluePortion::Join( SwGluePortion *pVictim )
164 // Die GluePortion wird ausgesogen und weggespuelt ...
165 AddPrtWidth( pVictim->PrtWidth() );
166 SetLen( pVictim->GetLen() + GetLen() );
167 if( Height() < pVictim->Height() )
168 Height( pVictim->Height() );
170 AdjFixWidth();
171 Cut( pVictim );
172 delete pVictim;
175 /*************************************************************************
176 * class SwFixPortion
177 *************************************************************************/
179 // Wir erwarten ein framelokales SwRect !
180 SwFixPortion::SwFixPortion( const SwRect &rRect )
181 :SwGluePortion( KSHORT(rRect.Width()) ), nFix( KSHORT(rRect.Left()) )
183 Height( KSHORT(rRect.Height()) );
184 SetWhichPor( POR_FIX );
187 SwFixPortion::SwFixPortion(const KSHORT nFixedWidth, const KSHORT nFixedPos)
188 : SwGluePortion(nFixedWidth), nFix(nFixedPos)
190 SetWhichPor( POR_FIX );
193 /*************************************************************************
194 * class SwMarginPortion
195 *************************************************************************/
197 SwMarginPortion::SwMarginPortion( const KSHORT nFixedWidth )
198 :SwGluePortion( nFixedWidth )
200 SetWhichPor( POR_MARGIN );
203 /*************************************************************************
204 * SwMarginPortion::AdjustRight()
206 * In der umschliessenden Schleife werden alle Portions durchsucht,
207 * dabei werden erst die am Ende liegenden GluePortions verarbeitet.
208 * Das Ende wird nach jeder Schleife nach vorne verlegt, bis keine
209 * GluePortions mehr vorhanden sind.
210 * Es werden immer GluePortion-Paare betrachtet (pLeft und pRight),
211 * wobei Textportions zwischen pLeft und pRight hinter pRight verschoben
212 * werden, wenn pRight genuegend Glue besitzt. Bei jeder Verschiebung
213 * wandert ein Teil des Glues von pRight nach pLeft.
214 * Im naechsten Schleifendurchlauf ist pLeft das pRight und das Spiel
215 * beginnt von vorne.
216 *************************************************************************/
218 void SwMarginPortion::AdjustRight( const SwLineLayout *pCurr )
220 SwGluePortion *pRight = 0;
221 BOOL bNoMove = 0 != pCurr->GetpKanaComp();
222 while( pRight != this )
225 // 1) Wir suchen den linken Glue
226 SwLinePortion *pPos = (SwLinePortion*)this;
227 SwGluePortion *pLeft = 0;
228 while( pPos )
230 DBG_LOOP;
231 if( pPos->InFixMargGrp() )
232 pLeft = (SwGluePortion*)pPos;
233 pPos = pPos->GetPortion();
234 if( pPos == pRight)
235 pPos = 0;
238 // Zwei nebeneinander liegende FlyPortions verschmelzen
239 if( pRight && pLeft->GetPortion() == pRight )
241 pRight->MoveAllGlue( pLeft );
242 pRight = 0;
244 KSHORT nRightGlue = pRight && 0 < pRight->GetPrtGlue()
245 ? KSHORT(pRight->GetPrtGlue()) : 0;
246 // 2) linken und rechten Glue ausgleichen
247 // Bei Tabs haengen wir nix um ...
248 if( pLeft && nRightGlue && !pRight->InTabGrp() )
250 // pPrev ist die Portion, die unmittelbar vor pRight liegt.
251 SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
253 if ( pRight->IsFlyPortion() && pRight->GetLen() )
255 SwFlyPortion *pFly = (SwFlyPortion *)pRight;
256 if ( pFly->GetBlankWidth() < nRightGlue )
258 // Hier entsteht eine neue TxtPortion, die dass zuvor
259 // vom Fly verschluckte Blank reaktiviert.
260 nRightGlue = nRightGlue - pFly->GetBlankWidth();
261 pFly->SubPrtWidth( pFly->GetBlankWidth() );
262 pFly->SetLen( 0 );
263 SwTxtPortion *pNewPor = new SwTxtPortion;
264 pNewPor->SetLen( 1 );
265 pNewPor->Height( pFly->Height() );
266 pNewPor->Width( pFly->GetBlankWidth() );
267 pFly->Insert( pNewPor );
269 else
270 pPrev = pLeft;
272 while( pPrev != pLeft )
274 DBG_LOOP;
276 if( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
277 pPrev->InHyphGrp() || pPrev->IsKernPortion() )
279 // Die Portion, die vor pRight liegt kann nicht
280 // verschoben werden, weil kein Glue mehr vorhanden ist.
281 // Wir fuehren die Abbruchbedingung herbei:
282 pPrev = pLeft;
284 else
286 nRightGlue = nRightGlue - pPrev->PrtWidth();
287 // pPrev wird hinter pRight verschoben.
288 // Dazu wird der Gluewert zwischen pRight und pLeft
289 // ausgeglichen.
290 pRight->MoveGlue( pLeft, short( pPrev->PrtWidth() ) );
291 // Jetzt wird die Verkettung gerichtet.
292 SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
293 pPrevPrev->SetPortion( pRight );
294 pPrev->SetPortion( pRight->GetPortion() );
295 pRight->SetPortion( pPrev );
296 if ( pPrev->GetPortion() && pPrev->InTxtGrp()
297 && pPrev->GetPortion()->IsHolePortion() )
299 SwHolePortion *pHolePor =
300 (SwHolePortion*)pPrev->GetPortion();
301 if ( !pHolePor->GetPortion() ||
302 !pHolePor->GetPortion()->InFixMargGrp() )
304 pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
305 pPrev->SetLen( pPrev->GetLen() + 1 );
306 pPrev->SetPortion( pHolePor->GetPortion() );
307 delete pHolePor;
310 pPrev = pPrevPrev;
314 // Wenn es keinen linken Glue mehr gibt, wird die Abbruchbedingung
315 // herbeigefuehrt.
316 pRight = pLeft ? pLeft : (SwGluePortion*)this;