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