1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 28 #include <hintids.hxx> 29 30 #include <editeng/tstpitem.hxx> 31 #include <editeng/lrspitem.hxx> 32 #include <editeng/scripttypeitem.hxx> 33 #include <com/sun/star/i18n/ScriptType.hdl> 34 #include <txatbase.hxx> 35 #include <txtftn.hxx> 36 #include <fmtftn.hxx> 37 #include <editsh.hxx> 38 #include <edimp.hxx> // fuer MACROS 39 #include <doc.hxx> 40 #include <swundo.hxx> // fuer UNDO-Ids 41 #include <ndtxt.hxx> 42 #include <ftnidx.hxx> 43 #include <expfld.hxx> 44 #include <rootfrm.hxx> 45 #include <cntfrm.hxx> 46 #include <breakit.hxx> 47 #include <txtfld.hxx> 48 #include <fmtfld.hxx> 49 #include <crsskip.hxx> 50 #include <txtfrm.hxx> // SwTxtFrm 51 #include <scriptinfo.hxx> 52 #include <svl/ctloptions.hxx> 53 #include <charfmt.hxx> // #i27615# 54 #include <numrule.hxx> 55 56 57 /************************************* 58 * harte Formatierung (Attribute) 59 *************************************/ 60 61 // wenn Selektion groesser Max Nodes oder mehr als Max Selektionen 62 // => keine Attribute 63 const sal_uInt16& getMaxLookup() 64 { 65 static const sal_uInt16 nMaxLookup = 1000; 66 return nMaxLookup; 67 } 68 69 // --> OD 2008-01-16 #newlistlevelattrs# 70 sal_Bool SwEditShell::GetCurAttr( SfxItemSet& rSet, 71 const bool bMergeIndentValuesOfNumRule ) const 72 // <-- 73 { 74 if( GetCrsrCnt() > getMaxLookup() ) 75 { 76 rSet.InvalidateAllItems(); 77 return sal_False; 78 } 79 80 SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() ); 81 SfxItemSet *pSet = &rSet; 82 83 FOREACHPAM_START(this) 84 85 // #i27615# if the cursor is in front of the numbering label 86 // the attributes to get are those from the numbering format. 87 if (PCURCRSR->IsInFrontOfLabel()) 88 { 89 SwTxtNode * pTxtNd = 90 PCURCRSR->GetPoint()->nNode.GetNode().GetTxtNode(); 91 92 if (pTxtNd) 93 { 94 SwNumRule * pNumRule = pTxtNd->GetNumRule(); 95 96 if (pNumRule) 97 { 98 const String & aCharFmtName = 99 pNumRule->Get(static_cast<sal_uInt16>(pTxtNd->GetActualListLevel())).GetCharFmtName(); 100 SwCharFmt * pCharFmt = 101 GetDoc()->FindCharFmtByName(aCharFmtName); 102 103 if (pCharFmt) 104 rSet.Put(pCharFmt->GetAttrSet()); 105 } 106 } 107 108 continue; 109 } 110 111 sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(), 112 nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex(); 113 xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(), 114 nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex(); 115 116 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt )) 117 { 118 sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp; 119 nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp; 120 } 121 122 if( nEndNd - nSttNd >= getMaxLookup() ) 123 { 124 rSet.ClearItem(); 125 rSet.InvalidateAllItems(); 126 return sal_False; 127 } 128 129 // beim 1.Node traegt der Node die Werte in den GetSet ein (Initial) 130 // alle weiteren Nodes werden zum GetSet zu gemergt 131 for( sal_uLong n = nSttNd; n <= nEndNd; ++n ) 132 { 133 SwNode* pNd = GetDoc()->GetNodes()[ n ]; 134 switch( pNd->GetNodeType() ) 135 { 136 case ND_TEXTNODE: 137 { 138 xub_StrLen nStt = n == nSttNd ? nSttCnt : 0, 139 nEnd = n == nEndNd ? nEndCnt 140 : ((SwTxtNode*)pNd)->GetTxt().Len(); 141 // --> OD 2008-01-16 #newlistlevelattrs# 142 ((SwTxtNode*)pNd)->GetAttr( *pSet, nStt, nEnd, 143 sal_False, sal_True, 144 bMergeIndentValuesOfNumRule ); 145 // <-- 146 } 147 break; 148 case ND_GRFNODE: 149 case ND_OLENODE: 150 ((SwCntntNode*)pNd)->GetAttr( *pSet ); 151 break; 152 153 default: 154 pNd = 0; 155 } 156 157 if( pNd ) 158 { 159 if( pSet != &rSet ) 160 rSet.MergeValues( aSet ); 161 162 if( aSet.Count() ) 163 aSet.ClearItem(); 164 } 165 pSet = &aSet; 166 } 167 168 FOREACHPAM_END() 169 170 return sal_True; 171 } 172 173 SwTxtFmtColl* SwEditShell::GetCurTxtFmtColl() const 174 { 175 SwTxtFmtColl *pFmt = 0; 176 177 if ( GetCrsrCnt() > getMaxLookup() ) 178 return 0; 179 180 FOREACHPAM_START(this) 181 182 sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(), 183 nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex(); 184 xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(), 185 nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex(); 186 187 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt )) 188 { 189 sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp; 190 nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp; 191 } 192 193 if( nEndNd - nSttNd >= getMaxLookup() ) 194 { 195 pFmt = 0; 196 break; 197 } 198 199 for( sal_uLong n = nSttNd; n <= nEndNd; ++n ) 200 { 201 SwNode* pNd = GetDoc()->GetNodes()[ n ]; 202 if( pNd->IsTxtNode() ) 203 { 204 if( !pFmt ) 205 pFmt = ((SwTxtNode*)pNd)->GetTxtColl(); 206 else if( pFmt == ((SwTxtNode*)pNd)->GetTxtColl() ) // ??? 207 break; 208 } 209 } 210 211 FOREACHPAM_END() 212 return pFmt; 213 } 214 215 216 217 sal_Bool SwEditShell::GetCurFtn( SwFmtFtn* pFillFtn ) 218 { 219 // der Cursor muss auf dem akt. Fussnoten-Anker stehen: 220 SwPaM* pCrsr = GetCrsr(); 221 SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode(); 222 if( !pTxtNd ) 223 return sal_False; 224 225 SwTxtAttr *const pFtn = pTxtNd->GetTxtAttrForCharAt( 226 pCrsr->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN); 227 if( pFtn && pFillFtn ) 228 { 229 // Daten vom Attribut uebertragen 230 const SwFmtFtn &rFtn = ((SwTxtFtn*)pFtn)->GetFtn(); 231 pFillFtn->SetNumber( rFtn ); 232 pFillFtn->SetEndNote( rFtn.IsEndNote() ); 233 } 234 return 0 != pFtn; 235 } 236 237 238 bool SwEditShell::SetCurFtn( const SwFmtFtn& rFillFtn ) 239 { 240 bool bChgd = false; 241 StartAllAction(); 242 243 SwPaM* pCrsr = GetCrsr(), *pFirst = pCrsr; 244 do { 245 bChgd |= pDoc->SetCurFtn( *pCrsr, rFillFtn.GetNumStr(), 246 rFillFtn.GetNumber(), 247 rFillFtn.IsEndNote() ); 248 249 } while( pFirst != ( pCrsr = (SwPaM*)pCrsr->GetNext() )); 250 251 EndAllAction(); 252 return bChgd; 253 } 254 255 256 257 /*sal_uInt16 SwEditShell::GetFtnCnt( sal_Bool bEndNotes = sal_False ) const 258 { 259 const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs(); 260 sal_uInt16 nCnt = 0; 261 for ( sal_uInt16 i = 0; i < rIdxs.Count(); ++i ) 262 { 263 const SwFmtFtn &rFtn = rIdxs[i]->GetFtn(); 264 if ( bEndNotes == rFtn.IsEndNote() ) 265 nCnt++; 266 } 267 return nCnt; 268 } */ 269 270 271 bool SwEditShell::HasFtns( bool bEndNotes ) const 272 { 273 const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs(); 274 for ( sal_uInt16 i = 0; i < rIdxs.Count(); ++i ) 275 { 276 const SwFmtFtn &rFtn = rIdxs[i]->GetFtn(); 277 if ( bEndNotes == rFtn.IsEndNote() ) 278 return sal_True; 279 } 280 return sal_False; 281 } 282 283 284 // gebe Liste aller Fussnoten und deren Anfangstexte 285 sal_uInt16 SwEditShell::GetSeqFtnList( SwSeqFldList& rList, bool bEndNotes ) 286 { 287 if( rList.Count() ) 288 rList.Remove( 0, rList.Count() ); 289 290 sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count(); 291 SwTxtFtn* pTxtFtn; 292 for( n = 0; n < nFtnCnt; ++n ) 293 { 294 pTxtFtn = pDoc->GetFtnIdxs()[ n ]; 295 const SwFmtFtn& rFtn = pTxtFtn->GetFtn(); 296 if ( rFtn.IsEndNote() != bEndNotes ) 297 continue; 298 299 SwNodeIndex* pIdx = pTxtFtn->GetStartNode(); 300 if( pIdx ) 301 { 302 SwNodeIndex aIdx( *pIdx, 1 ); 303 SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode(); 304 if( !pTxtNd ) 305 pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx ); 306 307 if( pTxtNd ) 308 { 309 String sTxt( rFtn.GetViewNumStr( *pDoc )); 310 if( sTxt.Len() ) 311 sTxt += ' '; 312 sTxt += pTxtNd->GetExpandTxt( 0, USHRT_MAX ); 313 314 _SeqFldLstElem* pNew = new _SeqFldLstElem( sTxt, 315 pTxtFtn->GetSeqRefNo() ); 316 while( rList.InsertSort( pNew ) ) 317 pNew->sDlgEntry += ' '; 318 } 319 } 320 } 321 322 return rList.Count(); 323 } 324 325 326 // linken Rand ueber Objectleiste einstellen (aenhlich dem Stufen von 327 // Numerierungen) 328 sal_Bool SwEditShell::IsMoveLeftMargin( sal_Bool bRight, sal_Bool bModulus ) const 329 { 330 sal_Bool bRet = sal_True; 331 332 const SvxTabStopItem& rTabItem = (SvxTabStopItem&)GetDoc()-> 333 GetDefault( RES_PARATR_TABSTOP ); 334 sal_uInt16 nDefDist = static_cast<sal_uInt16>(rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134); 335 if( !nDefDist ) 336 return sal_False; 337 338 FOREACHPAM_START(this) 339 340 sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(), 341 nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex(); 342 343 if( nSttNd > nEndNd ) 344 { 345 sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp; 346 } 347 348 SwCntntNode* pCNd; 349 for( sal_uLong n = nSttNd; bRet && n <= nEndNd; ++n ) 350 if( 0 != ( pCNd = GetDoc()->GetNodes()[ n ]->GetTxtNode() )) 351 { 352 const SvxLRSpaceItem& rLS = (SvxLRSpaceItem&) 353 pCNd->GetAttr( RES_LR_SPACE ); 354 if( bRight ) 355 { 356 long nNext = rLS.GetTxtLeft() + nDefDist; 357 if( bModulus ) 358 nNext = ( nNext / nDefDist ) * nDefDist; 359 SwFrm* pFrm = pCNd->getLayoutFrm( GetLayout() ); 360 if ( pFrm ) 361 { 362 const sal_uInt16 nFrmWidth = static_cast<sal_uInt16>( pFrm->IsVertical() ? 363 pFrm->Frm().Height() : 364 pFrm->Frm().Width() ); 365 bRet = nFrmWidth > ( nNext + MM50 ); 366 } 367 else 368 bRet = sal_False; 369 } 370 } 371 372 if( !bRet ) 373 break; 374 375 FOREACHPAM_END() 376 return bRet; 377 } 378 379 void SwEditShell::MoveLeftMargin( sal_Bool bRight, sal_Bool bModulus ) 380 { 381 StartAllAction(); 382 StartUndo( UNDO_START ); 383 384 SwPaM* pCrsr = GetCrsr(); 385 if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ? 386 { 387 SwPamRanges aRangeArr( *pCrsr ); 388 SwPaM aPam( *pCrsr->GetPoint() ); 389 for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n ) 390 GetDoc()->MoveLeftMargin( aRangeArr.SetPam( n, aPam ), 391 bRight, bModulus ); 392 } 393 else 394 GetDoc()->MoveLeftMargin( *pCrsr, bRight, bModulus ); 395 396 EndUndo( UNDO_END ); 397 EndAllAction(); 398 } 399 400 401 inline sal_uInt16 lcl_SetScriptFlags( sal_uInt16 nType ) 402 { 403 sal_uInt16 nRet; 404 switch( nType ) 405 { 406 case ::com::sun::star::i18n::ScriptType::LATIN: nRet = SCRIPTTYPE_LATIN; break; 407 case ::com::sun::star::i18n::ScriptType::ASIAN: nRet = SCRIPTTYPE_ASIAN; break; 408 case ::com::sun::star::i18n::ScriptType::COMPLEX: nRet = SCRIPTTYPE_COMPLEX; break; 409 default: nRet = 0; 410 } 411 return nRet; 412 } 413 414 sal_Bool lcl_IsNoEndTxtAttrAtPos( const SwTxtNode& rTNd, xub_StrLen nPos, 415 sal_uInt16 &rScrpt, sal_Bool bInSelection, sal_Bool bNum ) 416 { 417 sal_Bool bRet = sal_False; 418 const String& rTxt = rTNd.GetTxt(); 419 String sExp; 420 421 // consider numbering 422 if ( bNum ) 423 { 424 bRet = sal_False; 425 426 // --> OD 2008-03-19 #refactorlists# 427 if ( rTNd.IsInList() ) 428 { 429 ASSERT( rTNd.GetNumRule(), 430 "<lcl_IsNoEndTxtAttrAtPos(..)> - no list style found at text node. Serious defect -> please inform OD." ); 431 const SwNumRule* pNumRule = rTNd.GetNumRule(); 432 //Modified for i119959,2012.6.12 433 //Under this scenario,this pointer is null,but on win,it doesn't crash immediately 434 //it exits with exception,and associated memory will have problem which leads to crash problem in 435 //other place in dev env... 436 if ( pNumRule ) 437 { 438 //End 439 const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(rTNd.GetActualListLevel()) ); 440 if( SVX_NUM_BITMAP != rNumFmt.GetNumberingType() ) 441 { 442 if ( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() ) 443 sExp = rNumFmt.GetBulletChar(); 444 else 445 sExp = rTNd.GetNumString(); 446 } 447 //Modified for i119959,2012.6.12 448 //Under this scenario,this pointer is null,but on win,it doesn't crash immediately 449 //it exits with exception,and associated memory will have problem which leads to crash problem in 450 //other place in dev env... 451 } 452 //End 453 } 454 } 455 456 // and fields 457 if ( CH_TXTATR_BREAKWORD == rTxt.GetChar( nPos ) ) 458 { 459 const SwTxtAttr* const pAttr = rTNd.GetTxtAttrForCharAt( nPos ); 460 if (pAttr) 461 { 462 bRet = sal_True; // all other than fields can be 463 // defined as weak-script ? 464 if ( RES_TXTATR_FIELD == pAttr->Which() ) 465 { 466 const SwField* const pFld = pAttr->GetFld().GetFld(); 467 if (pFld) 468 { 469 sExp += pFld->ExpandField(true); 470 } 471 } 472 } 473 } 474 475 xub_StrLen nEnd = sExp.Len(); 476 if ( nEnd ) 477 { 478 xub_StrLen n; 479 if( bInSelection ) 480 { 481 sal_uInt16 nScript; 482 for( n = 0; n < nEnd; n = (xub_StrLen) 483 pBreakIt->GetBreakIter()->endOfScript( sExp, n, nScript )) 484 { 485 nScript = pBreakIt->GetBreakIter()->getScriptType( sExp, n ); 486 rScrpt |= lcl_SetScriptFlags( nScript ); 487 } 488 } 489 else 490 rScrpt |= lcl_SetScriptFlags( pBreakIt->GetBreakIter()-> 491 getScriptType( sExp, nEnd-1 )); 492 } 493 494 return bRet; 495 } 496 497 498 // returns the scripttpye of the selection 499 sal_uInt16 SwEditShell::GetScriptType() const 500 { 501 sal_uInt16 nRet = 0; 502 //if( pBreakIt->GetBreakIter().is() ) 503 { 504 FOREACHPAM_START(this) 505 506 const SwPosition *pStt = PCURCRSR->Start(), 507 *pEnd = pStt == PCURCRSR->GetMark() 508 ? PCURCRSR->GetPoint() 509 : PCURCRSR->GetMark(); 510 if( pStt == pEnd || *pStt == *pEnd ) 511 { 512 const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode(); 513 if( pTNd ) 514 { 515 // try to get SwScriptInfo 516 const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd ); 517 518 xub_StrLen nPos = pStt->nContent.GetIndex(); 519 //Task 90448: we need the scripttype of the previous 520 // position, if no selection exist! 521 if( nPos ) 522 { 523 SwIndex aIdx( pStt->nContent ); 524 if( pTNd->GoPrevious( &aIdx, CRSR_SKIP_CHARS ) ) 525 nPos = aIdx.GetIndex(); 526 } 527 528 sal_uInt16 nScript; 529 530 if ( pTNd->GetTxt().Len() ) 531 { 532 nScript = pScriptInfo ? 533 pScriptInfo->ScriptType( nPos ) : 534 pBreakIt->GetBreakIter()->getScriptType( pTNd->GetTxt(), nPos ); 535 } 536 else 537 nScript = GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() ); 538 539 if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nPos, nRet, sal_False, sal_False )) 540 nRet |= lcl_SetScriptFlags( nScript ); 541 } 542 } 543 else if ( pBreakIt->GetBreakIter().is() ) 544 { 545 sal_uLong nEndIdx = pEnd->nNode.GetIndex(); 546 SwNodeIndex aIdx( pStt->nNode ); 547 for( ; aIdx.GetIndex() <= nEndIdx; aIdx++ ) 548 if( aIdx.GetNode().IsTxtNode() ) 549 { 550 const SwTxtNode* pTNd = aIdx.GetNode().GetTxtNode(); 551 const String& rTxt = pTNd->GetTxt(); 552 553 // try to get SwScriptInfo 554 const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd ); 555 556 xub_StrLen nChg = aIdx == pStt->nNode 557 ? pStt->nContent.GetIndex() 558 : 0, 559 nEndPos = aIdx == nEndIdx 560 ? pEnd->nContent.GetIndex() 561 : rTxt.Len(); 562 563 ASSERT( nEndPos <= rTxt.Len(), "Index outside the range - endless loop!" ); 564 if( nEndPos > rTxt.Len() ) 565 nEndPos = rTxt.Len(); 566 567 sal_uInt16 nScript; 568 while( nChg < nEndPos ) 569 { 570 nScript = pScriptInfo ? 571 pScriptInfo->ScriptType( nChg ) : 572 pBreakIt->GetBreakIter()->getScriptType( 573 rTxt, nChg ); 574 575 if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nChg, nRet, sal_True, 576 0 == nChg && rTxt.Len() == nEndPos ) ) 577 nRet |= lcl_SetScriptFlags( nScript ); 578 579 if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | 580 SCRIPTTYPE_COMPLEX) == nRet ) 581 break; 582 583 xub_StrLen nFldPos = nChg+1; 584 585 nChg = pScriptInfo ? 586 pScriptInfo->NextScriptChg( nChg ) : 587 (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( 588 rTxt, nChg, nScript ); 589 590 nFldPos = rTxt.Search( 591 CH_TXTATR_BREAKWORD, nFldPos ); 592 if( nFldPos < nChg ) 593 nChg = nFldPos; 594 } 595 if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | 596 SCRIPTTYPE_COMPLEX) == nRet ) 597 break; 598 } 599 } 600 if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | 601 SCRIPTTYPE_COMPLEX) == nRet ) 602 break; 603 604 FOREACHPAM_END() 605 } 606 if( !nRet ) 607 nRet = SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM ); 608 return nRet; 609 } 610 611 612 sal_uInt16 SwEditShell::GetCurLang() const 613 { 614 const SwPaM* pCrsr = GetCrsr(); 615 const SwPosition& rPos = *pCrsr->GetPoint(); 616 const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode(); 617 sal_uInt16 nLang; 618 if( pTNd ) 619 { 620 //JP 24.9.2001: if exist no selection, then get the language before 621 // the current character! 622 xub_StrLen nPos = rPos.nContent.GetIndex(); 623 if( nPos && !pCrsr->HasMark() ) 624 --nPos; 625 nLang = pTNd->GetLang( nPos ); 626 } 627 else 628 nLang = LANGUAGE_DONTKNOW; 629 return nLang; 630 } 631 632 sal_uInt16 SwEditShell::GetScalingOfSelectedText() const 633 { 634 const SwPaM* pCrsr = GetCrsr(); 635 const SwPosition* pStt = pCrsr->Start(); 636 const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode(); 637 ASSERT( pTNd, "no textnode available" ); 638 639 sal_uInt16 nScaleWidth; 640 if( pTNd ) 641 { 642 xub_StrLen nStt = pStt->nContent.GetIndex(), nEnd; 643 const SwPosition* pEnd = pStt == pCrsr->GetPoint() 644 ? pCrsr->GetMark() 645 : pCrsr->GetPoint(); 646 if( pStt->nNode == pEnd->nNode ) 647 nEnd = pEnd->nContent.GetIndex(); 648 else 649 nEnd = pTNd->GetTxt().Len(); 650 nScaleWidth = pTNd->GetScalingOfSelectedText( nStt, nEnd ); 651 } 652 else 653 nScaleWidth = 100; // default are no scaling -> 100% 654 return nScaleWidth; 655 } 656