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