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 // 41 125 0, // RES_CHRATR_IDCTHINT // 42 126 36, // RES_TXTATR_REFMARK, // 43 127 37, // RES_TXTATR_TOXMARK, // 44 128 38, // RES_TXTATR_META, // 45 129 38, // RES_TXTATR_METAFIELD, // 46 130 0, // RES_TXTATR_AUTOFMT, // 47 131 0, // RES_TXTATR_INETFMT // 48 132 0, // RES_TXTATR_CHARFMT, // 49 133 39, // RES_TXTATR_CJK_RUBY, // 50 134 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 51 135 40, // RES_TXTATR_INPUTFIELD // 52 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 const 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 534 || rAttr.IsPriorityAttr() 535 || ( !pTopAttr->IsPriorityAttr() 536 && !lcl_ChgHyperLinkColor( *pTopAttr, rItem, mpShell, 0 ) ) ) 537 { 538 aAttrStack[ nStack ].Push( rAttr ); 539 return sal_True; 540 } 541 542 const sal_uInt16 nPos = aAttrStack[ nStack ].Count(); 543 ASSERT( nPos, "empty stack?" ); 544 aAttrStack[ nStack ].Insert( rAttr, nPos - 1 ); 545 return sal_False; 546 } 547 548 /************************************************************************* 549 * SwAttrHandler::PopAndChg() 550 *************************************************************************/ 551 552 void SwAttrHandler::PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt ) 553 { 554 if ( RES_TXTATR_WITHEND_END <= rAttr.Which() ) 555 return; // robust 556 557 // these special attributes in fact represent a collection of attributes 558 // they have to be removed from each stack they belong to 559 if ( RES_TXTATR_INETFMT == rAttr.Which() || 560 RES_TXTATR_CHARFMT == rAttr.Which() || 561 RES_TXTATR_AUTOFMT == rAttr.Which() ) 562 { 563 const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); 564 if ( !pSet ) return; 565 566 for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++) 567 { 568 const SfxPoolItem* pItem; 569 sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem ); 570 if ( bRet ) 571 { 572 // we remove rAttr from the appropriate stack 573 sal_uInt16 nStackPos = StackPos[ i ]; 574 aAttrStack[ nStackPos ].Remove( rAttr ); 575 // reset font according to attribute on top of stack 576 // or default value 577 ActivateTop( rFnt, i ); 578 } 579 } 580 } 581 // this is the usual case, we have a basic attribute, remove it from the 582 // stack and reset the font 583 else 584 { 585 aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr ); 586 // reset font according to attribute on top of stack 587 // or default value 588 ActivateTop( rFnt, rAttr.Which() ); 589 } 590 } 591 592 /************************************************************************* 593 * SwAttrHandler::Pop() 594 * 595 * only used during redlining 596 *************************************************************************/ 597 598 void SwAttrHandler::Pop( const SwTxtAttr& rAttr ) 599 { 600 ASSERT( rAttr.Which() < RES_TXTATR_WITHEND_END, 601 "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); 602 603 if ( rAttr.Which() < RES_TXTATR_WITHEND_END ) 604 { 605 aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr ); 606 } 607 } 608 609 /************************************************************************* 610 * SwAttrHandler::ActivateTop() 611 *************************************************************************/ 612 void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr ) 613 { 614 ASSERT( nAttr < RES_TXTATR_WITHEND_END, 615 "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); 616 617 const sal_uInt16 nStackPos = StackPos[ nAttr ]; 618 const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top(); 619 if ( pTopAt ) 620 { 621 // check if top attribute is collection of attributes 622 if ( RES_TXTATR_INETFMT == pTopAt->Which() || 623 RES_TXTATR_CHARFMT == pTopAt->Which() || 624 RES_TXTATR_AUTOFMT == pTopAt->Which() ) 625 { 626 const SfxItemSet* pSet = CharFmt::GetItemSet( pTopAt->GetAttr() ); 627 const SfxPoolItem* pItemNext; 628 pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext ); 629 630 Color aColor; 631 if ( lcl_ChgHyperLinkColor( *pTopAt, *pItemNext, mpShell, &aColor ) ) 632 { 633 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR ); 634 FontChg( aItemNext, rFnt, sal_False ); 635 } 636 else 637 FontChg( *pItemNext, rFnt, sal_False ); 638 } 639 else 640 FontChg( pTopAt->GetAttr(), rFnt, sal_False ); 641 } 642 643 // default value has to be set, we only have default values for char attribs 644 else if ( nStackPos < NUM_DEFAULT_VALUES ) 645 FontChg( *pDefaultArray[ nStackPos ], rFnt, sal_False ); 646 else if ( RES_TXTATR_REFMARK == nAttr ) 647 rFnt.GetRef()--; 648 else if ( RES_TXTATR_TOXMARK == nAttr ) 649 rFnt.GetTox()--; 650 else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) ) 651 { 652 rFnt.GetMeta()--; 653 } 654 else if ( RES_TXTATR_CJK_RUBY == nAttr ) 655 { 656 // ruby stack has no more attributes 657 // check, if an rotation attribute has to be applied 658 sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; 659 sal_Bool bTwoLineAct = sal_False; 660 const SfxPoolItem* pTwoLineItem = 0; 661 const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top(); 662 663 if ( pTwoLineAttr ) 664 { 665 pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); 666 bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue(); 667 } 668 else 669 bTwoLineAct = 670 ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue(); 671 672 if ( bTwoLineAct ) 673 return; 674 675 // eventually, an rotate attribute has to be activated 676 sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; 677 const SfxPoolItem* pRotateItem = 0; 678 const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top(); 679 680 if ( pRotateAttr ) 681 { 682 pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); 683 rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(), 684 bVertLayout ); 685 } 686 else 687 rFnt.SetVertical( 688 ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(), 689 bVertLayout 690 ); 691 } 692 else if ( RES_TXTATR_INPUTFIELD == nAttr ) 693 rFnt.GetInputField()--; 694 } 695 696 /************************************************************************* 697 * Font Changing Function 698 * 699 * When popping an attribute from the stack, the top mose remaining 700 * attribute in the stack becomes valid. The following function change 701 * a font depending on the stack id. 702 *************************************************************************/ 703 704 void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush ) 705 { 706 switch ( rItem.Which() ) 707 { 708 case RES_CHRATR_CASEMAP : 709 rFnt.SetCaseMap( ((SvxCaseMapItem&)rItem).GetCaseMap() ); 710 break; 711 case RES_CHRATR_COLOR : 712 rFnt.SetColor( ((SvxColorItem&)rItem).GetValue() ); 713 break; 714 case RES_CHRATR_CONTOUR : 715 rFnt.SetOutline( ((SvxContourItem&)rItem).GetValue() ); 716 break; 717 case RES_CHRATR_CROSSEDOUT : 718 rFnt.SetStrikeout( ((SvxCrossedOutItem&)rItem).GetStrikeout() ); 719 break; 720 case RES_CHRATR_ESCAPEMENT : 721 rFnt.SetEscapement( ((SvxEscapementItem&)rItem).GetEsc() ); 722 rFnt.SetProportion( ((SvxEscapementItem&)rItem).GetProp() ); 723 break; 724 case RES_CHRATR_FONT : 725 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_LATIN ); 726 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_LATIN ); 727 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_LATIN ); 728 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_LATIN ); 729 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_LATIN ); 730 break; 731 case RES_CHRATR_FONTSIZE : 732 rFnt.SetSize(Size(0,((SvxFontHeightItem&)rItem).GetHeight() ), SW_LATIN ); 733 break; 734 case RES_CHRATR_KERNING : 735 rFnt.SetFixKerning( ((SvxKerningItem&)rItem).GetValue() ); 736 break; 737 case RES_CHRATR_LANGUAGE : 738 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_LATIN ); 739 break; 740 case RES_CHRATR_POSTURE : 741 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_LATIN ); 742 break; 743 case RES_CHRATR_SHADOWED : 744 rFnt.SetShadow( ((SvxShadowedItem&)rItem).GetValue() ); 745 break; 746 case RES_CHRATR_UNDERLINE : 747 { 748 const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ]; 749 const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top(); 750 751 const SfxPoolItem* pTmpItem = pTopAt ? 752 CharFmt::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) : 753 pDefaultArray[ nStackPos ]; 754 755 if( (mpShell && !mpShell->GetWin()) || 756 (pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) ) 757 { 758 rFnt.SetUnderline( ((SvxUnderlineItem&)rItem).GetLineStyle() ); 759 rFnt.SetUnderColor( ((SvxUnderlineItem&)rItem).GetColor() ); 760 } 761 break; 762 } 763 case RES_CHRATR_OVERLINE : 764 rFnt.SetOverline( ((SvxOverlineItem&)rItem).GetLineStyle() ); 765 rFnt.SetOverColor( ((SvxOverlineItem&)rItem).GetColor() ); 766 break; 767 case RES_CHRATR_WEIGHT : 768 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_LATIN ); 769 break; 770 case RES_CHRATR_WORDLINEMODE : 771 rFnt.SetWordLineMode( ((SvxWordLineModeItem&)rItem).GetValue() ); 772 break; 773 case RES_CHRATR_AUTOKERN : 774 if( ((SvxAutoKernItem&)rItem).GetValue() ) 775 { 776 rFnt.SetAutoKern( ( !mpIDocumentSettingAccess || 777 !mpIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ? 778 KERNING_FONTSPECIFIC : 779 KERNING_ASIAN ); 780 } 781 else 782 rFnt.SetAutoKern( 0 ); 783 break; 784 case RES_CHRATR_BLINK : 785 rFnt.SetBlink( ((SvxBlinkItem&)rItem).GetValue() ); 786 break; 787 case RES_CHRATR_BACKGROUND : 788 rFnt.SetBackColor(new Color( ((SvxBrushItem&)rItem).GetColor() ) ); 789 break; 790 case RES_CHRATR_CJK_FONT : 791 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CJK ); 792 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CJK ); 793 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CJK ); 794 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CJK ); 795 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CJK ); 796 break; 797 case RES_CHRATR_CJK_FONTSIZE : 798 rFnt.SetSize(Size( 0, ((SvxFontHeightItem&)rItem).GetHeight()), SW_CJK); 799 break; 800 case RES_CHRATR_CJK_LANGUAGE : 801 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CJK ); 802 break; 803 case RES_CHRATR_CJK_POSTURE : 804 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CJK ); 805 break; 806 case RES_CHRATR_CJK_WEIGHT : 807 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CJK ); 808 break; 809 case RES_CHRATR_CTL_FONT : 810 rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CTL ); 811 rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CTL ); 812 rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CTL ); 813 rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CTL ); 814 rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CTL ); 815 break; 816 case RES_CHRATR_CTL_FONTSIZE : 817 rFnt.SetSize(Size(0, ((SvxFontHeightItem&)rItem).GetHeight() ), SW_CTL); 818 break; 819 case RES_CHRATR_CTL_LANGUAGE : 820 rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CTL ); 821 break; 822 case RES_CHRATR_CTL_POSTURE : 823 rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CTL ); 824 break; 825 case RES_CHRATR_CTL_WEIGHT : 826 rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CTL ); 827 break; 828 case RES_CHRATR_EMPHASIS_MARK : 829 rFnt.SetEmphasisMark( 830 ((SvxEmphasisMarkItem&)rItem).GetEmphasisMark() 831 ); 832 break; 833 case RES_CHRATR_SCALEW : 834 rFnt.SetPropWidth( ((SvxCharScaleWidthItem&)rItem).GetValue() ); 835 break; 836 case RES_CHRATR_RELIEF : 837 rFnt.SetRelief( (FontRelief)((SvxCharReliefItem&)rItem).GetValue() ); 838 break; 839 case RES_CHRATR_HIDDEN : 840 if( mpShell && mpShell->GetWin()) 841 { 842 if ( ((SvxCharHiddenItem&)rItem).GetValue() ) 843 rFnt.SetUnderline( UNDERLINE_DOTTED ); 844 else 845 ActivateTop( rFnt, RES_CHRATR_UNDERLINE ); 846 } 847 break; 848 case RES_CHRATR_ROTATE : 849 { 850 // rotate attribute is applied, when: 851 // 1. ruby stack is empty and 852 // 2. top of two line stack ( or default attribute )is an 853 // deactivated two line attribute 854 const bool bRuby = 855 0 != aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count(); 856 857 if ( bRuby ) 858 break; 859 860 sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; 861 sal_Bool bTwoLineAct = sal_False; 862 const SfxPoolItem* pTwoLineItem = 0; 863 const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top(); 864 865 if ( pTwoLineAttr ) 866 { 867 pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); 868 bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue(); 869 } 870 else 871 bTwoLineAct = 872 ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue(); 873 874 if ( !bTwoLineAct ) 875 rFnt.SetVertical( ((SvxCharRotateItem&)rItem).GetValue(), 876 bVertLayout ); 877 878 break; 879 } 880 case RES_CHRATR_TWO_LINES : 881 { 882 sal_Bool bRuby = 0 != 883 aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count(); 884 sal_Bool bTwoLineAct = sal_False; 885 886 // two line is activated, if 887 // 1. no ruby attribute is set and 888 // 2. attribute is active 889 bTwoLineAct = ((SvxTwoLinesItem&)rItem).GetValue(); 890 891 if ( !bRuby && bTwoLineAct ) 892 { 893 rFnt.SetVertical( 0, bVertLayout ); 894 break; 895 } 896 897 // a deactivating two line attribute is on top of stack, 898 // check if rotate attribute has to be enabled 899 if ( bRuby ) 900 break; 901 902 sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; 903 const SfxPoolItem* pRotateItem = 0; 904 const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top(); 905 906 if ( pRotateAttr ) 907 { 908 pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); 909 rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(), 910 bVertLayout ); 911 } 912 else 913 rFnt.SetVertical( 914 ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(), 915 bVertLayout 916 ); 917 break; 918 } 919 case RES_TXTATR_CJK_RUBY : 920 rFnt.SetVertical( 0, bVertLayout ); 921 break; 922 case RES_TXTATR_REFMARK : 923 if ( bPush ) 924 rFnt.GetRef()++; 925 else 926 rFnt.GetRef()--; 927 break; 928 case RES_TXTATR_TOXMARK : 929 if ( bPush ) 930 rFnt.GetTox()++; 931 else 932 rFnt.GetTox()--; 933 break; 934 case RES_TXTATR_META: 935 case RES_TXTATR_METAFIELD: 936 if ( bPush ) 937 rFnt.GetMeta()++; 938 else 939 rFnt.GetMeta()--; 940 break; 941 case RES_TXTATR_INPUTFIELD : 942 if ( bPush ) 943 rFnt.GetInputField()++; 944 else 945 rFnt.GetInputField()--; 946 break; 947 } 948 } 949 950 // Takes the default font and calculated the ascent and height 951 void SwAttrHandler::GetDefaultAscentAndHeight( ViewShell* pShell, OutputDevice& rOut, 952 sal_uInt16& nAscent, sal_uInt16& nHeight ) const 953 { 954 ASSERT( pFnt, "No font available for GetDefaultAscentAndHeight" ) 955 956 if ( pFnt ) 957 { 958 SwFont aFont( *pFnt ); 959 nHeight = aFont.GetHeight( pShell, rOut ); 960 nAscent = aFont.GetAscent( pShell, rOut ); 961 } 962 } 963 964