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_editeng.hxx" 26 27 #include <algorithm> 28 #include <svl/style.hxx> 29 #include <com/sun/star/i18n/WordType.hpp> 30 31 #include <svl/itemset.hxx> 32 #include <editeng/editeng.hxx> 33 #include <editeng/editdata.hxx> 34 #include <editeng/outliner.hxx> 35 #include <editeng/unoedhlp.hxx> 36 #include <svl/poolitem.hxx> 37 #include <vcl/wrkwin.hxx> 38 #include <editeng/eeitem.hxx> 39 40 #include <editeng/unoforou.hxx> 41 #include <editeng/unofored.hxx> 42 #include <editeng/outlobj.hxx> 43 44 using namespace ::com::sun::star; 45 46 //------------------------------------------------------------------------ 47 48 SvxOutlinerForwarder::SvxOutlinerForwarder( Outliner& rOutl, sal_Bool bOutlText /* = sal_False */ ) : 49 rOutliner( rOutl ), 50 bOutlinerText( bOutlText ), 51 mpAttribsCache( NULL ), 52 mpParaAttribsCache( NULL ), 53 mnParaAttribsCache( 0 ) 54 { 55 } 56 57 SvxOutlinerForwarder::~SvxOutlinerForwarder() 58 { 59 flushCache(); 60 } 61 62 sal_uInt32 SvxOutlinerForwarder::GetParagraphCount() const 63 { 64 return rOutliner.GetParagraphCount(); 65 } 66 67 sal_uInt16 SvxOutlinerForwarder::GetTextLen( sal_uInt32 nParagraph ) const 68 { 69 return rOutliner.GetEditEngine().GetTextLen( nParagraph ); 70 } 71 72 String SvxOutlinerForwarder::GetText( const ESelection& rSel ) const 73 { 74 //! GetText(ESelection) sollte es wohl auch mal am Outliner geben 75 // solange den Hack fuer die EditEngine uebernehmen: 76 EditEngine* pEditEngine = (EditEngine*)&rOutliner.GetEditEngine(); 77 return pEditEngine->GetText( rSel, LINEEND_LF ); 78 } 79 80 static SfxItemSet ImplOutlinerForwarderGetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib, EditEngine& rEditEngine ) 81 { 82 if( rSel.nStartPara == rSel.nEndPara ) 83 { 84 sal_uInt8 nFlags = 0; 85 86 switch( bOnlyHardAttrib ) 87 { 88 case EditEngineAttribs_All: 89 nFlags = GETATTRIBS_ALL; 90 break; 91 case EditEngineAttribs_HardAndPara: 92 nFlags = GETATTRIBS_PARAATTRIBS|GETATTRIBS_CHARATTRIBS; 93 break; 94 case EditEngineAttribs_OnlyHard: 95 nFlags = GETATTRIBS_CHARATTRIBS; 96 break; 97 default: 98 DBG_ERROR("unknown flags for SvxOutlinerForwarder::GetAttribs"); 99 } 100 return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags ); 101 } 102 else 103 { 104 return rEditEngine.GetAttribs( rSel, bOnlyHardAttrib ); 105 } 106 } 107 108 SfxItemSet SvxOutlinerForwarder::GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib ) const 109 { 110 if( mpAttribsCache && ( 0 == bOnlyHardAttrib ) ) 111 { 112 // have we the correct set in cache? 113 if( ((SvxOutlinerForwarder*)this)->maAttribCacheSelection.IsEqual(rSel) ) 114 { 115 // yes! just return the cache 116 return *mpAttribsCache; 117 } 118 else 119 { 120 // no, we need delete the old cache 121 delete mpAttribsCache; 122 mpAttribsCache = NULL; 123 } 124 } 125 126 //! gibt's das nicht am Outliner ??? 127 //! und warum ist GetAttribs an der EditEngine nicht const? 128 EditEngine& rEditEngine = (EditEngine&)rOutliner.GetEditEngine(); 129 130 SfxItemSet aSet( ImplOutlinerForwarderGetAttribs( rSel, bOnlyHardAttrib, rEditEngine ) ); 131 132 if( 0 == bOnlyHardAttrib ) 133 { 134 mpAttribsCache = new SfxItemSet( aSet ); 135 maAttribCacheSelection = rSel; 136 } 137 138 SfxStyleSheet* pStyle = rEditEngine.GetStyleSheet( rSel.nStartPara ); 139 if( pStyle ) 140 aSet.SetParent( &(pStyle->GetItemSet() ) ); 141 142 return aSet; 143 } 144 145 SfxItemSet SvxOutlinerForwarder::GetParaAttribs( sal_uInt32 nPara ) const 146 { 147 if( mpParaAttribsCache ) 148 { 149 // have we the correct set in cache? 150 if( nPara == mnParaAttribsCache ) 151 { 152 // yes! just return the cache 153 return *mpParaAttribsCache; 154 } 155 else 156 { 157 // no, we need delete the old cache 158 delete mpParaAttribsCache; 159 mpParaAttribsCache = NULL; 160 } 161 } 162 163 mpParaAttribsCache = new SfxItemSet( rOutliner.GetParaAttribs( nPara ) ); 164 mnParaAttribsCache = nPara; 165 166 EditEngine& rEditEngine = (EditEngine&)rOutliner.GetEditEngine(); 167 168 SfxStyleSheet* pStyle = rEditEngine.GetStyleSheet( nPara ); 169 if( pStyle ) 170 mpParaAttribsCache->SetParent( &(pStyle->GetItemSet() ) ); 171 172 return *mpParaAttribsCache; 173 } 174 175 void SvxOutlinerForwarder::SetParaAttribs( sal_uInt32 nPara, const SfxItemSet& rSet ) 176 { 177 flushCache(); 178 179 const SfxItemSet* pOldParent = rSet.GetParent(); 180 if( pOldParent ) 181 ((SfxItemSet*)&rSet)->SetParent( NULL ); 182 183 rOutliner.SetParaAttribs( nPara, rSet ); 184 185 if( pOldParent ) 186 ((SfxItemSet*)&rSet)->SetParent( pOldParent ); 187 } 188 189 void SvxOutlinerForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) 190 { 191 rOutliner.RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich ); 192 } 193 194 SfxItemPool* SvxOutlinerForwarder::GetPool() const 195 { 196 return rOutliner.GetEmptyItemSet().GetPool(); 197 } 198 199 void SvxOutlinerForwarder::GetPortions( sal_uInt32 nPara, SvUShorts& rList ) const 200 { 201 ((EditEngine&)rOutliner.GetEditEngine()).GetPortions( nPara, rList ); 202 } 203 204 void SvxOutlinerForwarder::QuickInsertText( const String& rText, const ESelection& rSel ) 205 { 206 flushCache(); 207 if( rText.Len() == 0 ) 208 { 209 rOutliner.QuickDelete( rSel ); 210 } 211 else 212 { 213 rOutliner.QuickInsertText( rText, rSel ); 214 } 215 } 216 217 void SvxOutlinerForwarder::QuickInsertLineBreak( const ESelection& rSel ) 218 { 219 flushCache(); 220 rOutliner.QuickInsertLineBreak( rSel ); 221 } 222 223 void SvxOutlinerForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) 224 { 225 flushCache(); 226 rOutliner.QuickInsertField( rFld, rSel ); 227 } 228 229 void SvxOutlinerForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) 230 { 231 flushCache(); 232 rOutliner.QuickSetAttribs( rSet, rSel ); 233 } 234 235 XubString SvxOutlinerForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_uInt32 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor ) 236 { 237 return rOutliner.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor ); 238 } 239 240 void SvxOutlinerForwarder::FieldClicked( const SvxFieldItem& rField, sal_uInt16 nPara, xub_StrLen nPos ) 241 { 242 rOutliner.FieldClicked( rField, nPara, nPos ); 243 } 244 245 sal_Bool SvxOutlinerForwarder::IsValid() const 246 { 247 // cannot reliably query outliner state 248 // while in the middle of an update 249 return rOutliner.GetUpdateMode(); 250 } 251 252 extern sal_uInt16 GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich ); 253 254 sal_uInt16 SvxOutlinerForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const 255 { 256 return GetSvxEditEngineItemState( (EditEngine&)rOutliner.GetEditEngine(), rSel, nWhich ); 257 } 258 259 sal_uInt16 SvxOutlinerForwarder::GetItemState( sal_uInt32 nPara, sal_uInt16 nWhich ) const 260 { 261 const SfxItemSet& rSet = rOutliner.GetParaAttribs( nPara ); 262 return rSet.GetItemState( nWhich ); 263 } 264 265 266 void SvxOutlinerForwarder::flushCache() 267 { 268 if( mpAttribsCache ) 269 { 270 delete mpAttribsCache; 271 mpAttribsCache = NULL; 272 } 273 274 if( mpParaAttribsCache ) 275 { 276 delete mpParaAttribsCache; 277 mpParaAttribsCache = NULL; 278 } 279 } 280 281 LanguageType SvxOutlinerForwarder::GetLanguage( sal_uInt16 nPara, sal_uInt16 nIndex ) const 282 { 283 return rOutliner.GetLanguage(nPara, nIndex); 284 } 285 286 sal_uInt16 SvxOutlinerForwarder::GetFieldCount( sal_uInt16 nPara ) const 287 { 288 return rOutliner.GetEditEngine().GetFieldCount(nPara); 289 } 290 291 EFieldInfo SvxOutlinerForwarder::GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const 292 { 293 return rOutliner.GetEditEngine().GetFieldInfo( nPara, nField ); 294 } 295 296 EBulletInfo SvxOutlinerForwarder::GetBulletInfo( sal_uInt16 nPara ) const 297 { 298 return rOutliner.GetBulletInfo( nPara ); 299 } 300 301 Rectangle SvxOutlinerForwarder::GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const 302 { 303 // #101701# 304 // EditEngine's 'internal' methods like GetCharacterBounds() 305 // don't rotate for vertical text. 306 Size aSize( rOutliner.CalcTextSize() ); 307 ::std::swap( aSize.Width(), aSize.Height() ); 308 bool bIsVertical( rOutliner.IsVertical() == sal_True ); 309 310 // #108900# Handle virtual position one-past-the end of the string 311 if( nIndex >= GetTextLen(nPara) ) 312 { 313 Rectangle aLast; 314 315 if( nIndex ) 316 { 317 // use last character, if possible 318 aLast = rOutliner.GetEditEngine().GetCharacterBounds( EPosition(nPara, nIndex-1) ); 319 320 // move at end of this last character, make one pixel wide 321 aLast.Move( aLast.Right() - aLast.Left(), 0 ); 322 aLast.SetSize( Size(1, aLast.GetHeight()) ); 323 324 // take care for CTL 325 aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical ); 326 } 327 else 328 { 329 // #109864# Bounds must lie within the paragraph 330 aLast = GetParaBounds( nPara ); 331 332 // #109151# Don't use paragraph height, but line height 333 // instead. aLast is already CTL-correct 334 if( bIsVertical) 335 aLast.SetSize( Size( rOutliner.GetLineHeight(nPara,0), 1 ) ); 336 else 337 aLast.SetSize( Size( 1, rOutliner.GetLineHeight(nPara,0) ) ); 338 } 339 340 return aLast; 341 } 342 else 343 { 344 return SvxEditSourceHelper::EEToUserSpace( rOutliner.GetEditEngine().GetCharacterBounds( EPosition(nPara, nIndex) ), 345 aSize, bIsVertical ); 346 } 347 } 348 349 Rectangle SvxOutlinerForwarder::GetParaBounds( sal_uInt16 nPara ) const 350 { 351 Point aPnt = rOutliner.GetDocPosTopLeft( nPara ); 352 Size aSize = rOutliner.CalcTextSize(); 353 354 if( rOutliner.IsVertical() ) 355 { 356 // #101701# 357 // Hargl. Outliner's 'external' methods return the rotated 358 // dimensions, 'internal' methods like GetTextHeight( n ) 359 // don't rotate. 360 sal_uLong nWidth = rOutliner.GetTextHeight( nPara ); 361 362 return Rectangle( aSize.Width() - aPnt.Y() - nWidth, 0, aSize.Width() - aPnt.Y(), aSize.Height() ); 363 } 364 else 365 { 366 sal_uLong nHeight = rOutliner.GetTextHeight( nPara ); 367 368 return Rectangle( 0, aPnt.Y(), aSize.Width(), aPnt.Y() + nHeight ); 369 } 370 } 371 372 MapMode SvxOutlinerForwarder::GetMapMode() const 373 { 374 return rOutliner.GetRefMapMode(); 375 } 376 377 OutputDevice* SvxOutlinerForwarder::GetRefDevice() const 378 { 379 return rOutliner.GetRefDevice(); 380 } 381 382 sal_Bool SvxOutlinerForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt16& nPara, sal_uInt16& nIndex ) const 383 { 384 // #101701# 385 Size aSize( rOutliner.CalcTextSize() ); 386 ::std::swap( aSize.Width(), aSize.Height() ); 387 Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos, 388 aSize, 389 rOutliner.IsVertical() == sal_True )); 390 391 EPosition aDocPos = rOutliner.GetEditEngine().FindDocPosition( aEEPos ); 392 393 nPara = aDocPos.nPara; 394 nIndex = aDocPos.nIndex; 395 396 return sal_True; 397 } 398 399 sal_Bool SvxOutlinerForwarder::GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const 400 { 401 ESelection aRes = rOutliner.GetEditEngine().GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD ); 402 403 if( aRes.nStartPara == nPara && 404 aRes.nStartPara == aRes.nEndPara ) 405 { 406 nStart = aRes.nStartPos; 407 nEnd = aRes.nEndPos; 408 409 return sal_True; 410 } 411 412 return sal_False; 413 } 414 sal_Bool SvxOutlinerForwarder::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt32 nPara, sal_uInt16 nIndex, sal_Bool bInCell ) const 415 { 416 return SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rOutliner.GetEditEngine(), nPara, nIndex, bInCell ); 417 } 418 419 sal_uInt16 SvxOutlinerForwarder::GetLineCount( sal_uInt16 nPara ) const 420 { 421 return static_cast < sal_uInt16 >( rOutliner.GetLineCount(nPara) ); 422 } 423 424 sal_uInt16 SvxOutlinerForwarder::GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const 425 { 426 return rOutliner.GetLineLen(nPara, nLine); 427 } 428 429 void SvxOutlinerForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nPara, sal_uInt16 nLine ) const 430 { 431 return rOutliner.GetEditEngine().GetLineBoundaries( rStart, rEnd, nPara, nLine ); 432 } 433 434 sal_uInt16 SvxOutlinerForwarder::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const 435 { 436 return rOutliner.GetEditEngine().GetLineNumberAtIndex( nPara, nIndex ); 437 } 438 439 sal_Bool SvxOutlinerForwarder::QuickFormatDoc( sal_Bool ) 440 { 441 rOutliner.QuickFormatDoc(); 442 443 return sal_True; 444 } 445 446 sal_Bool SvxOutlinerForwarder::Delete( const ESelection& rSelection ) 447 { 448 flushCache(); 449 rOutliner.QuickDelete( rSelection ); 450 rOutliner.QuickFormatDoc(); 451 452 return sal_True; 453 } 454 455 sal_Bool SvxOutlinerForwarder::InsertText( const String& rStr, const ESelection& rSelection ) 456 { 457 flushCache(); 458 rOutliner.QuickInsertText( rStr, rSelection ); 459 rOutliner.QuickFormatDoc(); 460 461 return sal_True; 462 } 463 464 sal_Int16 SvxOutlinerForwarder::GetDepth( sal_uInt16 nPara ) const 465 { 466 DBG_ASSERT( nPara < GetParagraphCount(), "SvxOutlinerForwarder::GetDepth: Invalid paragraph index"); 467 468 Paragraph* pPara = rOutliner.GetParagraph( nPara ); 469 470 sal_Int16 nLevel = -1; 471 472 if( pPara ) 473 nLevel = rOutliner.GetDepth( nPara ); 474 475 return nLevel; 476 } 477 478 sal_Bool SvxOutlinerForwarder::SetDepth( sal_uInt16 nPara, sal_Int16 nNewDepth ) 479 { 480 DBG_ASSERT( nPara < GetParagraphCount(), "SvxOutlinerForwarder::SetDepth: Invalid paragraph index"); 481 482 if( (nNewDepth >= -1) && (nNewDepth <= 9) && (nPara < GetParagraphCount()) ) 483 { 484 Paragraph* pPara = rOutliner.GetParagraph( nPara ); 485 if( pPara ) 486 { 487 rOutliner.SetDepth( pPara, nNewDepth ); 488 489 // const bool bOutlinerText = pSdrObject && (pSdrObject->GetObjInventor() == SdrInventor) && (pSdrObject->GetObjIdentifier() == OBJ_OUTLINETEXT); 490 if( bOutlinerText ) 491 rOutliner.SetLevelDependendStyleSheet( nPara ); 492 493 return sal_True; 494 } 495 } 496 497 return sal_False; 498 } 499 500 sal_Int16 SvxOutlinerForwarder::GetNumberingStartValue( sal_uInt16 nPara ) 501 { 502 if( nPara < GetParagraphCount() ) 503 { 504 return rOutliner.GetNumberingStartValue( nPara ); 505 } 506 else 507 { 508 DBG_ERROR( "SvxOutlinerForwarder::GetNumberingStartValue)(), Invalid paragraph index"); 509 return -1; 510 } 511 } 512 513 void SvxOutlinerForwarder::SetNumberingStartValue( sal_uInt16 nPara, sal_Int16 nNumberingStartValue ) 514 { 515 if( nPara < GetParagraphCount() ) 516 { 517 rOutliner.SetNumberingStartValue( nPara, nNumberingStartValue ); 518 } 519 else 520 { 521 DBG_ERROR( "SvxOutlinerForwarder::SetNumberingStartValue)(), Invalid paragraph index"); 522 } 523 } 524 525 sal_Bool SvxOutlinerForwarder::IsParaIsNumberingRestart( sal_uInt16 nPara ) 526 { 527 if( nPara < GetParagraphCount() ) 528 { 529 return rOutliner.IsParaIsNumberingRestart( nPara ); 530 } 531 else 532 { 533 DBG_ERROR( "SvxOutlinerForwarder::IsParaIsNumberingRestart)(), Invalid paragraph index"); 534 return sal_False; 535 } 536 } 537 538 void SvxOutlinerForwarder::SetParaIsNumberingRestart( sal_uInt16 nPara, sal_Bool bParaIsNumberingRestart ) 539 { 540 if( nPara < GetParagraphCount() ) 541 { 542 rOutliner.SetParaIsNumberingRestart( nPara, bParaIsNumberingRestart ); 543 } 544 else 545 { 546 DBG_ERROR( "SvxOutlinerForwarder::SetParaIsNumberingRestart)(), Invalid paragraph index"); 547 } 548 } 549 550 const SfxItemSet * SvxOutlinerForwarder::GetEmptyItemSetPtr() 551 { 552 EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() ); 553 return &rEditEngine.GetEmptyItemSet(); 554 } 555 556 void SvxOutlinerForwarder::AppendParagraph() 557 { 558 EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() ); 559 rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), String::EmptyString() ); 560 } 561 562 xub_StrLen SvxOutlinerForwarder::AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet & /*rSet*/ ) 563 { 564 xub_StrLen nLen = 0; 565 566 EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() ); 567 sal_uInt32 nParaCount = rEditEngine.GetParagraphCount(); 568 DBG_ASSERT( nPara < nParaCount, "paragraph index out of bounds" ); 569 if (/*0 <= nPara && */nPara < nParaCount) 570 { 571 nLen = rEditEngine.GetTextLen( nPara ); 572 rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) ); 573 } 574 575 return nLen; 576 } 577 578 void SvxOutlinerForwarder::CopyText(const SvxTextForwarder& rSource) 579 { 580 const SvxOutlinerForwarder* pSourceForwarder = dynamic_cast< const SvxOutlinerForwarder* >( &rSource ); 581 if( !pSourceForwarder ) 582 return; 583 OutlinerParaObject* pNewOutlinerParaObject = pSourceForwarder->rOutliner.CreateParaObject(); 584 rOutliner.SetText( *pNewOutlinerParaObject ); 585 delete pNewOutlinerParaObject; 586 } 587 588 //------------------------------------------------------------------------ 589 590 591 sal_Int16 SvxTextForwarder::GetNumberingStartValue( sal_uInt16 ) 592 { 593 return -1; 594 } 595 596 void SvxTextForwarder::SetNumberingStartValue( sal_uInt16, sal_Int16 ) 597 { 598 } 599 600 sal_Bool SvxTextForwarder::IsParaIsNumberingRestart( sal_uInt16 ) 601 { 602 return sal_False; 603 } 604 605 void SvxTextForwarder::SetParaIsNumberingRestart( sal_uInt16, sal_Bool ) 606 { 607 } 608 609 //------------------------------------------------------------------------ 610 611