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 <editeng/eeitem.hxx> 33 #include <com/sun/star/i18n/WordType.hpp> 34 35 #include <svl/itemset.hxx> 36 #include <editeng/editeng.hxx> 37 #include <editeng/editview.hxx> 38 #include <editeng/unoedhlp.hxx> 39 #include <editeng/editdata.hxx> 40 #include <editeng/outliner.hxx> 41 #include <editeng/editobj.hxx> // nur fuer die GetText-Kruecke 42 43 #include <editeng/unofored.hxx> 44 45 using namespace ::com::sun::star; 46 47 //------------------------------------------------------------------------ 48 49 SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine& rEngine ) : 50 rEditEngine( rEngine ) 51 { 52 } 53 54 SvxEditEngineForwarder::~SvxEditEngineForwarder() 55 { 56 // die EditEngine muss ggf. von aussen geloescht werden 57 } 58 59 sal_uInt16 SvxEditEngineForwarder::GetParagraphCount() const 60 { 61 return rEditEngine.GetParagraphCount(); 62 } 63 64 sal_uInt16 SvxEditEngineForwarder::GetTextLen( sal_uInt16 nParagraph ) const 65 { 66 return rEditEngine.GetTextLen( nParagraph ); 67 } 68 69 String SvxEditEngineForwarder::GetText( const ESelection& rSel ) const 70 { 71 String aRet = rEditEngine.GetText( rSel, LINEEND_LF ); 72 aRet.ConvertLineEnd(); 73 return aRet; 74 } 75 76 SfxItemSet SvxEditEngineForwarder::GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib ) const 77 { 78 if( rSel.nStartPara == rSel.nEndPara ) 79 { 80 sal_uInt8 nFlags = 0; 81 switch( bOnlyHardAttrib ) 82 { 83 case EditEngineAttribs_All: 84 nFlags = GETATTRIBS_ALL; 85 break; 86 case EditEngineAttribs_HardAndPara: 87 nFlags = GETATTRIBS_PARAATTRIBS|GETATTRIBS_CHARATTRIBS; 88 break; 89 case EditEngineAttribs_OnlyHard: 90 nFlags = GETATTRIBS_CHARATTRIBS; 91 break; 92 default: 93 DBG_ERROR("unknown flags for SvxOutlinerForwarder::GetAttribs"); 94 } 95 96 return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags ); 97 } 98 else 99 { 100 return rEditEngine.GetAttribs( rSel, bOnlyHardAttrib ); 101 } 102 } 103 104 SfxItemSet SvxEditEngineForwarder::GetParaAttribs( sal_uInt16 nPara ) const 105 { 106 SfxItemSet aSet( rEditEngine.GetParaAttribs( nPara ) ); 107 108 sal_uInt16 nWhich = EE_PARA_START; 109 while( nWhich <= EE_PARA_END ) 110 { 111 if( aSet.GetItemState( nWhich, sal_True ) != SFX_ITEM_ON ) 112 { 113 if( rEditEngine.HasParaAttrib( nPara, nWhich ) ) 114 aSet.Put( rEditEngine.GetParaAttrib( nPara, nWhich ) ); 115 } 116 nWhich++; 117 } 118 119 return aSet; 120 } 121 122 void SvxEditEngineForwarder::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet ) 123 { 124 rEditEngine.SetParaAttribs( nPara, rSet ); 125 } 126 127 void SvxEditEngineForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) 128 { 129 rEditEngine.RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich ); 130 } 131 132 SfxItemPool* SvxEditEngineForwarder::GetPool() const 133 { 134 return rEditEngine.GetEmptyItemSet().GetPool(); 135 } 136 137 void SvxEditEngineForwarder::GetPortions( sal_uInt16 nPara, SvUShorts& rList ) const 138 { 139 rEditEngine.GetPortions( nPara, rList ); 140 } 141 142 void SvxEditEngineForwarder::QuickInsertText( const String& rText, const ESelection& rSel ) 143 { 144 rEditEngine.QuickInsertText( rText, rSel ); 145 } 146 147 void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection& rSel ) 148 { 149 rEditEngine.QuickInsertLineBreak( rSel ); 150 } 151 152 void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) 153 { 154 rEditEngine.QuickInsertField( rFld, rSel ); 155 } 156 157 void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) 158 { 159 rEditEngine.QuickSetAttribs( rSet, rSel ); 160 } 161 162 sal_Bool SvxEditEngineForwarder::IsValid() const 163 { 164 // cannot reliably query EditEngine state 165 // while in the middle of an update 166 return rEditEngine.GetUpdateMode(); 167 } 168 169 XubString SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor ) 170 { 171 return rEditEngine.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor ); 172 } 173 174 void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField, sal_uInt16 nPara, xub_StrLen nPos ) 175 { 176 rEditEngine.FieldClicked( rField, nPara, nPos ); 177 } 178 179 sal_uInt16 GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich ) 180 { 181 EECharAttribArray aAttribs; 182 183 const SfxPoolItem* pLastItem = NULL; 184 185 SfxItemState eState = SFX_ITEM_DEFAULT; 186 187 // check all paragraphs inside the selection 188 for( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ ) 189 { 190 SfxItemState eParaState = SFX_ITEM_DEFAULT; 191 192 // calculate start and endpos for this paragraph 193 sal_uInt16 nPos = 0; 194 if( rSel.nStartPara == nPara ) 195 nPos = rSel.nStartPos; 196 197 sal_uInt16 nEndPos = rSel.nEndPos; 198 if( rSel.nEndPara != nPara ) 199 nEndPos = rEditEngine.GetTextLen( nPara ); 200 201 202 // get list of char attribs 203 rEditEngine.GetCharAttribs( nPara, aAttribs ); 204 205 sal_Bool bEmpty = sal_True; // we found no item inside the selektion of this paragraph 206 sal_Bool bGaps = sal_False; // we found items but theire gaps between them 207 sal_uInt16 nLastEnd = nPos; 208 209 const SfxPoolItem* pParaItem = NULL; 210 211 for( sal_uInt16 nAttrib = 0; nAttrib < aAttribs.Count(); nAttrib++ ) 212 { 213 struct EECharAttrib aAttrib = aAttribs.GetObject( nAttrib ); 214 DBG_ASSERT( aAttrib.pAttr, "GetCharAttribs gives corrupt data" ); 215 216 const sal_Bool bEmptyPortion = aAttrib.nStart == aAttrib.nEnd; 217 if( (!bEmptyPortion && (aAttrib.nStart >= nEndPos)) || (bEmptyPortion && (aAttrib.nStart > nEndPos)) ) 218 break; // break if we are already behind our selektion 219 220 if( (!bEmptyPortion && (aAttrib.nEnd <= nPos)) || (bEmptyPortion && (aAttrib.nEnd < nPos)) ) 221 continue; // or if the attribute ends before our selektion 222 223 if( aAttrib.pAttr->Which() != nWhich ) 224 continue; // skip if is not the searched item 225 226 // if we already found an item 227 if( pParaItem ) 228 { 229 // ... and its different to this one than the state is dont care 230 if( *pParaItem != *aAttrib.pAttr ) 231 return SFX_ITEM_DONTCARE; 232 } 233 else 234 { 235 pParaItem = aAttrib.pAttr; 236 } 237 238 if( bEmpty ) 239 bEmpty = sal_False; 240 241 if( !bGaps && aAttrib.nStart > nLastEnd ) 242 bGaps = sal_True; 243 244 nLastEnd = aAttrib.nEnd; 245 } 246 247 if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) ) 248 bGaps = sal_True; 249 /* 250 // since we have no portion with our item or if there were gaps 251 if( bEmpty || bGaps ) 252 { 253 // we need to check the paragraph item 254 const SfxItemSet& rParaSet = rEditEngine.GetParaAttribs( nPara ); 255 if( rParaSet.GetItemState( nWhich ) == SFX_ITEM_SET ) 256 { 257 eState = SFX_ITEM_SET; 258 // get item from the paragraph 259 const SfxPoolItem* pTempItem = rParaSet.GetItem( nWhich ); 260 if( pParaItem ) 261 { 262 if( *pParaItem != *pTempItem ) 263 return SFX_ITEM_DONTCARE; 264 } 265 else 266 { 267 pParaItem = pTempItem; 268 } 269 270 // set if theres no last item or if its the same 271 eParaState = SFX_ITEM_SET; 272 } 273 else if( bEmpty ) 274 { 275 eParaState = SFX_ITEM_DEFAULT; 276 } 277 else if( bGaps ) 278 { 279 // gaps and item not set in paragraph, thats a dont care 280 return SFX_ITEM_DONTCARE; 281 } 282 } 283 else 284 { 285 eParaState = SFX_ITEM_SET; 286 } 287 */ 288 if( bEmpty ) 289 eParaState = SFX_ITEM_DEFAULT; 290 else if( bGaps ) 291 eParaState = SFX_ITEM_DONTCARE; 292 else 293 eParaState = SFX_ITEM_SET; 294 295 // if we already found an item check if we found the same 296 if( pLastItem ) 297 { 298 if( (pParaItem == NULL) || (*pLastItem != *pParaItem) ) 299 return SFX_ITEM_DONTCARE; 300 } 301 else 302 { 303 pLastItem = pParaItem; 304 eState = eParaState; 305 } 306 } 307 308 return eState; 309 } 310 311 sal_uInt16 SvxEditEngineForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const 312 { 313 return GetSvxEditEngineItemState( rEditEngine, rSel, nWhich ); 314 } 315 316 sal_uInt16 SvxEditEngineForwarder::GetItemState( sal_uInt16 nPara, sal_uInt16 nWhich ) const 317 { 318 const SfxItemSet& rSet = rEditEngine.GetParaAttribs( nPara ); 319 return rSet.GetItemState( nWhich ); 320 } 321 322 LanguageType SvxEditEngineForwarder::GetLanguage( sal_uInt16 nPara, sal_uInt16 nIndex ) const 323 { 324 return rEditEngine.GetLanguage(nPara, nIndex); 325 } 326 327 sal_uInt16 SvxEditEngineForwarder::GetFieldCount( sal_uInt16 nPara ) const 328 { 329 return rEditEngine.GetFieldCount(nPara); 330 } 331 332 EFieldInfo SvxEditEngineForwarder::GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const 333 { 334 return rEditEngine.GetFieldInfo( nPara, nField ); 335 } 336 337 EBulletInfo SvxEditEngineForwarder::GetBulletInfo( sal_uInt16 ) const 338 { 339 return EBulletInfo(); 340 } 341 342 Rectangle SvxEditEngineForwarder::GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const 343 { 344 // #101701# 345 // EditEngine's 'internal' methods like GetCharacterBounds() 346 // don't rotate for vertical text. 347 Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() ); 348 ::std::swap( aSize.Width(), aSize.Height() ); 349 bool bIsVertical( rEditEngine.IsVertical() == sal_True ); 350 351 // #108900# Handle virtual position one-past-the end of the string 352 if( nIndex >= rEditEngine.GetTextLen(nPara) ) 353 { 354 Rectangle aLast; 355 356 if( nIndex ) 357 { 358 // use last character, if possible 359 aLast = rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex-1) ); 360 361 // move at end of this last character, make one pixel wide 362 aLast.Move( aLast.Right() - aLast.Left(), 0 ); 363 aLast.SetSize( Size(1, aLast.GetHeight()) ); 364 365 // take care for CTL 366 aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical ); 367 } 368 else 369 { 370 // #109864# Bounds must lie within the paragraph 371 aLast = GetParaBounds( nPara ); 372 373 // #109151# Don't use paragraph height, but line height 374 // instead. aLast is already CTL-correct 375 if( bIsVertical) 376 aLast.SetSize( Size( rEditEngine.GetLineHeight(nPara,0), 1 ) ); 377 else 378 aLast.SetSize( Size( 1, rEditEngine.GetLineHeight(nPara,0) ) ); 379 } 380 381 return aLast; 382 } 383 else 384 { 385 return SvxEditSourceHelper::EEToUserSpace( rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex) ), 386 aSize, bIsVertical ); 387 } 388 } 389 390 Rectangle SvxEditEngineForwarder::GetParaBounds( sal_uInt16 nPara ) const 391 { 392 const Point aPnt = rEditEngine.GetDocPosTopLeft( nPara ); 393 sal_uLong nWidth; 394 sal_uLong nHeight; 395 sal_uLong nTextWidth; 396 397 if( rEditEngine.IsVertical() ) 398 { 399 // #101701# 400 // Hargl. EditEngine's 'external' methods return the rotated 401 // dimensions, 'internal' methods like GetTextHeight( n ) 402 // don't rotate. 403 nWidth = rEditEngine.GetTextHeight( nPara ); 404 nHeight = rEditEngine.GetTextHeight(); 405 nTextWidth = rEditEngine.GetTextHeight(); 406 407 return Rectangle( nTextWidth - aPnt.Y() - nWidth, 0, nTextWidth - aPnt.Y(), nHeight ); 408 } 409 else 410 { 411 nWidth = rEditEngine.CalcTextWidth(); 412 nHeight = rEditEngine.GetTextHeight( nPara ); 413 414 return Rectangle( 0, aPnt.Y(), nWidth, aPnt.Y() + nHeight ); 415 } 416 } 417 418 MapMode SvxEditEngineForwarder::GetMapMode() const 419 { 420 return rEditEngine.GetRefMapMode(); 421 } 422 423 OutputDevice* SvxEditEngineForwarder::GetRefDevice() const 424 { 425 return rEditEngine.GetRefDevice(); 426 } 427 428 sal_Bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt16& nPara, sal_uInt16& nIndex ) const 429 { 430 // #101701# 431 Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() ); 432 ::std::swap( aSize.Width(), aSize.Height() ); 433 Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos, 434 aSize, 435 rEditEngine.IsVertical() == sal_True )); 436 437 EPosition aDocPos = rEditEngine.FindDocPosition( aEEPos ); 438 439 nPara = aDocPos.nPara; 440 nIndex = aDocPos.nIndex; 441 442 return sal_True; 443 } 444 445 sal_Bool SvxEditEngineForwarder::GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const 446 { 447 ESelection aRes = rEditEngine.GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD ); 448 449 if( aRes.nStartPara == nPara && 450 aRes.nStartPara == aRes.nEndPara ) 451 { 452 nStart = aRes.nStartPos; 453 nEnd = aRes.nEndPos; 454 455 return sal_True; 456 } 457 458 return sal_False; 459 } 460 461 sal_Bool SvxEditEngineForwarder::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt16 nPara, sal_uInt16 nIndex ) const 462 { 463 return SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rEditEngine, nPara, nIndex ); 464 } 465 466 sal_uInt16 SvxEditEngineForwarder::GetLineCount( sal_uInt16 nPara ) const 467 { 468 return rEditEngine.GetLineCount(nPara); 469 } 470 471 sal_uInt16 SvxEditEngineForwarder::GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const 472 { 473 return rEditEngine.GetLineLen(nPara, nLine); 474 } 475 476 void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nPara, sal_uInt16 nLine ) const 477 { 478 rEditEngine.GetLineBoundaries(rStart, rEnd, nPara, nLine); 479 } 480 481 sal_uInt16 SvxEditEngineForwarder::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const 482 { 483 return rEditEngine.GetLineNumberAtIndex(nPara, nIndex); 484 } 485 486 487 sal_Bool SvxEditEngineForwarder::QuickFormatDoc( sal_Bool ) 488 { 489 rEditEngine.QuickFormatDoc(); 490 491 return sal_True; 492 } 493 494 sal_Bool SvxEditEngineForwarder::Delete( const ESelection& rSelection ) 495 { 496 rEditEngine.QuickDelete( rSelection ); 497 rEditEngine.QuickFormatDoc(); 498 499 return sal_True; 500 } 501 502 sal_Bool SvxEditEngineForwarder::InsertText( const String& rStr, const ESelection& rSelection ) 503 { 504 rEditEngine.QuickInsertText( rStr, rSelection ); 505 rEditEngine.QuickFormatDoc(); 506 507 return sal_True; 508 } 509 510 sal_Int16 SvxEditEngineForwarder::GetDepth( sal_uInt16 ) const 511 { 512 // EditEngine does not support outline depth 513 return -1; 514 } 515 516 sal_Bool SvxEditEngineForwarder::SetDepth( sal_uInt16, sal_Int16 nNewDepth ) 517 { 518 // EditEngine does not support outline depth 519 return nNewDepth == -1 ? sal_True : sal_False; 520 } 521 522 const SfxItemSet * SvxEditEngineForwarder::GetEmptyItemSetPtr() 523 { 524 return &rEditEngine.GetEmptyItemSet(); 525 } 526 527 void SvxEditEngineForwarder::AppendParagraph() 528 { 529 rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), String::EmptyString() ); 530 } 531 532 xub_StrLen SvxEditEngineForwarder::AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet & /*rSet*/ ) 533 { 534 xub_StrLen nLen = 0; 535 536 sal_uInt16 nParaCount = rEditEngine.GetParagraphCount(); 537 DBG_ASSERT( nPara < nParaCount, "paragraph index out of bounds" ); 538 if (/*0 <= nPara && */nPara < nParaCount) 539 { 540 nLen = rEditEngine.GetTextLen( nPara ); 541 rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) ); 542 } 543 544 return nLen; 545 } 546 547 void SvxEditEngineForwarder::CopyText(const SvxTextForwarder& rSource) 548 { 549 const SvxEditEngineForwarder* pSourceForwarder = dynamic_cast< const SvxEditEngineForwarder* >( &rSource ); 550 if( !pSourceForwarder ) 551 return; 552 EditTextObject* pNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject(); 553 rEditEngine.SetText( *pNewTextObject ); 554 delete pNewTextObject; 555 } 556 557 //------------------------------------------------------------------------ 558