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