xref: /AOO41X/main/sw/source/core/text/porrst.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 #include <hintids.hxx>
31 #include <sfx2/printer.hxx>
32 #include <editeng/lspcitem.hxx>
33 #include <editeng/adjitem.hxx>
34 #include <editeng/escpitem.hxx>
35 #include <editeng/lrspitem.hxx>
36 #include <editeng/pgrditem.hxx>
37 #include <vcl/window.hxx>
38 #include <vcl/svapp.hxx>
39 #include <viewsh.hxx>	// ViewShell
40 #include <viewopt.hxx>
41 #include <ndtxt.hxx>	// SwTxtNode
42 #include <pagefrm.hxx>  // SwPageFrm
43 #include <paratr.hxx>
44 #include <SwPortionHandler.hxx>
45 #include <txtcfg.hxx>
46 #include <porrst.hxx>
47 #include <inftxt.hxx>
48 #include <txtpaint.hxx>	// ClipVout
49 #include <swfntcch.hxx>	// SwFontAccess
50 #include <tgrditem.hxx>
51 #include <pagedesc.hxx> // SwPageDesc
52 #include <frmatr.hxx>
53 #include <redlnitr.hxx>	// SwRedlineItr
54 #include <porfly.hxx> 	// SwFlyPortion
55 #include <atrhndl.hxx>
56 #include "rootfrm.hxx"
57 
58 #include <IDocumentRedlineAccess.hxx>
59 #include <IDocumentSettingAccess.hxx>
60 #include <IDocumentDeviceAccess.hxx>
61 
62 /*************************************************************************
63  *                      class SwTmpEndPortion
64  *************************************************************************/
65 
66 SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion )
67 {
68 	Height( rPortion.Height() );
69 	SetAscent( rPortion.GetAscent() );
70 	SetWhichPor( POR_TMPEND );
71 }
72 
73 /*************************************************************************
74  *				   virtual SwTmpEndPortion::Paint()
75  *************************************************************************/
76 
77 void SwTmpEndPortion::Paint( const SwTxtPaintInfo &rInf ) const
78 {
79 	if( rInf.OnWin() && rInf.GetOpt().IsParagraph() )
80 	{
81 		SwDefFontSave aSave( rInf );
82 		const XubString aTmp( CH_PAR );
83 		rInf.DrawText( aTmp, *this );
84 	}
85 }
86 
87 /*************************************************************************
88  *						class SwBreakPortion
89  *************************************************************************/
90 SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion )
91     : SwLinePortion( rPortion )
92 {
93 	nLineLength = 1;
94 	SetWhichPor( POR_BRK );
95 }
96 
97 xub_StrLen SwBreakPortion::GetCrsrOfst( const KSHORT ) const
98 { return 0; }
99 
100 KSHORT SwBreakPortion::GetViewWidth( const SwTxtSizeInfo & ) const
101 { return 0; }
102 
103 SwLinePortion *SwBreakPortion::Compress()
104 { return (GetPortion() && GetPortion()->InTxtGrp() ? 0 : this); }
105 
106 void SwBreakPortion::Paint( const SwTxtPaintInfo &rInf ) const
107 {
108     if( rInf.OnWin() && rInf.GetOpt().IsLineBreak() )
109         rInf.DrawLineBreak( *this );
110 }
111 
112 /*************************************************************************
113  *				   virtual SwBreakPortion::Format()
114  *************************************************************************/
115 
116 sal_Bool SwBreakPortion::Format( SwTxtFormatInfo &rInf )
117 {
118     const SwLinePortion *pRoot = rInf.GetRoot();
119 	Width( 0 );
120 	Height( pRoot->Height() );
121 	SetAscent( pRoot->GetAscent() );
122 	if ( rInf.GetIdx()+1 == rInf.GetTxt().Len() )
123 		rInf.SetNewLine( sal_True );
124 	return sal_True;
125 }
126 
127 /*************************************************************************
128  *              virtual SwBreakPortion::HandlePortion()
129  *************************************************************************/
130 
131 void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const
132 {
133     rPH.Text( GetLen(), GetWhichPor() );
134 }
135 
136 
137 SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn,
138                               sal_Bool bBG, sal_Bool bGK ) :
139     nKern( nKrn ), bBackground( bBG ), bGridKern( bGK )
140 {
141 	Height( rPortion.Height() );
142 	SetAscent( rPortion.GetAscent() );
143 	nLineLength = 0;
144 	SetWhichPor( POR_KERN );
145 	if( nKern > 0 )
146 		Width( nKern );
147  	rPortion.Insert( this );
148 }
149 
150 SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) :
151     nKern( 0 ), bBackground( sal_False ), bGridKern( sal_True )
152 {
153 	Height( rPortion.Height() );
154 	SetAscent( rPortion.GetAscent() );
155 
156 	nLineLength = 0;
157 	SetWhichPor( POR_KERN );
158 }
159 
160 void SwKernPortion::Paint( const SwTxtPaintInfo &rInf ) const
161 {
162 	if( Width() )
163 	{
164         // bBackground is set for Kerning Portions between two fields
165         if ( bBackground )
166             rInf.DrawViewOpt( *this, POR_FLD );
167 
168 		rInf.DrawBackBrush( *this );
169 
170         // do we have to repaint a post it portion?
171         if( rInf.OnWin() && pPortion && !pPortion->Width() )
172             pPortion->PrePaint( rInf, this );
173 
174         if( rInf.GetFont()->IsPaintBlank() )
175 		{
176             static sal_Char __READONLY_DATA sDoubleSpace[] = "  ";
177 			XubString aTxtDouble( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
178             // --> FME 2006-07-12 #b6439097#
179             SwRect aClipRect;
180             rInf.CalcRect( *this, &aClipRect, 0 );
181             SwSaveClip aClip( (OutputDevice*)rInf.GetOut() );
182             aClip.ChgClip( aClipRect, 0 );
183             // <--
184             rInf.DrawText( aTxtDouble, *this, 0, 2, sal_True );
185 		}
186 	}
187 }
188 
189 void SwKernPortion::FormatEOL( SwTxtFormatInfo &rInf )
190 {
191     if ( bGridKern )
192         return;
193 
194     if( rInf.GetLast() == this )
195 		rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
196 	if( nKern < 0 )
197 		Width( -nKern );
198 	else
199 		Width( 0 );
200 	rInf.GetLast()->FormatEOL( rInf );
201 }
202 
203 SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) :
204 	bLeft( sal_True )
205 {
206 	Height( rPortion.Height() );
207 	SetAscent( rPortion.GetAscent() );
208 	nLineLength = 0;
209 	SetWhichPor( POR_ARROW );
210 }
211 
212 SwArrowPortion::SwArrowPortion( const SwTxtPaintInfo &rInf )
213 	: bLeft( sal_False )
214 {
215     Height( (sal_uInt16)(rInf.GetTxtFrm()->Prt().Height()) );
216 	aPos.X() = rInf.GetTxtFrm()->Frm().Left() +
217 			   rInf.GetTxtFrm()->Prt().Right();
218 	aPos.Y() = rInf.GetTxtFrm()->Frm().Top() +
219 			   rInf.GetTxtFrm()->Prt().Bottom();
220     SetWhichPor( POR_ARROW );
221 }
222 
223 void SwArrowPortion::Paint( const SwTxtPaintInfo &rInf ) const
224 {
225 	((SwArrowPortion*)this)->aPos = rInf.GetPos();
226 }
227 
228 SwLinePortion *SwArrowPortion::Compress() { return this; }
229 
230 SwTwips SwTxtFrm::EmptyHeight() const
231 {
232     ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::EmptyHeight with swapped frame" );
233 
234     SwFont *pFnt;
235 	const SwTxtNode& rTxtNode = *GetTxtNode();
236     const IDocumentSettingAccess* pIDSA = rTxtNode.getIDocumentSettingAccess();
237 	ViewShell *pSh = getRootFrm()->GetCurrShell();
238 	if ( rTxtNode.HasSwAttrSet() )
239 	{
240 		const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
241         pFnt = new SwFont( pAttrSet, pIDSA );
242 	}
243 	else
244 	{
245 		SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh);
246         pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
247 		pFnt->ChkMagic( pSh, pFnt->GetActual() );
248 	}
249 
250     if ( IsVertical() )
251         pFnt->SetVertical( 2700 );
252 
253     OutputDevice* pOut = pSh ? pSh->GetOut() : 0;
254     if ( !pOut || !pSh->GetViewOptions()->getBrowseMode() ||
255 		 pSh->GetViewOptions()->IsPrtFormat() )
256 	{
257         pOut = rTxtNode.getIDocumentDeviceAccess()->getReferenceDevice(true);
258 	}
259 
260     const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
261     if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
262 	{
263         MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
264         if( MSHRT_MAX != nRedlPos )
265         {
266             SwAttrHandler aAttrHandler;
267             aAttrHandler.Init(  GetTxtNode()->GetSwAttrSet(),
268                                *GetTxtNode()->getIDocumentSettingAccess(), NULL );
269             SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler,
270                                  nRedlPos, sal_True );
271         }
272     }
273 
274 	SwTwips nRet;
275 	if( !pOut )
276         nRet = IsVertical() ?
277                Prt().SSize().Width() + 1 :
278                Prt().SSize().Height() + 1;
279 	else
280 	{
281 		pFnt->SetFntChg( sal_True );
282         pFnt->ChgPhysFnt( pSh, *pOut );
283         nRet = pFnt->GetHeight( pSh, *pOut );
284 	}
285 	delete pFnt;
286 	return nRet;
287 }
288 
289 /*************************************************************************
290  *						SwTxtFrm::FormatEmpty()
291  *************************************************************************/
292 
293 sal_Bool SwTxtFrm::FormatEmpty()
294 {
295     ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::FormatEmpty with swapped frame" );
296 
297 	if ( HasFollow() || GetTxtNode()->GetpSwpHints() ||
298 		0 != GetTxtNode()->GetNumRule() ||
299         GetTxtNode()->HasHiddenCharAttribute( true ) ||
300 		 IsInFtn() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
301 		return sal_False;
302 	const SwAttrSet& aSet = GetTxtNode()->GetSwAttrSet();
303     const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
304     if( ( ( ! IsRightToLeft() && ( SVX_ADJUST_LEFT != nAdjust ) ) ||
305           (   IsRightToLeft() && ( SVX_ADJUST_RIGHT != nAdjust ) ) ) ||
306           aSet.GetRegister().GetValue() )
307         return sal_False;
308 	const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing();
309 	if( SVX_LINE_SPACE_MIN == rSpacing.GetLineSpaceRule() ||
310 		SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() ||
311 		aSet.GetLRSpace().IsAutoFirst() )
312 		return sal_False;
313 	else
314 	{
315         SwTxtFly aTxtFly( this );
316 		SwRect aRect;
317 		sal_Bool bFirstFlyCheck = 0 != Prt().Height();
318 		if ( bFirstFlyCheck &&
319 			 aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
320 			return sal_False;
321 		else
322 		{
323             SwTwips nHeight = EmptyHeight();
324 
325             if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
326                  IsInDocBody() )
327             {
328                 GETGRID( FindPageFrm() )
329                 if ( pGrid )
330                     nHeight = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
331             }
332 
333             SWRECTFN( this )
334             const SwTwips nChg = nHeight - (Prt().*fnRect->fnGetHeight)();
335 
336             if( !nChg )
337 				SetUndersized( sal_False );
338 			AdjustFrm( nChg );
339 
340 			if( HasBlinkPor() )
341 			{
342 				ClearPara();
343 				ResetBlinkPor();
344 			}
345 			SetCacheIdx( MSHRT_MAX );
346 			if( !IsEmpty() )
347 			{
348 				SetEmpty( sal_True );
349 				SetCompletePaint();
350 			}
351 			if( !bFirstFlyCheck &&
352 				 aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
353 				 return sal_False;
354 
355             // --> OD 2004-11-17 #i35635# - call method <HideAndShowObjects()>
356             // to assure that objects anchored at the empty paragraph are
357             // correctly visible resp. invisible.
358             HideAndShowObjects();
359             // <--
360 			return sal_True;
361 		}
362 	}
363 }
364 
365 sal_Bool SwTxtFrm::FillRegister( SwTwips& rRegStart, KSHORT& rRegDiff )
366 {
367 	const SwFrm *pFrm = this;
368 	rRegDiff = 0;
369 	while( !( ( FRM_BODY | FRM_FLY )
370 		   & pFrm->GetType() ) && pFrm->GetUpper() )
371 		pFrm = pFrm->GetUpper();
372 	if( ( FRM_BODY| FRM_FLY ) & pFrm->GetType() )
373 	{
374         SWRECTFN( pFrm )
375         rRegStart = (pFrm->*fnRect->fnGetPrtTop)();
376 		pFrm = pFrm->FindPageFrm();
377 		if( pFrm->IsPageFrm() )
378 		{
379 			SwPageDesc* pDesc = ((SwPageFrm*)pFrm)->FindPageDesc();
380 			if( pDesc )
381 			{
382 				rRegDiff = pDesc->GetRegHeight();
383 				if( !rRegDiff )
384 				{
385 					const SwTxtFmtColl *pFmt = pDesc->GetRegisterFmtColl();
386 					if( pFmt )
387 					{
388 						const SvxLineSpacingItem &rSpace = pFmt->GetLineSpacing();
389 						if( SVX_LINE_SPACE_FIX == rSpace.GetLineSpaceRule() )
390 						{
391 							rRegDiff = rSpace.GetLineHeight();
392 							pDesc->SetRegHeight( rRegDiff );
393 							pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 );
394 						}
395 						else
396 						{
397 							ViewShell *pSh = getRootFrm()->GetCurrShell();
398 							SwFontAccess aFontAccess( pFmt, pSh );
399 							SwFont aFnt( *aFontAccess.Get()->GetFont() );
400 
401 							OutputDevice *pOut = 0;
402                             if( !pSh || !pSh->GetViewOptions()->getBrowseMode() ||
403 								pSh->GetViewOptions()->IsPrtFormat() )
404                                 pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
405 
406                             if( pSh && !pOut )
407 								pOut = pSh->GetWin();
408 
409 							if( !pOut )
410 								pOut = GetpApp()->GetDefaultDevice();
411 
412 							MapMode aOldMap( pOut->GetMapMode() );
413 							pOut->SetMapMode( MapMode( MAP_TWIP ) );
414 
415                             aFnt.ChgFnt( pSh, *pOut );
416                             rRegDiff = aFnt.GetHeight( pSh, *pOut );
417 							KSHORT nNettoHeight = rRegDiff;
418 
419 							switch( rSpace.GetLineSpaceRule() )
420 							{
421 								case SVX_LINE_SPACE_AUTO:
422 								break;
423 								case SVX_LINE_SPACE_MIN:
424 								{
425 									if( rRegDiff < KSHORT( rSpace.GetLineHeight() ) )
426 										rRegDiff = rSpace.GetLineHeight();
427 									break;
428 								}
429 								default: ASSERT(
430 								sal_False, ": unknown LineSpaceRule" );
431 							}
432 							switch( rSpace.GetInterLineSpaceRule() )
433 							{
434 								case SVX_INTER_LINE_SPACE_OFF:
435 								break;
436 								case SVX_INTER_LINE_SPACE_PROP:
437 								{
438 									long nTmp = rSpace.GetPropLineSpace();
439 									if( nTmp < 50 )
440 										nTmp = nTmp ? 50 : 100;
441 									nTmp *= rRegDiff;
442 									nTmp /= 100;
443 									if( !nTmp )
444 										++nTmp;
445 									rRegDiff = (KSHORT)nTmp;
446 									nNettoHeight = rRegDiff;
447 									break;
448 								}
449 								case SVX_INTER_LINE_SPACE_FIX:
450 								{
451 									rRegDiff = rRegDiff + rSpace.GetInterLineSpace();
452 									nNettoHeight = rRegDiff;
453 									break;
454 								}
455 								default: ASSERT( sal_False, ": unknown InterLineSpaceRule" );
456 							}
457 							pDesc->SetRegHeight( rRegDiff );
458 							pDesc->SetRegAscent( rRegDiff - nNettoHeight +
459                                                  aFnt.GetAscent( pSh, *pOut ) );
460 							pOut->SetMapMode( aOldMap );
461 						}
462 					}
463 				}
464                 const long nTmpDiff = pDesc->GetRegAscent() - rRegDiff;
465                 if ( bVert )
466                     rRegStart -= nTmpDiff;
467                 else
468                     rRegStart += nTmpDiff;
469 			}
470 		}
471 	}
472 	return ( 0 != rRegDiff );
473 }
474 
475 /*************************************************************************
476  *              virtual SwHiddenTextPortion::Paint()
477  *************************************************************************/
478 
479 void SwHiddenTextPortion::Paint( const SwTxtPaintInfo & rInf) const
480 {
481     (void)rInf;
482 #if OSL_DEBUG_LEVEL > 1
483     OutputDevice* pOut = (OutputDevice*)rInf.GetOut();
484     Color aCol( SwViewOption::GetFieldShadingsColor() );
485     Color aOldColor( pOut->GetFillColor() );
486     pOut->SetFillColor( aCol );
487     Point aPos( rInf.GetPos() );
488     aPos.Y() -= 150;
489     aPos.X() -= 25;
490     SwRect aRect( aPos, Size( 100, 200 ) );
491     ((OutputDevice*)pOut)->DrawRect( aRect.SVRect() );
492     pOut->SetFillColor( aOldColor );
493 #endif
494 }
495 
496 /*************************************************************************
497  *              virtual SwHiddenTextPortion::Format()
498  *************************************************************************/
499 
500 sal_Bool SwHiddenTextPortion::Format( SwTxtFormatInfo &rInf )
501 {
502     Width( 0 );
503     rInf.GetTxtFrm()->HideFootnotes( rInf.GetIdx(), rInf.GetIdx() + GetLen() );
504 
505     return sal_False;
506 };
507 
508 /*************************************************************************
509  *              virtual SwControlCharPortion::Paint()
510  *************************************************************************/
511 
512 void SwControlCharPortion::Paint( const SwTxtPaintInfo &rInf ) const
513 {
514     if ( Width() )  // is only set during prepaint mode
515     {
516         rInf.DrawViewOpt( *this, POR_CONTROLCHAR );
517 
518         if ( !rInf.GetOpt().IsPagePreview() &&
519              !rInf.GetOpt().IsReadonly() &&
520               SwViewOption::IsFieldShadings() &&
521               CHAR_ZWNBSP != mcChar )
522         {
523             SwFont aTmpFont( *rInf.GetFont() );
524             aTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
525             const sal_uInt16 nProp = 40;
526             aTmpFont.SetProportion( nProp );  // a smaller font
527             SwFontSave aFontSave( rInf, &aTmpFont );
528 
529             String aOutString;
530 
531             switch ( mcChar )
532             {
533                 case CHAR_ZWSP :
534                     aOutString = '/'; break;
535 //                case CHAR_LRM :
536 //                    rTxt = sal_Unicode(0x2514); break;
537 //                case CHAR_RLM :
538 //                    rTxt = sal_Unicode(0x2518); break;
539             }
540 
541             if ( !mnHalfCharWidth )
542                 mnHalfCharWidth = rInf.GetTxtSize( aOutString ).Width() / 2;
543 
544             Point aOldPos = rInf.GetPos();
545             Point aNewPos( aOldPos );
546             aNewPos.X() = aNewPos.X() + ( Width() / 2 ) - mnHalfCharWidth;
547             const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aNewPos );
548 
549             rInf.DrawText( aOutString, *this );
550 
551             const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aOldPos );
552         }
553     }
554 }
555 
556 /*************************************************************************
557  *              virtual SwControlCharPortion::Format()
558  *************************************************************************/
559 
560 sal_Bool SwControlCharPortion::Format( SwTxtFormatInfo &rInf )
561 {
562     const SwLinePortion* pRoot = rInf.GetRoot();
563     Width( 0 );
564     Height( pRoot->Height() );
565     SetAscent( pRoot->GetAscent() );
566 
567     return sal_False;
568 }
569 
570 /*************************************************************************
571  *              virtual SwControlCharPortion::GetViewWidth()
572  *************************************************************************/
573 
574 KSHORT SwControlCharPortion::GetViewWidth( const SwTxtSizeInfo& rInf ) const
575 {
576     if( !mnViewWidth )
577         mnViewWidth = rInf.GetTxtSize( ' ' ).Width();
578 
579     return mnViewWidth;
580 }
581