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