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