1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: txtfld.cxx,v $
10 * $Revision: 1.30.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include "hintids.hxx"
38 #include <charfmt.hxx>
40 #include "viewsh.hxx" // NewFldPortion, GetDoc()
41 #include "doc.hxx" // NewFldPortion, GetSysFldType()
42 #include "rootfrm.hxx" // Info ueber virt. PageNumber
43 #include "pagefrm.hxx" // NewFldPortion, GetVirtPageNum()
44 #include "ndtxt.hxx" // NewNumberPortion, pHints->GetNum()
45 #include "fldbas.hxx" // SwField
46 #include "viewopt.hxx" // SwViewOptions
47 #include "flyfrm.hxx" //IsInBody()
48 #include "viewimp.hxx"
49 #include "txtatr.hxx" // SwTxtFld
51 #include "swfont.hxx" // NewFldPortion, new SwFont
52 #include "fntcache.hxx" // NewFldPortion, SwFntAccess
54 #include "porftn.hxx" // NewExtraPortion
55 #include "porref.hxx" // NewExtraPortion
56 #include "portox.hxx" // NewExtraPortion
57 #include "porhyph.hxx" // NewExtraPortion
58 #include "porfly.hxx" // NewExtraPortion
59 #include "itrform2.hxx" // SwTxtFormatter
63 #include "docufld.hxx"
64 #include "pagedesc.hxx" // NewFldPortion, GetNum()
65 #include <pormulti.hxx> // SwMultiPortion
66 #include "fmtmeta.hxx" // lcl_NewMetaPortion
69 /*************************************************************************
70 * SwTxtFormatter::NewFldPortion()
71 *************************************************************************/
74 sal_Bool
lcl_IsInBody( SwFrm
*pFrm
)
76 if ( pFrm
->IsInDocBody() )
80 const SwFrm
*pTmp
= pFrm
;
82 while ( 0 != (pFly
= pTmp
->FindFlyFrm()) )
83 pTmp
= pFly
->GetAnchorFrm();
84 return pTmp
->IsInDocBody();
89 SwExpandPortion
*SwTxtFormatter::NewFldPortion( SwTxtFormatInfo
&rInf
,
90 const SwTxtAttr
*pHint
) const
92 SwExpandPortion
*pRet
= 0;
93 SwFrm
*pFrame
= (SwFrm
*)pFrm
;
94 SwField
*pFld
= (SwField
*)pHint
->GetFld().GetFld();
95 const sal_Bool bName
= rInf
.GetOpt().IsFldName();
97 SwCharFmt
* pChFmt
= 0;
98 sal_Bool bNewFlyPor
= sal_False
,
102 ((SwTxtFormatter
*)this)->SeekAndChg( rInf
);
103 if (pFld
->GetLanguage() != GetFnt()->GetLanguage())
105 pFld
->SetLanguage( GetFnt()->GetLanguage() );
106 // let the visual note know about its new language
107 if (pFld
->GetTyp()->Which()==RES_POSTITFLD
)
108 const_cast<SwFmtFld
*> (&pHint
->GetFld())->Broadcast( SwFmtFldHint( &pHint
->GetFld(), SWFMTFLD_LANGUAGE
) );
111 ViewShell
*pSh
= rInf
.GetVsh();
112 sal_Bool bPlaceHolder
= sal_False
;
114 switch( pFld
->GetTyp()->Which() )
118 pRet
= new SwPostItsPortion( RES_SCRIPTFLD
== pFld
->GetTyp()->Which() );
121 case RES_COMBINED_CHARS
:
123 String
sStr( pFld
->GetCntnt( bName
));
125 pRet
= new SwFldPortion( sStr
);
127 pRet
= new SwCombinedPortion( sStr
);
131 case RES_HIDDENTXTFLD
:
132 pRet
= new SwHiddenPortion(pFld
->GetCntnt( bName
));
136 if( !bName
&& pSh
&& !pSh
->Imp()->IsUpdateExpFlds() )
138 ((SwChapterField
*)pFld
)->ChangeExpansion( pFrame
,
139 &((SwTxtFld
*)pHint
)->GetTxtNode() );
141 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
145 if( !bName
&& pSh
&& !pSh
->Imp()->IsUpdateExpFlds() )
146 ((SwDocStatField
*)pFld
)->ChangeExpansion( pFrame
);
147 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
150 case RES_PAGENUMBERFLD
:
152 if( !bName
&& pSh
&& !pSh
->Imp()->IsUpdateExpFlds() )
154 SwPageNumberFieldType
*pPageNr
= (SwPageNumberFieldType
*)pFld
->GetTyp();
156 const SwRootFrm
* pTmpRootFrm
= pSh
->GetLayout();
157 const sal_Bool bVirt
= pTmpRootFrm
->IsVirtPageNum();
159 SwDoc
* pDoc
= pSh
->GetDoc();
160 MSHORT nVirtNum
= pFrame
->GetVirtPageNum();
161 MSHORT nNumPages
= pTmpRootFrm
->GetPageNum();
162 sal_Int16 nNumFmt
= -1;
163 if(SVX_NUM_PAGEDESC
== pFld
->GetFormat())
164 nNumFmt
= pFrame
->FindPageFrm()->GetPageDesc()->GetNumType().GetNumberingType();
166 pPageNr
->ChangeExpansion( pDoc
, nVirtNum
, nNumPages
,
167 bVirt
, nNumFmt
> -1 ? &nNumFmt
: 0);
169 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
174 if( !bName
&& pSh
&& !pSh
->Imp()->IsUpdateExpFlds() )
176 SwGetExpField
* pExpFld
= (SwGetExpField
*)pFld
;
177 if( !::lcl_IsInBody( pFrame
) )
179 pExpFld
->ChgBodyTxtFlag( sal_False
);
180 pExpFld
->ChangeExpansion( *pFrame
, *((SwTxtFld
*)pHint
) );
182 else if( !pExpFld
->IsInBodyTxt() )
184 // war vorher anders, also erst expandieren, dann umsetzen!!
185 pExpFld
->ChangeExpansion( *pFrame
, *((SwTxtFld
*)pHint
) );
186 pExpFld
->ChgBodyTxtFlag( sal_True
);
189 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
196 SwDBField
* pDBFld
= (SwDBField
*)pFld
;
197 pDBFld
->ChgBodyTxtFlag( ::lcl_IsInBody( pFrame
) );
198 /* Solange das ChangeExpansion auskommentiert ist.
199 * Aktualisieren in Kopf/Fuszeilen geht aktuell nicht.
200 if( !::lcl_IsInBody( pFrame ) )
202 pDBFld->ChgBodyTxtFlag( sal_False );
203 pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
205 else if( !pDBFld->IsInBodyTxt() )
207 // war vorher anders, also erst expandieren, dann umsetzen!!
208 pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
209 pDBFld->ChgBodyTxtFlag( sal_True );
213 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
216 case RES_REFPAGEGETFLD
:
217 if( !bName
&& pSh
&& !pSh
->Imp()->IsUpdateExpFlds() )
218 ((SwRefPageGetField
*)pFld
)->ChangeExpansion( pFrame
, (SwTxtFld
*)pHint
);
219 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
) );
222 case RES_JUMPEDITFLD
:
224 pChFmt
= ((SwJumpEditField
*)pFld
)->GetCharFmt();
225 bNewFlyPor
= sal_True
;
226 bPlaceHolder
= sal_True
;
231 pRet
= new SwFldPortion(pFld
->GetCntnt( bName
) );
240 pTmpFnt
= new SwFont( *pFnt
);
243 SwAttrPool
* pPool
= pChFmt
->GetAttrSet().GetPool();
244 SfxItemSet
aSet( *pPool
, RES_CHRATR_BEGIN
, RES_CHRATR_END
);
245 SfxItemSet
aTmpSet( aSet
);
246 pFrm
->GetTxtNode()->GetAttr(aSet
,rInf
.GetIdx(),rInf
.GetIdx()+1);
247 aTmpSet
.Set( pChFmt
->GetAttrSet() );
248 aTmpSet
.Differentiate( aSet
);
249 if( aTmpSet
.Count() )
250 pTmpFnt
->SetDiffFnt( &aTmpSet
, pFrm
->GetTxtNode()->getIDocumentSettingAccess() );
253 pTmpFnt
->SetDiffFnt( &pChFmt
->GetAttrSet(), pFrm
->GetTxtNode()->getIDocumentSettingAccess() );
255 pRet
= new SwFldPortion( pFld
->GetCntnt( bName
), pTmpFnt
, bPlaceHolder
);
261 /*************************************************************************
262 * SwTxtFormatter::TryNewNoLengthPortion()
263 *************************************************************************/
265 SwFldPortion
* lcl_NewMetaPortion(SwTxtAttr
& rHint
, const bool bPrefix
)
267 ::sw::Meta
*const pMeta(
268 static_cast<SwFmtMeta
&>(rHint
.GetAttr()).GetMeta() );
270 ::sw::MetaField
*const pField( dynamic_cast< ::sw::MetaField
* >(pMeta
) );
271 OSL_ENSURE(pField
, "lcl_NewMetaPortion: no meta field?");
274 pField
->GetPrefixAndSuffix((bPrefix
) ? &fix
: 0, (bPrefix
) ? 0 : &fix
);
276 return new SwFldPortion( fix
);
279 /** Try to create a new portion with zero length, for an end of a hint
280 (where there is no CH_TXTATR). Because there may be multiple hint ends at a
281 given index, m_nHintEndIndex is used to keep track of the already created
282 portions. But the portions created here may actually be deleted again,
283 due to UnderFlow. In that case, m_nHintEndIndex must be decremented,
284 so the portion will be created again on the next line.
287 SwTxtFormatter::TryNewNoLengthPortion(SwTxtFormatInfo
& rInfo
)
291 const xub_StrLen
nIdx(rInfo
.GetIdx());
292 while (m_nHintEndIndex
< pHints
->GetEndCount())
294 SwTxtAttr
& rHint( *pHints
->GetEnd(m_nHintEndIndex
) );
295 xub_StrLen
const nEnd( *rHint
.GetAnyEnd() );
303 if (RES_TXTATR_METAFIELD
== rHint
.Which())
305 SwFldPortion
*const pPortion(
306 lcl_NewMetaPortion(rHint
, false));
307 pPortion
->SetNoLength(); // no CH_TXTATR at hint end!
316 /*************************************************************************
317 * SwTxtFormatter::NewExtraPortion()
318 *************************************************************************/
320 SwLinePortion
*SwTxtFormatter::NewExtraPortion( SwTxtFormatInfo
&rInf
)
322 SwTxtAttr
*pHint
= GetAttr( rInf
.GetIdx() );
323 SwLinePortion
*pRet
= 0;
326 #if OSL_DEBUG_LEVEL > 1
327 // aDbstream << "NewExtraPortion: hint not found?" << endl;
329 pRet
= new SwTxtPortion
;
335 switch( pHint
->Which() )
337 case RES_TXTATR_FLYCNT
:
339 pRet
= NewFlyCntPortion( rInf
, pHint
);
342 case RES_TXTATR_FTN
:
344 pRet
= NewFtnPortion( rInf
, pHint
);
347 case RES_TXTATR_FIELD
:
349 pRet
= NewFldPortion( rInf
, pHint
);
352 case RES_TXTATR_REFMARK
:
354 pRet
= new SwIsoRefPortion
;
357 case RES_TXTATR_TOXMARK
:
359 pRet
= new SwIsoToxPortion
;
362 case RES_TXTATR_METAFIELD
:
364 pRet
= lcl_NewMetaPortion( *pHint
, true );
371 #if OSL_DEBUG_LEVEL > 1
372 // aDbstream << "NewExtraPortion: unknown hint" << endl;
374 const XubString aNothing
;
375 pRet
= new SwFldPortion( aNothing
);
381 /*************************************************************************
382 * SwTxtFormatter::NewNumberPortion()
383 *************************************************************************/
386 SwNumberPortion
*SwTxtFormatter::NewNumberPortion( SwTxtFormatInfo
&rInf
) const
388 if( rInf
.IsNumDone() || rInf
.GetTxtStart() != nStart
389 || rInf
.GetTxtStart() != rInf
.GetIdx() )
392 SwNumberPortion
*pRet
= 0;
393 const SwTxtNode
* pTxtNd
= GetTxtFrm()->GetTxtNode();
394 const SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
396 // hat ein "gueltige" Nummer ?
397 if( pTxtNd
->IsNumbered() && pTxtNd
->IsCountedInList())
399 const SwNumFmt
&rNumFmt
= pNumRule
->Get( static_cast<USHORT
>(pTxtNd
->GetActualListLevel()) );
400 const sal_Bool bLeft
= SVX_ADJUST_LEFT
== rNumFmt
.GetNumAdjust();
401 const sal_Bool bCenter
= SVX_ADJUST_CENTER
== rNumFmt
.GetNumAdjust();
402 // --> OD 2008-01-23 #newlistlevelattrs#
403 const bool bLabelAlignmentPosAndSpaceModeActive(
404 rNumFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
);
405 const KSHORT nMinDist
= bLabelAlignmentPosAndSpaceModeActive
406 ? 0 : rNumFmt
.GetCharTextDistance();
409 if( SVX_NUM_BITMAP
== rNumFmt
.GetNumberingType() )
411 // --> OD 2008-01-23 #newlistlevelattrs#
412 pRet
= new SwGrfNumPortion( (SwFrm
*)GetTxtFrm(),
413 pTxtNd
->GetLabelFollowedBy(),
415 rNumFmt
.GetGraphicOrientation(),
416 rNumFmt
.GetGraphicSize(),
417 bLeft
, bCenter
, nMinDist
,
418 bLabelAlignmentPosAndSpaceModeActive
);
420 long nTmpA
= rInf
.GetLast()->GetAscent();
421 long nTmpD
= rInf
.GetLast()->Height() - nTmpA
;
423 ((SwGrfNumPortion
*)pRet
)->SetBase( nTmpA
, nTmpD
, nTmpA
, nTmpD
);
427 // Der SwFont wird dynamisch angelegt und im CTOR uebergeben,
428 // weil das CharFmt nur einen SV-Font zurueckliefert.
429 // Im Dtor vom SwNumberPortion wird der SwFont deletet.
431 const SwAttrSet
* pFmt
= rNumFmt
.GetCharFmt() ?
432 &rNumFmt
.GetCharFmt()->GetAttrSet() :
434 const IDocumentSettingAccess
* pIDSA
= pTxtNd
->getIDocumentSettingAccess();
436 if( SVX_NUM_CHAR_SPECIAL
== rNumFmt
.GetNumberingType() )
438 const Font
*pFmtFnt
= rNumFmt
.GetBulletFont();
441 // Build a new bullet font basing on the current paragraph font:
443 pNumFnt
= new SwFont( &rInf
.GetCharAttr(), pIDSA
);
445 // --> FME 2005-08-11 #i53199#
446 if ( !pIDSA
->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT
) )
449 // Underline style of paragraph font should not be considered
450 // Overline style of paragraph font should not be considered
451 // Weight style of paragraph font should not be considered
452 // Posture style of paragraph font should not be considered
453 pNumFnt
->SetUnderline( UNDERLINE_NONE
);
454 pNumFnt
->SetOverline( UNDERLINE_NONE
);
455 pNumFnt
->SetItalic( ITALIC_NONE
, SW_LATIN
);
456 pNumFnt
->SetItalic( ITALIC_NONE
, SW_CJK
);
457 pNumFnt
->SetItalic( ITALIC_NONE
, SW_CTL
);
458 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_LATIN
);
459 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_CJK
);
460 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_CTL
);
464 // Apply the explicit attributes from the character style
465 // associated with the numering to the new bullet font.
468 pNumFnt
->SetDiffFnt( pFmt
, pIDSA
);
472 const BYTE nAct
= pNumFnt
->GetActual();
473 pNumFnt
->SetFamily( pFmtFnt
->GetFamily(), nAct
);
474 pNumFnt
->SetName( pFmtFnt
->GetName(), nAct
);
475 pNumFnt
->SetStyleName( pFmtFnt
->GetStyleName(), nAct
);
476 pNumFnt
->SetCharSet( pFmtFnt
->GetCharSet(), nAct
);
477 pNumFnt
->SetPitch( pFmtFnt
->GetPitch(), nAct
);
480 // we do not allow a vertical font
481 pNumFnt
->SetVertical( pNumFnt
->GetOrientation(),
482 pFrm
->IsVertical() );
484 // --> OD 2008-01-23 #newlistelevelattrs#
485 pRet
= new SwBulletPortion( rNumFmt
.GetBulletChar(),
486 pTxtNd
->GetLabelFollowedBy(),
488 bLeft
, bCenter
, nMinDist
,
489 bLabelAlignmentPosAndSpaceModeActive
);
494 // --> OD 2006-06-02 #b6432095#
495 // use method <SwNumRule::MakeNumString(..)> instead of
496 // method <SwTxtNode::GetNumString()>, because for levels with
497 // numbering none the prefix and the suffix strings have to be provided.
498 // XubString aTxt( pTxtNd->GetNumString() );
499 XubString
aTxt( pNumRule
->MakeNumString( *(pTxtNd
->GetNum()) ) );
501 // --> OD 2008-01-23 #newlistlevelattrs#
502 if ( aTxt
.Len() > 0 )
504 aTxt
.Insert( pTxtNd
->GetLabelFollowedBy() );
508 // 7974: Nicht nur eine Optimierung...
509 // Eine Numberportion ohne Text wird die Breite von 0
510 // erhalten. Die nachfolgende Textportion wird im BreakLine
511 // in das BreakCut laufen, obwohl rInf.GetLast()->GetFlyPortion()
516 // Build a new numbering font basing on the current paragraph font:
518 pNumFnt
= new SwFont( &rInf
.GetCharAttr(), pIDSA
);
520 // --> FME 2005-08-11 #i53199#
521 if ( !pIDSA
->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT
) )
524 // Underline style of paragraph font should not be considered
525 pNumFnt
->SetUnderline( UNDERLINE_NONE
);
526 // Overline style of paragraph font should not be considered
527 pNumFnt
->SetOverline( UNDERLINE_NONE
);
532 // Apply the explicit attributes from the character style
533 // associated with the numering to the new bullet font.
536 pNumFnt
->SetDiffFnt( pFmt
, pIDSA
);
538 // we do not allow a vertical font
539 pNumFnt
->SetVertical( pNumFnt
->GetOrientation(), pFrm
->IsVertical() );
541 // --> OD 2008-01-23 #newlistlevelattrs#
542 pRet
= new SwNumberPortion( aTxt
, pNumFnt
,
543 bLeft
, bCenter
, nMinDist
,
544 bLabelAlignmentPosAndSpaceModeActive
);