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