1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: porglue.cxx,v $
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"
37 #include "paratr.hxx" // pTabStop, ADJ*
38 #include "viewopt.hxx" // SwViewOptions
39 #include "errhdl.hxx" // ASSERT
40 #include <SwPortionHandler.hxx>
43 #include "porglue.hxx"
45 #include "porlay.hxx" // SwParaPortion, SetFull
46 #include "porfly.hxx" // SwParaPortion, SetFull
48 /*************************************************************************
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
);
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);
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
);
98 /*************************************************************************
99 * virtual SwGluePortion::Paint()
100 *************************************************************************/
102 void SwGluePortion::Paint( const SwTxtPaintInfo
&rInf
) const
107 if( rInf
.GetFont()->IsPaintBlank() )
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() )
118 const xub_Unicode cChar
= rInf
.GetChar( rInf
.GetIdx() );
119 ASSERT( CH_BLANK
== cChar
|| CH_BULLET
== cChar
,
120 "SwGluePortion::Paint: blank expected" );
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
);
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
);
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() );
153 pTarget
->AddPrtWidth( 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() );
175 /*************************************************************************
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
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;
231 if( pPos
->InFixMargGrp() )
232 pLeft
= (SwGluePortion
*)pPos
;
233 pPos
= pPos
->GetPortion();
238 // Zwei nebeneinander liegende FlyPortions verschmelzen
239 if( pRight
&& pLeft
->GetPortion() == pRight
)
241 pRight
->MoveAllGlue( pLeft
);
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() );
263 SwTxtPortion
*pNewPor
= new SwTxtPortion
;
264 pNewPor
->SetLen( 1 );
265 pNewPor
->Height( pFly
->Height() );
266 pNewPor
->Width( pFly
->GetBlankWidth() );
267 pFly
->Insert( pNewPor
);
272 while( pPrev
!= pLeft
)
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:
286 nRightGlue
= nRightGlue
- pPrev
->PrtWidth();
287 // pPrev wird hinter pRight verschoben.
288 // Dazu wird der Gluewert zwischen pRight und pLeft
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() );
314 // Wenn es keinen linken Glue mehr gibt, wird die Abbruchbedingung
316 pRight
= pLeft
? pLeft
: (SwGluePortion
*)this;