xref: /trunk/main/sw/source/core/text/porlin.cxx (revision 870262e3)
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( sal_False, "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