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 #include "hintids.hxx" 29 #include <fmtfld.hxx> 30 #include <txtfld.hxx> 31 #include <charfmt.hxx> 32 33 #include "viewsh.hxx" // NewFldPortion, GetDoc() 34 #include "doc.hxx" // NewFldPortion, GetSysFldType() 35 #include "rootfrm.hxx" // Info ueber virt. PageNumber 36 #include "pagefrm.hxx" // NewFldPortion, GetVirtPageNum() 37 #include "ndtxt.hxx" // NewNumberPortion, pHints->GetNum() 38 #include "fldbas.hxx" // SwField 39 #include "viewopt.hxx" // SwViewOptions 40 #include "flyfrm.hxx" //IsInBody() 41 #include "viewimp.hxx" 42 #include "txtatr.hxx" // SwTxtFld 43 #include "txtcfg.hxx" 44 #include "swfont.hxx" // NewFldPortion, new SwFont 45 #include "fntcache.hxx" // NewFldPortion, SwFntAccess 46 #include "porfld.hxx" 47 #include "porftn.hxx" // NewExtraPortion 48 #include "porref.hxx" // NewExtraPortion 49 #include "portox.hxx" // NewExtraPortion 50 #include "porhyph.hxx" // NewExtraPortion 51 #include "porfly.hxx" // NewExtraPortion 52 #include "itrform2.hxx" // SwTxtFormatter 53 #include "chpfld.hxx" 54 #include "dbfld.hxx" 55 #include "expfld.hxx" 56 #include "docufld.hxx" 57 #include "pagedesc.hxx" // NewFldPortion, GetNum() 58 #include <pormulti.hxx> // SwMultiPortion 59 #include "fmtmeta.hxx" // lcl_NewMetaPortion 60 61 62 /************************************************************************* 63 * SwTxtFormatter::NewFldPortion() 64 *************************************************************************/ 65 66 67 sal_Bool lcl_IsInBody( SwFrm *pFrm ) 68 { 69 if ( pFrm->IsInDocBody() ) 70 return sal_True; 71 else 72 { 73 const SwFrm *pTmp = pFrm; 74 const SwFlyFrm *pFly; 75 while ( 0 != (pFly = pTmp->FindFlyFrm()) ) 76 pTmp = pFly->GetAnchorFrm(); 77 return pTmp->IsInDocBody(); 78 } 79 } 80 81 82 SwExpandPortion *SwTxtFormatter::NewFldPortion( SwTxtFormatInfo &rInf, 83 const SwTxtAttr *pHint ) const 84 { 85 SwExpandPortion *pRet = 0; 86 SwFrm *pFrame = (SwFrm*)pFrm; 87 SwField *pFld = (SwField*)pHint->GetFld().GetFld(); 88 const sal_Bool bName = rInf.GetOpt().IsFldName(); 89 90 SwCharFmt* pChFmt = 0; 91 sal_Bool bNewFlyPor = sal_False, 92 bINet = sal_False; 93 94 // set language 95 ((SwTxtFormatter*)this)->SeekAndChg( rInf ); 96 if (pFld->GetLanguage() != GetFnt()->GetLanguage()) 97 { 98 pFld->SetLanguage( GetFnt()->GetLanguage() ); 99 // let the visual note know about its new language 100 if (pFld->GetTyp()->Which()==RES_POSTITFLD) 101 const_cast<SwFmtFld*> (&pHint->GetFld())->Broadcast( SwFmtFldHint( &pHint->GetFld(), SWFMTFLD_LANGUAGE ) ); 102 } 103 104 ViewShell *pSh = rInf.GetVsh(); 105 SwDoc *const pDoc( (pSh) ? pSh->GetDoc() : 0 ); 106 bool const bInClipboard( (pDoc) ? pDoc->IsClipBoard() : true ); 107 sal_Bool bPlaceHolder = sal_False; 108 109 switch( pFld->GetTyp()->Which() ) 110 { 111 case RES_SCRIPTFLD: 112 case RES_POSTITFLD: 113 pRet = new SwPostItsPortion( RES_SCRIPTFLD == pFld->GetTyp()->Which() ); 114 break; 115 116 case RES_COMBINED_CHARS: 117 { 118 if( bName ) 119 { 120 String const sName( pFld->GetFieldName() ); 121 pRet = new SwFldPortion(sName); 122 } 123 else 124 { 125 String const sContent( pFld->ExpandField(bInClipboard) ); 126 pRet = new SwCombinedPortion(sContent); 127 } 128 } 129 break; 130 131 case RES_HIDDENTXTFLD: 132 { 133 String const str( (bName) 134 ? pFld->GetFieldName() 135 : pFld->ExpandField(bInClipboard) ); 136 pRet = new SwHiddenPortion(str); 137 } 138 break; 139 140 case RES_CHAPTERFLD: 141 if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() ) 142 { 143 ((SwChapterField*)pFld)->ChangeExpansion( pFrame, 144 &((SwTxtFld*)pHint)->GetTxtNode() ); 145 } 146 { 147 String const str( (bName) 148 ? pFld->GetFieldName() 149 : pFld->ExpandField(bInClipboard) ); 150 pRet = new SwFldPortion( str ); 151 } 152 break; 153 154 case RES_DOCSTATFLD: 155 if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() ) 156 { 157 ((SwDocStatField*)pFld)->ChangeExpansion( pFrame ); 158 } 159 { 160 String const str( (bName) 161 ? pFld->GetFieldName() 162 : pFld->ExpandField(bInClipboard) ); 163 pRet = new SwFldPortion( str ); 164 } 165 break; 166 167 case RES_PAGENUMBERFLD: 168 { 169 if( !bName && pSh && pSh->GetLayout() && !pSh->Imp()->IsUpdateExpFlds() )//swmod 080122 170 { 171 SwPageNumberFieldType *pPageNr = (SwPageNumberFieldType *)pFld->GetTyp(); 172 173 const SwRootFrm* pTmpRootFrm = pSh->GetLayout(); 174 const sal_Bool bVirt = pTmpRootFrm->IsVirtPageNum(); 175 176 MSHORT nVirtNum = pFrame->GetVirtPageNum(); 177 MSHORT nNumPages = pTmpRootFrm->GetPageNum(); 178 sal_Int16 nNumFmt = -1; 179 if(SVX_NUM_PAGEDESC == pFld->GetFormat()) 180 nNumFmt = pFrame->FindPageFrm()->GetPageDesc()->GetNumType().GetNumberingType(); 181 182 pPageNr->ChangeExpansion( pDoc, nVirtNum, nNumPages, 183 bVirt, nNumFmt > -1 ? &nNumFmt : 0); 184 } 185 { 186 String const str( (bName) 187 ? pFld->GetFieldName() 188 : pFld->ExpandField(bInClipboard) ); 189 pRet = new SwFldPortion( str ); 190 } 191 break; 192 } 193 case RES_GETEXPFLD: 194 { 195 if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() ) 196 { 197 SwGetExpField* pExpFld = (SwGetExpField*)pFld; 198 if( !::lcl_IsInBody( pFrame ) ) 199 { 200 pExpFld->ChgBodyTxtFlag( sal_False ); 201 pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) ); 202 } 203 else if( !pExpFld->IsInBodyTxt() ) 204 { 205 // war vorher anders, also erst expandieren, dann umsetzen!! 206 pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) ); 207 pExpFld->ChgBodyTxtFlag( sal_True ); 208 } 209 } 210 { 211 String const str( (bName) 212 ? pFld->GetFieldName() 213 : pFld->ExpandField(bInClipboard) ); 214 pRet = new SwFldPortion( str ); 215 } 216 break; 217 } 218 case RES_DBFLD: 219 { 220 if( !bName ) 221 { 222 SwDBField* pDBFld = (SwDBField*)pFld; 223 pDBFld->ChgBodyTxtFlag( ::lcl_IsInBody( pFrame ) ); 224 /* Solange das ChangeExpansion auskommentiert ist. 225 * Aktualisieren in Kopf/Fuszeilen geht aktuell nicht. 226 if( !::lcl_IsInBody( pFrame ) ) 227 { 228 pDBFld->ChgBodyTxtFlag( sal_False ); 229 pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint ); 230 } 231 else if( !pDBFld->IsInBodyTxt() ) 232 { 233 // war vorher anders, also erst expandieren, dann umsetzen!! 234 pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint ); 235 pDBFld->ChgBodyTxtFlag( sal_True ); 236 } 237 */ 238 } 239 { 240 String const str( (bName) 241 ? pFld->GetFieldName() 242 : pFld->ExpandField(bInClipboard) ); 243 pRet = new SwFldPortion(str); 244 } 245 break; 246 } 247 case RES_REFPAGEGETFLD: 248 if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() ) 249 { 250 ((SwRefPageGetField*)pFld)->ChangeExpansion( pFrame, (SwTxtFld*)pHint ); 251 } 252 { 253 String const str( (bName) 254 ? pFld->GetFieldName() 255 : pFld->ExpandField(bInClipboard) ); 256 pRet = new SwFldPortion(str); 257 } 258 break; 259 260 case RES_JUMPEDITFLD: 261 if( !bName ) 262 pChFmt = ((SwJumpEditField*)pFld)->GetCharFmt(); 263 bNewFlyPor = sal_True; 264 bPlaceHolder = sal_True; 265 break; 266 267 default: 268 { 269 String const str( (bName) 270 ? pFld->GetFieldName() 271 : pFld->ExpandField(bInClipboard) ); 272 pRet = new SwFldPortion(str); 273 } 274 } 275 276 if( bNewFlyPor ) 277 { 278 SwFont *pTmpFnt = 0; 279 if( !bName ) 280 { 281 pTmpFnt = new SwFont( *pFnt ); 282 if( bINet ) 283 { 284 SwAttrPool* pPool = pChFmt->GetAttrSet().GetPool(); 285 SfxItemSet aSet( *pPool, RES_CHRATR_BEGIN, RES_CHRATR_END ); 286 SfxItemSet aTmpSet( aSet ); 287 pFrm->GetTxtNode()->GetAttr(aSet,rInf.GetIdx(),rInf.GetIdx()+1); 288 aTmpSet.Set( pChFmt->GetAttrSet() ); 289 aTmpSet.Differentiate( aSet ); 290 if( aTmpSet.Count() ) 291 pTmpFnt->SetDiffFnt( &aTmpSet, pFrm->GetTxtNode()->getIDocumentSettingAccess() ); 292 } 293 else 294 pTmpFnt->SetDiffFnt( &pChFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() ); 295 } 296 { 297 String const str( (bName) 298 ? pFld->GetFieldName() 299 : pFld->ExpandField(bInClipboard) ); 300 pRet = new SwFldPortion(str, pTmpFnt, bPlaceHolder); 301 } 302 } 303 304 return pRet; 305 } 306 307 /************************************************************************* 308 * SwTxtFormatter::TryNewNoLengthPortion() 309 *************************************************************************/ 310 311 SwFldPortion * lcl_NewMetaPortion(SwTxtAttr & rHint, const bool bPrefix) 312 { 313 ::sw::Meta *const pMeta( 314 static_cast<SwFmtMeta &>(rHint.GetAttr()).GetMeta() ); 315 ::rtl::OUString fix; 316 ::sw::MetaField *const pField( dynamic_cast< ::sw::MetaField * >(pMeta) ); 317 OSL_ENSURE(pField, "lcl_NewMetaPortion: no meta field?"); 318 if (pField) 319 { 320 pField->GetPrefixAndSuffix((bPrefix) ? &fix : 0, (bPrefix) ? 0 : &fix); 321 } 322 return new SwFldPortion( fix ); 323 } 324 325 /** Try to create a new portion with zero length, for an end of a hint 326 (where there is no CH_TXTATR). Because there may be multiple hint ends at a 327 given index, m_nHintEndIndex is used to keep track of the already created 328 portions. But the portions created here may actually be deleted again, 329 due to UnderFlow. In that case, m_nHintEndIndex must be decremented, 330 so the portion will be created again on the next line. 331 */ 332 SwExpandPortion * 333 SwTxtFormatter::TryNewNoLengthPortion(SwTxtFormatInfo & rInfo) 334 { 335 if (pHints) 336 { 337 const xub_StrLen nIdx(rInfo.GetIdx()); 338 while (m_nHintEndIndex < pHints->GetEndCount()) 339 { 340 SwTxtAttr & rHint( *pHints->GetEnd(m_nHintEndIndex) ); 341 xub_StrLen const nEnd( *rHint.GetAnyEnd() ); 342 if (nEnd > nIdx) 343 { 344 break; 345 } 346 ++m_nHintEndIndex; 347 if (nEnd == nIdx) 348 { 349 if (RES_TXTATR_METAFIELD == rHint.Which()) 350 { 351 SwFldPortion *const pPortion( 352 lcl_NewMetaPortion(rHint, false)); 353 pPortion->SetNoLength(); // no CH_TXTATR at hint end! 354 return pPortion; 355 } 356 } 357 } 358 } 359 return 0; 360 } 361 362 /************************************************************************* 363 * SwTxtFormatter::NewExtraPortion() 364 *************************************************************************/ 365 366 SwLinePortion *SwTxtFormatter::NewExtraPortion( SwTxtFormatInfo &rInf ) 367 { 368 SwTxtAttr *pHint = GetAttr( rInf.GetIdx() ); 369 SwLinePortion *pRet = 0; 370 if( !pHint ) 371 { 372 #if OSL_DEBUG_LEVEL > 1 373 // aDbstream << "NewExtraPortion: hint not found?" << endl; 374 #endif 375 pRet = new SwTxtPortion; 376 pRet->SetLen( 1 ); 377 rInf.SetLen( 1 ); 378 return pRet; 379 } 380 381 switch( pHint->Which() ) 382 { 383 case RES_TXTATR_FLYCNT : 384 { 385 pRet = NewFlyCntPortion( rInf, pHint ); 386 break; 387 } 388 case RES_TXTATR_FTN : 389 { 390 pRet = NewFtnPortion( rInf, pHint ); 391 break; 392 } 393 case RES_TXTATR_FIELD : 394 { 395 pRet = NewFldPortion( rInf, pHint ); 396 break; 397 } 398 case RES_TXTATR_REFMARK : 399 { 400 pRet = new SwIsoRefPortion; 401 break; 402 } 403 case RES_TXTATR_TOXMARK : 404 { 405 pRet = new SwIsoToxPortion; 406 break; 407 } 408 case RES_TXTATR_METAFIELD: 409 { 410 pRet = lcl_NewMetaPortion( *pHint, true ); 411 break; 412 } 413 default: ; 414 } 415 if( !pRet ) 416 { 417 #if OSL_DEBUG_LEVEL > 1 418 // aDbstream << "NewExtraPortion: unknown hint" << endl; 419 #endif 420 const XubString aNothing; 421 pRet = new SwFldPortion( aNothing ); 422 rInf.SetLen( 1 ); 423 } 424 return pRet; 425 } 426 427 /************************************************************************* 428 * SwTxtFormatter::NewNumberPortion() 429 *************************************************************************/ 430 431 432 SwNumberPortion *SwTxtFormatter::NewNumberPortion( SwTxtFormatInfo &rInf ) const 433 { 434 if( rInf.IsNumDone() || rInf.GetTxtStart() != nStart 435 || rInf.GetTxtStart() != rInf.GetIdx() ) 436 return 0; 437 438 SwNumberPortion *pRet = 0; 439 const SwTxtNode* pTxtNd = GetTxtFrm()->GetTxtNode(); 440 const SwNumRule* pNumRule = pTxtNd->GetNumRule(); 441 442 // hat ein "gueltige" Nummer ? 443 if( pTxtNd->IsNumbered() && pTxtNd->IsCountedInList()) 444 { 445 const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()) ); 446 const sal_Bool bLeft = SVX_ADJUST_LEFT == rNumFmt.GetNumAdjust(); 447 const sal_Bool bCenter = SVX_ADJUST_CENTER == rNumFmt.GetNumAdjust(); 448 // --> OD 2008-01-23 #newlistlevelattrs# 449 const bool bLabelAlignmentPosAndSpaceModeActive( 450 rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ); 451 const KSHORT nMinDist = bLabelAlignmentPosAndSpaceModeActive 452 ? 0 : rNumFmt.GetCharTextDistance(); 453 // <-- 454 455 if( SVX_NUM_BITMAP == rNumFmt.GetNumberingType() ) 456 { 457 // --> OD 2008-01-23 #newlistlevelattrs# 458 pRet = new SwGrfNumPortion( (SwFrm*)GetTxtFrm(), 459 pTxtNd->GetLabelFollowedBy(), 460 rNumFmt.GetBrush(), 461 rNumFmt.GetGraphicOrientation(), 462 rNumFmt.GetGraphicSize(), 463 bLeft, bCenter, nMinDist, 464 bLabelAlignmentPosAndSpaceModeActive ); 465 // <-- 466 long nTmpA = rInf.GetLast()->GetAscent(); 467 long nTmpD = rInf.GetLast()->Height() - nTmpA; 468 if( !rInf.IsTest() ) 469 ((SwGrfNumPortion*)pRet)->SetBase( nTmpA, nTmpD, nTmpA, nTmpD ); 470 } 471 else 472 { 473 // Der SwFont wird dynamisch angelegt und im CTOR uebergeben, 474 // weil das CharFmt nur einen SV-Font zurueckliefert. 475 // Im Dtor vom SwNumberPortion wird der SwFont deletet. 476 SwFont *pNumFnt = 0; 477 const SwAttrSet* pFmt = rNumFmt.GetCharFmt() ? 478 &rNumFmt.GetCharFmt()->GetAttrSet() : 479 NULL; 480 const IDocumentSettingAccess* pIDSA = pTxtNd->getIDocumentSettingAccess(); 481 482 if( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() ) 483 { 484 const Font *pFmtFnt = rNumFmt.GetBulletFont(); 485 486 // 487 // Build a new bullet font basing on the current paragraph font: 488 // 489 pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA ); 490 491 // --> FME 2005-08-11 #i53199# 492 if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) ) 493 { 494 // i18463: 495 // Underline style of paragraph font should not be considered 496 // Overline style of paragraph font should not be considered 497 // Weight style of paragraph font should not be considered 498 // Posture style of paragraph font should not be considered 499 pNumFnt->SetUnderline( UNDERLINE_NONE ); 500 pNumFnt->SetOverline( UNDERLINE_NONE ); 501 pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN ); 502 pNumFnt->SetItalic( ITALIC_NONE, SW_CJK ); 503 pNumFnt->SetItalic( ITALIC_NONE, SW_CTL ); 504 pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN ); 505 pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK ); 506 pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL ); 507 } 508 509 // 510 // Apply the explicit attributes from the character style 511 // associated with the numering to the new bullet font. 512 // 513 if( pFmt ) 514 pNumFnt->SetDiffFnt( pFmt, pIDSA ); 515 516 if ( pFmtFnt ) 517 { 518 const sal_uInt8 nAct = pNumFnt->GetActual(); 519 pNumFnt->SetFamily( pFmtFnt->GetFamily(), nAct ); 520 pNumFnt->SetName( pFmtFnt->GetName(), nAct ); 521 pNumFnt->SetStyleName( pFmtFnt->GetStyleName(), nAct ); 522 pNumFnt->SetCharSet( pFmtFnt->GetCharSet(), nAct ); 523 pNumFnt->SetPitch( pFmtFnt->GetPitch(), nAct ); 524 } 525 526 // we do not allow a vertical font 527 pNumFnt->SetVertical( pNumFnt->GetOrientation(), 528 pFrm->IsVertical() ); 529 530 // --> OD 2008-01-23 #newlistelevelattrs# 531 pRet = new SwBulletPortion( rNumFmt.GetBulletChar(), 532 pTxtNd->GetLabelFollowedBy(), 533 pNumFnt, 534 bLeft, bCenter, nMinDist, 535 bLabelAlignmentPosAndSpaceModeActive ); 536 // <-- 537 } 538 else 539 { 540 XubString aTxt( pTxtNd->GetNumString() ); 541 // --> OD 2008-01-23 #newlistlevelattrs# 542 if ( aTxt.Len() > 0 ) 543 { 544 aTxt.Insert( pTxtNd->GetLabelFollowedBy() ); 545 } 546 // <-- 547 548 // 7974: Nicht nur eine Optimierung... 549 // Eine Numberportion ohne Text wird die Breite von 0 550 // erhalten. Die nachfolgende Textportion wird im BreakLine 551 // in das BreakCut laufen, obwohl rInf.GetLast()->GetFlyPortion() 552 // vorliegt! 553 if( aTxt.Len() ) 554 { 555 // 556 // Build a new numbering font basing on the current paragraph font: 557 // 558 pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA ); 559 560 // --> FME 2005-08-11 #i53199# 561 if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) ) 562 { 563 // i18463: 564 // Underline style of paragraph font should not be considered 565 pNumFnt->SetUnderline( UNDERLINE_NONE ); 566 // Overline style of paragraph font should not be considered 567 pNumFnt->SetOverline( UNDERLINE_NONE ); 568 } 569 570 571 // 572 // Apply the explicit attributes from the character style 573 // associated with the numering to the new bullet font. 574 // 575 if( pFmt ) 576 pNumFnt->SetDiffFnt( pFmt, pIDSA ); 577 578 // we do not allow a vertical font 579 pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() ); 580 581 // --> OD 2008-01-23 #newlistlevelattrs# 582 pRet = new SwNumberPortion( aTxt, pNumFnt, 583 bLeft, bCenter, nMinDist, 584 bLabelAlignmentPosAndSpaceModeActive ); 585 // <-- 586 } 587 } 588 } 589 } 590 return pRet; 591 } 592 593