xref: /AOO41X/main/sw/source/core/text/porlin.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 #ifndef _OUTDEV_HXX //autogen
29 #include <vcl/outdev.hxx>
30 #endif
31 #include <SwPortionHandler.hxx>
32 
33 #include "errhdl.hxx"   // ASSERT
34 
35 #include "txtcfg.hxx"
36 #include "porlin.hxx"
37 #include "inftxt.hxx"
38 #include "portxt.hxx"
39 #include "pormulti.hxx"
40 #include "porglue.hxx"
41 #include "inftxt.hxx"
42 #include "blink.hxx"
43 #ifdef DBG_UTIL
44 
ChkChain(SwLinePortion * pStart)45 sal_Bool ChkChain( SwLinePortion *pStart )
46 {
47     SwLinePortion *pPor = pStart->GetPortion();
48     MSHORT nCount = 0;
49     while( pPor )
50     {
51         ++nCount;
52         ASSERT( nCount < 200 && pPor != pStart,
53                 "ChkChain(): lost in chains" );
54         if( nCount >= 200 || pPor == pStart )
55         {
56             // der Lebensretter
57             pPor = pStart->GetPortion();
58             pStart->SetPortion(0);
59             pPor->Truncate();
60             pStart->SetPortion( pPor );
61             return sal_False;
62         }
63         pPor = pPor->GetPortion();
64     }
65     return sal_True;
66 }
67 #endif
68 
69 #if OSL_DEBUG_LEVEL > 1
70 const sal_Char *GetPortionName( const MSHORT nType );
71 #endif
72 
~SwLinePortion()73 SwLinePortion::~SwLinePortion()
74 {
75     if( pBlink )
76         pBlink->Delete( this );
77 }
78 
Compress()79 SwLinePortion *SwLinePortion::Compress()
80 {
81     return GetLen() || Width() ? this : 0;
82 }
83 
GetViewWidth(const SwTxtSizeInfo &) const84 KSHORT SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const
85 {
86     return 0;
87 }
88 
89 /*************************************************************************
90  *               SwLinePortion::SwLinePortion( )
91  *************************************************************************/
92 
SwLinePortion()93 SwLinePortion::SwLinePortion( ) :
94     pPortion( NULL ),
95     nLineLength( 0 ),
96     nAscent( 0 )
97 {
98 }
99 
100 /*************************************************************************
101  *               SwLinePortion::PrePaint()
102  *************************************************************************/
103 
PrePaint(const SwTxtPaintInfo & rInf,const SwLinePortion * pLast) const104 void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf,
105                               const SwLinePortion* pLast ) const
106 {
107     ASSERT( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
108     ASSERT( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
109 
110     const KSHORT nViewWidth = GetViewWidth( rInf );
111 
112     if( ! nViewWidth )
113         return;
114 
115     const KSHORT nHalfView = nViewWidth / 2;
116     sal_uInt16 nLastWidth = pLast->Width();
117 
118     if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
119         nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
120 
121     KSHORT nPos;
122     SwTxtPaintInfo aInf( rInf );
123 
124     const sal_Bool bBidiPor = ( rInf.GetTxtFrm()->IsRightToLeft() ) !=
125                           ( 0 != ( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() ) );
126 
127     sal_uInt16 nDir = bBidiPor ?
128                   1800 :
129                   rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
130 
131     switch ( nDir )
132     {
133     case 0 :
134         nPos = KSHORT( rInf.X() );
135         if( nLastWidth > nHalfView )
136             nPos += nLastWidth - nHalfView;
137         aInf.X( nPos );
138         break;
139     case 900 :
140         nPos = KSHORT( rInf.Y() );
141         if( nLastWidth > nHalfView )
142             nPos -= nLastWidth + nHalfView;
143         aInf.Y( nPos );
144         break;
145     case 1800 :
146         nPos = KSHORT( rInf.X() );
147         if( nLastWidth > nHalfView )
148             nPos -= nLastWidth + nHalfView;
149         aInf.X( nPos );
150         break;
151     case 2700 :
152         nPos = KSHORT( rInf.Y() );
153         if( nLastWidth > nHalfView )
154             nPos += nLastWidth - nHalfView;
155         aInf.Y( nPos );
156         break;
157     }
158 
159     SwLinePortion *pThis = (SwLinePortion*)this;
160     pThis->Width( nViewWidth );
161     Paint( aInf );
162     pThis->Width(0);
163 }
164 
165 /*************************************************************************
166  *                  SwLinePortion::CalcTxtSize()
167  *************************************************************************/
168 
CalcTxtSize(const SwTxtSizeInfo & rInf)169 void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf )
170 {
171     if( GetLen() == rInf.GetLen()  )
172         *((SwPosSize*)this) = GetTxtSize( rInf );
173     else
174     {
175         SwTxtSizeInfo aInf( rInf );
176         aInf.SetLen( GetLen() );
177         *((SwPosSize*)this) = GetTxtSize( aInf );
178     }
179 }
180 
181 /*************************************************************************
182  *                  SwLinePortion::Truncate()
183  *
184  * Es werden alle nachfolgenden Portions geloescht.
185  *************************************************************************/
186 
_Truncate()187 void SwLinePortion::_Truncate()
188 {
189     SwLinePortion *pPos = pPortion;
190     do
191     {   ASSERT( pPos != this, "SwLinePortion::Truncate: loop" );
192         SwLinePortion *pLast = pPos;
193         pPos = pPos->GetPortion();
194         pLast->SetPortion( 0 );
195         delete pLast;
196 
197     } while( pPos );
198 
199     pPortion = 0;
200 }
201 
202 /*************************************************************************
203  *                virtual SwLinePortion::Insert()
204  *
205  * Es wird immer hinter uns eingefuegt.
206  *************************************************************************/
207 
Insert(SwLinePortion * pIns)208 SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
209 {
210     pIns->FindLastPortion()->SetPortion( pPortion );
211     SetPortion( pIns );
212 #ifdef DBG_UTIL
213     ChkChain( this );
214 #endif
215     return pIns;
216 }
217 
218 /*************************************************************************
219  *                  SwLinePortion::FindLastPortion()
220  *************************************************************************/
221 
FindLastPortion()222 SwLinePortion *SwLinePortion::FindLastPortion()
223 {
224     SwLinePortion *pPos = this;
225     // An das Ende wandern und pLinPortion an den letzten haengen ...
226     while( pPos->GetPortion() )
227     {
228         DBG_LOOP;
229         pPos = pPos->GetPortion();
230     }
231     return pPos;
232 }
233 
234 /*************************************************************************
235  *                virtual SwLinePortion::Append()
236  *************************************************************************/
237 
Append(SwLinePortion * pIns)238 SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
239 {
240     SwLinePortion *pPos = FindLastPortion();
241     pPos->SetPortion( pIns );
242     pIns->SetPortion( 0 );
243 #ifdef DBG_UTIL
244     ChkChain( this );
245 #endif
246     return pIns;
247 }
248 
249 /*************************************************************************
250  *                virtual SwLinePortion::Cut()
251  *************************************************************************/
252 
Cut(SwLinePortion * pVictim)253 SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
254 {
255     SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
256     ASSERT( pPrev, "SwLinePortion::Cut(): can't cut" );
257     pPrev->SetPortion( pVictim->GetPortion() );
258     pVictim->SetPortion(0);
259     return pVictim;
260 }
261 
262 /*************************************************************************
263  *                SwLinePortion::FindPrevPortion()
264  *************************************************************************/
265 
FindPrevPortion(const SwLinePortion * pRoot)266 SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
267 {
268     ASSERT( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
269     SwLinePortion *pPos = (SwLinePortion*)pRoot;
270     while( pPos->GetPortion() && pPos->GetPortion() != this )
271     {
272         DBG_LOOP;
273         pPos = pPos->GetPortion();
274     }
275     ASSERT( pPos->GetPortion(),
276             "SwLinePortion::FindPrevPortion: blowing in the wind");
277     return pPos;
278 }
279 
280 /*************************************************************************
281  *                virtual SwLinePortion::GetCrsrOfst()
282  *************************************************************************/
283 
GetCrsrOfst(const KSHORT nOfst) const284 xub_StrLen SwLinePortion::GetCrsrOfst( const KSHORT nOfst ) const
285 {
286     if( nOfst > ( PrtWidth() / 2 ) )
287         return GetLen();
288     else
289         return 0;
290 }
291 
292 /*************************************************************************
293  *                virtual SwLinePortion::GetTxtSize()
294  *************************************************************************/
295 
GetTxtSize(const SwTxtSizeInfo &) const296 SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const
297 {
298     ASSERT( !this, "SwLinePortion::GetTxtSize: don't ask me about sizes, "
299                    "I'm only a stupid SwLinePortion" );
300     return SwPosSize();
301 }
302 
303 #ifdef DBG_UTIL
304 
305 /*************************************************************************
306  *                virtual SwLinePortion::Check()
307  *************************************************************************/
308 
Check(SvStream &,SwTxtSizeInfo &)309 sal_Bool SwLinePortion::Check( SvStream &, SwTxtSizeInfo & ) //$ ostream
310 {
311     return sal_True;
312 }
313 #endif
314 
315 /*************************************************************************
316  *                 virtual SwLinePortion::Format()
317  *************************************************************************/
318 
Format(SwTxtFormatInfo & rInf)319 sal_Bool SwLinePortion::Format( SwTxtFormatInfo &rInf )
320 {
321     if( rInf.X() > rInf.Width() )
322     {
323         Truncate();
324         rInf.SetUnderFlow( this );
325         return sal_True;
326     }
327 
328     const SwLinePortion *pLast = rInf.GetLast();
329     Height( pLast->Height() );
330     SetAscent( pLast->GetAscent() );
331     const KSHORT nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
332     // Nur Portions mit echter Breite koennen ein sal_True zurueckliefern
333     // Notizen beispielsweise setzen niemals bFull==sal_True
334     if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
335     {
336         Truncate();
337         if( nNewWidth > rInf.Width() )
338             PrtWidth( nNewWidth - rInf.Width() );
339         rInf.GetLast()->FormatEOL( rInf );
340         return sal_True;
341     }
342     return sal_False;
343 }
344 
345 /*************************************************************************
346  *                 virtual SwLinePortion::FormatEOL()
347  *************************************************************************/
348 
349 // Format end of line
350 
FormatEOL(SwTxtFormatInfo &)351 void SwLinePortion::FormatEOL( SwTxtFormatInfo & )
352 { }
353 
354 /*************************************************************************
355  *                      SwLinePortion::Move()
356  *************************************************************************/
357 
Move(SwTxtPaintInfo & rInf)358 void SwLinePortion::Move( SwTxtPaintInfo &rInf )
359 {
360     sal_Bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
361     const sal_Bool bFrmDir = rInf.GetTxtFrm()->IsRightToLeft();
362     sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
363                        (   bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
364 
365     if ( InSpaceGrp() && rInf.GetSpaceAdd() )
366     {
367         SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
368         if( rInf.IsRotated() )
369             rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
370         else if ( bCounterDir )
371             rInf.X( rInf.X() - nTmp );
372         else
373             rInf.X( rInf.X() + nTmp );
374     }
375     else
376     {
377         if( InFixMargGrp() && !IsMarginPortion() )
378         {
379             rInf.IncSpaceIdx();
380             rInf.IncKanaIdx();
381         }
382         if( rInf.IsRotated() )
383             rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
384         else if ( bCounterDir )
385             rInf.X( rInf.X() - PrtWidth() );
386         else
387             rInf.X( rInf.X() + PrtWidth() );
388     }
389     if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() )
390         rInf.IncSpaceIdx();
391 
392     rInf.SetIdx( rInf.GetIdx() + GetLen() );
393 }
394 
395 /*************************************************************************
396  *              virtual SwLinePortion::CalcSpacing()
397  *************************************************************************/
398 
CalcSpacing(long,const SwTxtSizeInfo &) const399 long SwLinePortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
400 {
401     return 0;
402 }
403 
404 /*************************************************************************
405  *              virtual SwLinePortion::GetExpTxt()
406  *************************************************************************/
407 
GetExpTxt(const SwTxtSizeInfo &,XubString &) const408 sal_Bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
409 {
410     return sal_False;
411 }
412 
413 /*************************************************************************
414  *              virtual SwLinePortion::HandlePortion()
415  *************************************************************************/
416 
HandlePortion(SwPortionHandler & rPH) const417 void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
418 {
419     String aString;
420     rPH.Special( GetLen(), aString, GetWhichPor() );
421 }
422 
423