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 <errhdl.hxx> // ASSERT 29 #include <atrhndl.hxx> 30 #include <svl/itemiter.hxx> 31 #include <vcl/outdev.hxx> 32 #include <editeng/cmapitem.hxx> 33 #include <editeng/colritem.hxx> 34 #include <editeng/cntritem.hxx> 35 #include <editeng/crsditem.hxx> 36 #include <editeng/escpitem.hxx> 37 #include <editeng/fontitem.hxx> 38 #include <editeng/fhgtitem.hxx> 39 #include <editeng/kernitem.hxx> 40 #include <editeng/charreliefitem.hxx> 41 #include <editeng/langitem.hxx> 42 #include <editeng/postitem.hxx> 43 #include <editeng/shdditem.hxx> 44 #include <editeng/udlnitem.hxx> 45 #include <editeng/wghtitem.hxx> 46 #include <editeng/wrlmitem.hxx> 47 #include <editeng/akrnitem.hxx> 48 #include <editeng/blnkitem.hxx> 49 #include <editeng/charrotateitem.hxx> 50 #include <editeng/emphitem.hxx> 51 #include <editeng/charscaleitem.hxx> 52 #include <editeng/twolinesitem.hxx> 53 #include <editeng/charhiddenitem.hxx> 54 #include <viewopt.hxx> 55 #include <charfmt.hxx> 56 #include <fchrfmt.hxx> 57 #include <fmtautofmt.hxx> 58 #include <editeng/brshitem.hxx> 59 #include <fmtinfmt.hxx> 60 #include <txtinet.hxx> 61 #include <IDocumentSettingAccess.hxx> 62 #include <viewsh.hxx> // ViewShell 63 #include <viewopt.hxx> // SwViewOptions 64 65 #define STACK_INCREMENT 4 66 67 /************************************************************************* 68 * Attribute to Stack Mapping 69 * 70 * Attributes applied to a text are pushed on different stacks. For each 71 * stack, the top most attribute on the stack is valid. Because some 72 * kinds of attributes have to be pushed to the same stacks we map their 73 * ids to stack ids 74 * Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx == 35 ) 75 * are stored in the defaultitem-cache, if you add one, you have to increase 76 * NUM_DEFAULT_VALUES. 77 * Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx. 78 *************************************************************************/ 79 80 const sal_uInt8 StackPos[ static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) - 81 static_cast<sal_uInt16>(RES_CHRATR_BEGIN) + 1 ] = 82 { 83 0, // // 0 84 1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN // 1 85 0, // RES_CHRATR_CHARSETCOLOR, // 2 86 2, // RES_CHRATR_COLOR, // 3 87 3, // RES_CHRATR_CONTOUR, // 4 88 4, // RES_CHRATR_CROSSEDOUT, // 5 89 5, // RES_CHRATR_ESCAPEMENT, // 6 90 6, // RES_CHRATR_FONT, // 7 91 7, // RES_CHRATR_FONTSIZE, // 8 92 8, // RES_CHRATR_KERNING, // 9 93 9, // RES_CHRATR_LANGUAGE, // 10 94 10, // RES_CHRATR_POSTURE, // 11 95 0, // RES_CHRATR_PROPORTIONALFONTSIZE, // 12 96 11, // RES_CHRATR_SHADOWED, // 13 97 12, // RES_CHRATR_UNDERLINE, // 14 98 13, // RES_CHRATR_WEIGHT, // 15 99 14, // RES_CHRATR_WORDLINEMODE, // 16 100 15, // RES_CHRATR_AUTOKERN, // 17 101 16, // RES_CHRATR_BLINK, // 18 102 17, // RES_CHRATR_NOHYPHEN, // 19 103 0, // RES_CHRATR_NOLINEBREAK, // 20 104 18, // RES_CHRATR_BACKGROUND, // 21 105 19, // RES_CHRATR_CJK_FONT, // 22 106 20, // RES_CHRATR_CJK_FONTSIZE, // 23 107 21, // RES_CHRATR_CJK_LANGUAGE, // 24 108 22, // RES_CHRATR_CJK_POSTURE, // 25 109 23, // RES_CHRATR_CJK_WEIGHT, // 26 110 24, // RES_CHRATR_CTL_FONT, // 27 111 25, // RES_CHRATR_CTL_FONTSIZE, // 28 112 26, // RES_CHRATR_CTL_LANGUAGE, // 29 113 27, // RES_CHRATR_CTL_POSTURE, // 30 114 28, // RES_CHRATR_CTL_WEIGHT, // 31 115 29, // RES_CHRATR_ROTATE, // 32 116 30, // RES_CHRATR_EMPHASIS_MARK, // 33 117 31, // RES_CHRATR_TWO_LINES, // 34 118 32, // RES_CHRATR_SCALEW, // 35 119 33, // RES_CHRATR_RELIEF, // 36 120 34, // RES_CHRATR_HIDDEN, // 37 121 35, // RES_CHRATR_OVERLINE, // 38 122 0, // RES_CHRATR_DUMMY1, // 39 123 0, // RES_CHRATR_DUMMY2, // 40 124 0, // RES_CHRATR_BIDIRTL 125 0, // RES_CHRATR_IDCTHINT 126 36, // RES_TXTATR_REFMARK, // 41 127 37, // RES_TXTATR_TOXMARK, // 42 128 38, // RES_TXTATR_META, // 43 129 38, // RES_TXTATR_METAFIELD, // 44 130 0, // RES_TXTATR_AUTOFMT, // 45 131 0, // RES_TXTATR_INETFMT // 46 132 0, // RES_TXTATR_CHARFMT, // 47 133 39, // RES_TXTATR_CJK_RUBY, // 48 134 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 49 135 0, // RES_TXTATR_DUMMY5 // 50 136 }; 137 138 /************************************************************************* 139 * CharFmt::GetItem 140 * returns the item set associated with an character/inet/auto style 141 *************************************************************************/ 142 143 namespace CharFmt 144 { 145 146 const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr ) 147 { 148 const SfxItemSet* pSet = 0; 149 150 if ( RES_TXTATR_AUTOFMT == rAttr.Which() ) 151 { 152 pSet = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle().get(); 153 } 154 else 155 { 156 // aus der Vorlage die Attribute holen: 157 SwCharFmt* pFmt = RES_TXTATR_INETFMT == rAttr.Which() ? 158 ((SwFmtINetFmt&)rAttr).GetTxtINetFmt()->GetCharFmt() : 159 ((SwFmtCharFmt&)rAttr).GetCharFmt(); 160 if( pFmt ) 161 { 162 pSet = &pFmt->GetAttrSet(); 163 } 164 } 165 166 return pSet; 167 } 168 169 /************************************************************************* 170 * CharFmt::GetItem 171 * extracts pool item of type nWhich from rAttr 172 *************************************************************************/ 173 174 const SfxPoolItem* GetItem( const SwTxtAttr& rAttr, sal_uInt16 nWhich ) 175 { 176 if ( RES_TXTATR_INETFMT == rAttr.Which() || 177 RES_TXTATR_CHARFMT == rAttr.Which() || 178 RES_TXTATR_AUTOFMT == rAttr.Which() ) 179 { 180 const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); 181 if ( !pSet ) return 0; 182 183 bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which(); 184 const SfxPoolItem* pItem; 185 sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( nWhich, bInParent, &pItem ); 186 187 return bRet ? pItem : 0; 188 } 189 190 return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : 0; 191 } 192 193 /************************************************************************* 194 * CharFmt::IsItemIncluded 195 * checks if item is included in character/inet/auto style 196 *************************************************************************/ 197 198 sal_Bool IsItemIncluded( const sal_uInt16 nWhich, const SwTxtAttr *pAttr ) 199 { 200 sal_Bool bRet = sal_False; 201 202 const SfxItemSet* pItemSet = CharFmt::GetItemSet( pAttr->GetAttr() ); 203 if ( pItemSet ) 204 bRet = SFX_ITEM_SET == pItemSet->GetItemState( nWhich, sal_True ); 205 206 return bRet; 207 } 208 209 } 210 211 /************************************************************************* 212 * lcl_ChgHyperLinkColor 213 * The color of hyperlinks is taken from the associated character attribute, 214 * depending on its 'visited' state. There are actually two cases, which 215 * should override the colors from the character attribute: 216 * 1. We never take the 'visited' color during printing/pdf export/preview 217 * 2. The user has choosen to override these colors in the view options 218 *************************************************************************/ 219 220 bool lcl_ChgHyperLinkColor( const SwTxtAttr& rAttr, 221 const SfxPoolItem& rItem, 222 const ViewShell* pShell, 223 Color* pColor ) 224 { 225 if ( !pShell || 226 RES_TXTATR_INETFMT != rAttr.Which() || 227 RES_CHRATR_COLOR != rItem.Which() ) 228 return false; 229 230 // --> FME 2004-09-13 #i15455# 231 // 1. case: 232 // We do not want to show visited links: 233 // (printing, pdf export, page preview) 234 // 235 if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER || 236 pShell->GetViewOptions()->IsPDFExport() || 237 pShell->GetViewOptions()->IsPagePreview() ) 238 { 239 if ( ((SwTxtINetFmt&)rAttr).IsVisited() ) 240 { 241 if ( pColor ) 242 { 243 // take color from character format 'unvisited link' 244 SwTxtINetFmt& rInetAttr( const_cast<SwTxtINetFmt&>( 245 static_cast<const SwTxtINetFmt&>(rAttr)) ); 246 rInetAttr.SetVisited( false ); 247 const SwCharFmt* pTmpFmt = ((SwTxtINetFmt&)rAttr).GetCharFmt(); 248 const SfxPoolItem* pItem; 249 pTmpFmt->GetItemState( RES_CHRATR_COLOR, sal_True, &pItem ); 250 *pColor = ((SvxColorItem*)pItem)->GetValue(); 251 rInetAttr.SetVisited( true ); 252 } 253 return true; 254 } 255 256 return false; 257 } 258 // <-- 259 260 // 261 // 2. case: 262 // We do not want to apply the color set in the hyperlink 263 // attribute, instead we take the colors from the view options: 264 // 265 if ( pShell->GetWin() && 266 ( 267 (((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsVisitedLinks()) || 268 (!((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsLinks()) 269 ) 270 ) 271 { 272 if ( pColor ) 273 { 274 if ( ((SwTxtINetFmt&)rAttr).IsVisited() ) 275 { 276 // take color from view option 'visited link color' 277 *pColor = SwViewOption::GetVisitedLinksColor(); 278 } 279 else 280 { 281 // take color from view option 'unvisited link color' 282 *pColor = SwViewOption::GetLinksColor(); 283 } 284 } 285 return true; 286 } 287 288 return false; 289 } 290 291 /************************************************************************* 292 * SwAttrHandler::SwAttrStack::SwAttrStack() 293 *************************************************************************/ 294 295 inline SwAttrHandler::SwAttrStack::SwAttrStack() 296 : nCount( 0 ), nSize( INITIAL_NUM_ATTR ) 297 { 298 pArray = pInitialArray; 299 } 300 301 /************************************************************************* 302 * SwAttrHandler::SwAttrStack::Insert() 303 *************************************************************************/ 304 305 void SwAttrHandler::SwAttrStack::Insert( const SwTxtAttr& rAttr, const sal_uInt16 nPos ) 306 { 307 // do we still have enough space? 308 if ( nCount >= nSize ) 309 { 310 // we are still in our initial array 311 if ( INITIAL_NUM_ATTR == nSize ) 312 { 313 nSize += STACK_INCREMENT; 314 pArray = new SwTxtAttr*[ nSize ]; 315 // copy from pInitArray to new Array 316 memcpy( pArray, pInitialArray, 317 INITIAL_NUM_ATTR * sizeof(SwTxtAttr*) 318 ); 319 } 320 // we are in new memory 321 else 322 { 323 nSize += STACK_INCREMENT; 324 SwTxtAttr** pTmpArray = new SwTxtAttr*[ nSize ]; 325 // copy from pArray to new Array 326 memcpy( pTmpArray, pArray, nCount * sizeof(SwTxtAttr*) ); 327 // free old array 328 delete [] pArray; 329 pArray = pTmpArray; 330 } 331 } 332 333 ASSERT( nPos <= nCount, "wrong position for insert operation"); 334 335 if ( nPos < nCount ) 336 memmove( pArray + nPos + 1, pArray + nPos, 337 ( nCount - nPos ) * sizeof(SwTxtAttr*) 338 ); 339 pArray[ nPos ] = (SwTxtAttr*)&rAttr; 340 341 nCount++; 342 } 343 344 /************************************************************************* 345 * SwAttrHandler::SwAttrStack::Remove() 346 *************************************************************************/ 347 348 void SwAttrHandler::SwAttrStack::Remove( const SwTxtAttr& rAttr ) 349 { 350 sal_uInt16 nPos = Pos( rAttr ); 351 if ( nPos < nCount ) 352 { 353 memmove( pArray + nPos, pArray + nPos + 1, 354 ( nCount - 1 - nPos ) * sizeof(SwTxtAttr*) 355 ); 356 nCount--; 357 } 358 } 359 360 /************************************************************************* 361 * SwAttrHandler::SwAttrStack::Top() 362 *************************************************************************/ 363 364 const SwTxtAttr* SwAttrHandler::SwAttrStack::Top() const 365 { 366 return nCount ? pArray[ nCount - 1 ] : 0; 367 } 368 369 /************************************************************************* 370 * SwAttrHandler::SwAttrStack::Pos() 371 *************************************************************************/ 372 373 sal_uInt16 SwAttrHandler::SwAttrStack::Pos( const SwTxtAttr& rAttr ) const 374 { 375 if ( ! nCount ) 376 // empty stack 377 return USHRT_MAX; 378 379 for ( sal_uInt16 nIdx = nCount; nIdx > 0; ) 380 { 381 if ( &rAttr == pArray[ --nIdx ] ) 382 return nIdx; 383 } 384 385 // element not found 386 return USHRT_MAX; 387 } 388 389 /************************************************************************* 390 * SwAttrHandler::SwAttrHandler() 391 *************************************************************************/ 392 393 SwAttrHandler::SwAttrHandler() : mpShell( 0 ), pFnt( 0 ), bVertLayout( sal_False ) 394 395 { 396 memset( pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) ); 397 } 398 399 SwAttrHandler::~SwAttrHandler() 400 { 401 delete pFnt; 402 } 403 404 /************************************************************************* 405 * SwAttrHandler::Init() 406 *************************************************************************/ 407 408 void SwAttrHandler::Init( const SwAttrSet& rAttrSet, 409 const IDocumentSettingAccess& rIDocumentSettingAcces, 410 const ViewShell* pSh ) 411 { 412 mpIDocumentSettingAccess = &rIDocumentSettingAcces; 413 mpShell = pSh; 414 415 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ ) 416 pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i, sal_True ); 417 } 418 419 void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS, 420 const IDocumentSettingAccess& rIDocumentSettingAcces, 421 const ViewShell* pSh, 422 SwFont& rFnt, sal_Bool bVL ) 423 { 424 // initialize default array 425 memcpy( pDefaultArray, pPoolItem, 426 NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) ); 427 428 mpIDocumentSettingAccess = &rIDocumentSettingAcces; 429 mpShell = pSh; 430 431 // do we have to apply additional paragraph attributes? 432 bVertLayout = bVL; 433 434 if ( pAS && pAS->Count() ) 435 { 436 SfxItemIter aIter( *pAS ); 437 sal_uInt16 nWhich; 438 const SfxPoolItem* pItem = aIter.GetCurItem(); 439 while( sal_True ) 440 { 441 nWhich = pItem->Which(); 442 if (isCHRATR(nWhich)) 443 { 444 pDefaultArray[ StackPos[ nWhich ] ] = pItem; 445 FontChg( *pItem, rFnt, sal_True ); 446 } 447 448 if( aIter.IsAtEnd() ) 449 break; 450 451 pItem = aIter.NextItem(); 452 } 453 } 454 455 // It is possible, that Init is called more than once, e.g., in a 456 // SwTxtFrm::FormatOnceMore situation. 457 delete pFnt; 458 pFnt = new SwFont( rFnt ); 459 } 460 461 void SwAttrHandler::Reset( ) 462 { 463 for ( sal_uInt16 i = 0; i < NUM_ATTRIBUTE_STACKS; i++ ) 464 aAttrStack[ i ].Reset(); 465 } 466 467 /************************************************************************* 468 * SwAttrHandler::PushAndChg() 469 *************************************************************************/ 470 471 void SwAttrHandler::PushAndChg( const SwTxtAttr& rAttr, SwFont& rFnt ) 472 { 473 // these special attributes in fact represent a collection of attributes 474 // they have to be pushed to each stack they belong to 475 if ( RES_TXTATR_INETFMT == rAttr.Which() || 476 RES_TXTATR_CHARFMT == rAttr.Which() || 477 RES_TXTATR_AUTOFMT == rAttr.Which() ) 478 { 479 const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); 480 if ( !pSet ) return; 481 482 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++) 483 { 484 const SfxPoolItem* pItem; 485 sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem ); 486 487 if ( bRet ) 488 { 489 // we push rAttr onto the appropriate stack 490 if ( Push( rAttr, *pItem ) ) 491 { 492 // we let pItem change rFnt 493 Color aColor; 494 if ( lcl_ChgHyperLinkColor( rAttr, *pItem, mpShell, &aColor ) ) 495 { 496 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR ); 497 FontChg( aItemNext, rFnt, sal_True ); 498 } 499 else 500 FontChg( *pItem, rFnt, sal_True ); 501 } 502 } 503 } 504 } 505 // this is the usual case, we have a basic attribute, push it onto the 506 // stack and change the font 507 else 508 { 509 if ( Push( rAttr, rAttr.GetAttr() ) ) 510 // we let pItem change rFnt 511 FontChg( rAttr.GetAttr(), rFnt, sal_True ); 512 } 513 } 514 515 /************************************************************************* 516 * SwAttrHandler::Push() 517 *************************************************************************/ 518 519 sal_Bool SwAttrHandler::Push( const SwTxtAttr& rAttr, const SfxPoolItem& rItem ) 520 { 521 ASSERT( rItem.Which() < RES_TXTATR_WITHEND_END, 522 "I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); 523 524 // robust 525 if ( RES_TXTATR_WITHEND_END <= rItem.Which() ) 526 return sal_False; 527 528 sal_uInt16 nStack = StackPos[ rItem.Which() ]; 529 530 // attributes originating from redlining have highest priority 531 // second priority are hyperlink attributes, which have a color replacement 532 const SwTxtAttr* pTopAttr = aAttrStack[ nStack ].Top(); 533 if ( !pTopAttr || rAttr.IsPriorityAttr() || 534 ( !pTopAttr->IsPriorityAttr() && 535 !lcl_ChgHyperLinkColor( *pTopAttr, rItem, mpShell, 0 ) ) ) 536 { 537 aAttrStack[ nStack ].Push( rAttr ); 538 return sal_True; 539 } 540 541 sal_uInt16 nPos = aAttrStack[ nStack ].Count(); 542 ASSERT( nPos, "empty stack?" ); 543 aAttrStack[ nStack ].Insert( rAttr, nPos - 1 ); 544 return sal_False; 545 } 546 547 /************************************************************************* 548 * SwAttrHandler::PopAndChg() 549 *************************************************************************/ 550 551 void SwAttrHandler::PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt ) 552 { 553 if ( RES_TXTATR_WITHEND_END <= rAttr.Which() ) 554 return; // robust 555 556 // these special attributes in fact represent a collection of attributes 557 // they have to be removed from each stack they belong to 558 if ( RES_TXTATR_INETFMT == rAttr.Which() || 559 RES_TXTATR_CHARFMT == rAttr.Which() || 560 RES_TXTATR_AUTOFMT == rAttr.Which() ) 561 { 562 const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); 563 if ( !pSet ) return; 564 565 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++) 566 { 567 const SfxPoolItem* pItem; 568 sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem ); 569 if ( bRet ) 570 { 571 // we remove rAttr from the appropriate stack 572 sal_uInt16 nStackPos = StackPos[ i ]; 573 aAttrStack[ nStackPos ].Remove( rAttr ); 574 // reset font according to attribute on top of stack 575 // or default value 576 ActivateTop( rFnt, i ); 577 } 578 } 579 } 580 // this is the usual case, we have a basic attribute, remove it from the 581 // stack and reset the font 582 else 583 { 584 aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr ); 585 // reset font according to attribute on top of stack 586 // or default value 587 ActivateTop( rFnt, rAttr.Which() ); 588 } 589 } 590 591 /************************************************************************* 592 * SwAttrHandler::Pop() 593 * 594 * only used during redlining 595 *************************************************************************/ 596 597 void SwAttrHandler::Pop( const SwTxtAttr& rAttr ) 598 { 599 ASSERT( rAttr.Which() < RES_TXTATR_WITHEND_END, 600 "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); 601 602 if ( rAttr.Which() < RES_TXTATR_WITHEND_END ) 603 { 604 aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr ); 605 } 606 } 607 608 /************************************************************************* 609 * SwAttrHandler::ActivateTop() 610 *************************************************************************/ 611 void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr ) 612 { 613 ASSERT( nAttr < RES_TXTATR_WITHEND_END, 614 "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); 615 616 const sal_uInt16 nStackPos = StackPos[ nAttr ]; 617 const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top(); 618 if ( pTopAt ) 619 { 620 // check if top attribute is collection of attributes 621 if ( RES_TXTATR_INETFMT == pTopAt->Which() || 622 RES_TXTATR_CHARFMT == pTopAt->Which() || 623 RES_TXTATR_AUTOFMT == pTopAt->Which() ) 624 { 625 const SfxItemSet* pSet = CharFmt::GetItemSet( pTopAt->GetAttr() ); 626 const SfxPoolItem* pItemNext; 627 pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext ); 628 629 Color aColor; 630 if ( lcl_ChgHyperLinkColor( *pTopAt, *pItemNext, mpShell, &aColor ) ) 631 { 632 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR ); 633 FontChg( aItemNext, rFnt, sal_False ); 634 } 635 else 636 FontChg( *pItemNext, rFnt, sal_False ); 637 } 638 else 639 FontChg( pTopAt->GetAttr(), rFnt, sal_False ); 640 } 641 642 // default value has to be set, we only have default values for char attribs 643 else if ( nStackPos < NUM_DEFAULT_VALUES ) 644 FontChg( *pDefaultArray[ nStackPos ], rFnt, sal_False ); 645 else if ( RES_TXTATR_REFMARK == nAttr ) 646 rFnt.GetRef()--; 647 else if ( RES_TXTATR_TOXMARK == nAttr ) 648 rFnt.GetTox()--; 649 else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) ) 650 { 651 rFnt.GetMeta()--; 652 } 653 else if ( RES_TXTATR_CJK_RUBY == nAttr ) 654 { 655 // ruby stack has no more attributes 656 // check, if an rotation attribute has to be applied 657 sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; 658 sal_Bool bTwoLineAct = sal_False; 659 const SfxPoolItem* pTwoLineItem = 0; 660 const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top(); 661 662 if ( pTwoLineAttr ) 663 { 664 pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); 665 bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue(); 666 } 667 else 668 bTwoLineAct = 669 ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue(); 670 671 if ( bTwoLineAct ) 672 return; 673 674 // eventually, an rotate attribute has to be activated 675 sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; 676 const SfxPoolItem* pRotateItem = 0; 677 const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top(); 678 679 if ( pRotateAttr ) 680 { 681 pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); 682 rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(), 683 bVertLayout ); 684 } 685 else 686 rFnt.SetVertical( 687 ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(), 688 bVertLayout 689 ); 690 } 691 } 692 693 /************************************************************************* 694 * Font Changing Function 695 * 696 * When popping an attribute from the stack, the top mose remaining 697 * attribute in the stack becomes valid. The following function change 698 * a font depending on the stack id. 699 *************************************************************************/ 700 701 void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush ) 702 { 703 switch ( rItem.Which() ) 704 { 705 case RES_CHRATR_CASEMAP : 706 rFnt.SetCaseMap( ((SvxCaseMapItem&)rItem).GetCaseMap() ); 707 break; 708 case RES_CHRATR_COLOR : 709 rFnt.SetColor( ((SvxColorItem&)rItem).GetValue() ); 710 break; 711 case RES_CHRATR_CONTOUR : 712 rFnt.SetOutline( ((SvxContourItem&)rItem).GetValue() ); 713 break; 714 case RES_CHRATR_CROSSEDOUT : 715 rFnt.SetStrikeout( ((SvxCrossedOutItem&)rItem).GetStrikeout() ); 716 break; 717 case RES_CHRATR_ESCAPEMENT : 718 rFnt.SetEscapement( ((SvxEscapementItem&)rItem).GetEsc() ); 719 rFnt.SetProportion( ((SvxEscapementItem&)rItem).GetProp() ); 720 break; 721 case RES_CHRATR_FONT : 722 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_LATIN ); 723 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_LATIN ); 724 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_LATIN ); 725 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_LATIN ); 726 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_LATIN ); 727 break; 728 case RES_CHRATR_FONTSIZE : 729 rFnt.SetSize(Size(0,((SvxFontHeightItem&)rItem).GetHeight() ), SW_LATIN ); 730 break; 731 case RES_CHRATR_KERNING : 732 rFnt.SetFixKerning( ((SvxKerningItem&)rItem).GetValue() ); 733 break; 734 case RES_CHRATR_LANGUAGE : 735 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_LATIN ); 736 break; 737 case RES_CHRATR_POSTURE : 738 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_LATIN ); 739 break; 740 case RES_CHRATR_SHADOWED : 741 rFnt.SetShadow( ((SvxShadowedItem&)rItem).GetValue() ); 742 break; 743 case RES_CHRATR_UNDERLINE : 744 { 745 const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ]; 746 const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top(); 747 748 const SfxPoolItem* pTmpItem = pTopAt ? 749 CharFmt::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) : 750 pDefaultArray[ nStackPos ]; 751 752 if( (mpShell && !mpShell->GetWin()) || 753 (pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) ) 754 { 755 rFnt.SetUnderline( ((SvxUnderlineItem&)rItem).GetLineStyle() ); 756 rFnt.SetUnderColor( ((SvxUnderlineItem&)rItem).GetColor() ); 757 } 758 break; 759 } 760 case RES_CHRATR_OVERLINE : 761 rFnt.SetOverline( ((SvxOverlineItem&)rItem).GetLineStyle() ); 762 rFnt.SetOverColor( ((SvxOverlineItem&)rItem).GetColor() ); 763 break; 764 case RES_CHRATR_WEIGHT : 765 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_LATIN ); 766 break; 767 case RES_CHRATR_WORDLINEMODE : 768 rFnt.SetWordLineMode( ((SvxWordLineModeItem&)rItem).GetValue() ); 769 break; 770 case RES_CHRATR_AUTOKERN : 771 if( ((SvxAutoKernItem&)rItem).GetValue() ) 772 { 773 rFnt.SetAutoKern( ( !mpIDocumentSettingAccess || 774 !mpIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ? 775 KERNING_FONTSPECIFIC : 776 KERNING_ASIAN ); 777 } 778 else 779 rFnt.SetAutoKern( 0 ); 780 break; 781 case RES_CHRATR_BLINK : 782 rFnt.SetBlink( ((SvxBlinkItem&)rItem).GetValue() ); 783 break; 784 case RES_CHRATR_BACKGROUND : 785 rFnt.SetBackColor(new Color( ((SvxBrushItem&)rItem).GetColor() ) ); 786 break; 787 case RES_CHRATR_CJK_FONT : 788 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CJK ); 789 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CJK ); 790 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CJK ); 791 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CJK ); 792 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CJK ); 793 break; 794 case RES_CHRATR_CJK_FONTSIZE : 795 rFnt.SetSize(Size( 0, ((SvxFontHeightItem&)rItem).GetHeight()), SW_CJK); 796 break; 797 case RES_CHRATR_CJK_LANGUAGE : 798 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CJK ); 799 break; 800 case RES_CHRATR_CJK_POSTURE : 801 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CJK ); 802 break; 803 case RES_CHRATR_CJK_WEIGHT : 804 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CJK ); 805 break; 806 case RES_CHRATR_CTL_FONT : 807 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CTL ); 808 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CTL ); 809 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CTL ); 810 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CTL ); 811 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CTL ); 812 break; 813 case RES_CHRATR_CTL_FONTSIZE : 814 rFnt.SetSize(Size(0, ((SvxFontHeightItem&)rItem).GetHeight() ), SW_CTL); 815 break; 816 case RES_CHRATR_CTL_LANGUAGE : 817 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CTL ); 818 break; 819 case RES_CHRATR_CTL_POSTURE : 820 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CTL ); 821 break; 822 case RES_CHRATR_CTL_WEIGHT : 823 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CTL ); 824 break; 825 case RES_CHRATR_EMPHASIS_MARK : 826 rFnt.SetEmphasisMark( 827 ((SvxEmphasisMarkItem&)rItem).GetEmphasisMark() 828 ); 829 break; 830 case RES_CHRATR_SCALEW : 831 rFnt.SetPropWidth( ((SvxCharScaleWidthItem&)rItem).GetValue() ); 832 break; 833 case RES_CHRATR_RELIEF : 834 rFnt.SetRelief( (FontRelief)((SvxCharReliefItem&)rItem).GetValue() ); 835 break; 836 case RES_CHRATR_HIDDEN : 837 if( mpShell && mpShell->GetWin()) 838 { 839 if ( ((SvxCharHiddenItem&)rItem).GetValue() ) 840 rFnt.SetUnderline( UNDERLINE_DOTTED ); 841 else 842 ActivateTop( rFnt, RES_CHRATR_UNDERLINE ); 843 } 844 break; 845 case RES_CHRATR_ROTATE : 846 { 847 // rotate attribute is applied, when: 848 // 1. ruby stack is empty and 849 // 2. top of two line stack ( or default attribute )is an 850 // deactivated two line attribute 851 const bool bRuby = 852 0 != aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count(); 853 854 if ( bRuby ) 855 break; 856 857 sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; 858 sal_Bool bTwoLineAct = sal_False; 859 const SfxPoolItem* pTwoLineItem = 0; 860 const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top(); 861 862 if ( pTwoLineAttr ) 863 { 864 pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); 865 bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue(); 866 } 867 else 868 bTwoLineAct = 869 ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue(); 870 871 if ( !bTwoLineAct ) 872 rFnt.SetVertical( ((SvxCharRotateItem&)rItem).GetValue(), 873 bVertLayout ); 874 875 break; 876 } 877 case RES_CHRATR_TWO_LINES : 878 { 879 sal_Bool bRuby = 0 != 880 aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count(); 881 sal_Bool bTwoLineAct = sal_False; 882 883 // two line is activated, if 884 // 1. no ruby attribute is set and 885 // 2. attribute is active 886 bTwoLineAct = ((SvxTwoLinesItem&)rItem).GetValue(); 887 888 if ( !bRuby && bTwoLineAct ) 889 { 890 rFnt.SetVertical( 0, bVertLayout ); 891 break; 892 } 893 894 // a deactivating two line attribute is on top of stack, 895 // check if rotate attribute has to be enabled 896 if ( bRuby ) 897 break; 898 899 sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; 900 const SfxPoolItem* pRotateItem = 0; 901 const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top(); 902 903 if ( pRotateAttr ) 904 { 905 pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); 906 rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(), 907 bVertLayout ); 908 } 909 else 910 rFnt.SetVertical( 911 ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(), 912 bVertLayout 913 ); 914 break; 915 } 916 case RES_TXTATR_CJK_RUBY : 917 rFnt.SetVertical( 0, bVertLayout ); 918 break; 919 case RES_TXTATR_REFMARK : 920 if ( bPush ) 921 rFnt.GetRef()++; 922 else 923 rFnt.GetRef()--; 924 break; 925 case RES_TXTATR_TOXMARK : 926 if ( bPush ) 927 rFnt.GetTox()++; 928 else 929 rFnt.GetTox()--; 930 break; 931 case RES_TXTATR_META: 932 case RES_TXTATR_METAFIELD: 933 if ( bPush ) 934 rFnt.GetMeta()++; 935 else 936 rFnt.GetMeta()--; 937 break; 938 } 939 } 940 941 // Takes the default font and calculated the ascent and height 942 void SwAttrHandler::GetDefaultAscentAndHeight( ViewShell* pShell, OutputDevice& rOut, 943 sal_uInt16& nAscent, sal_uInt16& nHeight ) const 944 { 945 ASSERT( pFnt, "No font available for GetDefaultAscentAndHeight" ) 946 947 if ( pFnt ) 948 { 949 SwFont aFont( *pFnt ); 950 nHeight = aFont.GetHeight( pShell, rOut ); 951 nAscent = aFont.GetAscent( pShell, rOut ); 952 } 953 } 954 955