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 <svl/intitem.hxx> 28 #include <editeng/editeng.hxx> 29 #include <editeng/editview.hxx> 30 #include <editeng/editdata.hxx> 31 #include <editeng/eerdll.hxx> 32 #include <editeng/lrspitem.hxx> 33 #include <editeng/fhgtitem.hxx> 34 35 #include <math.h> 36 #include <svl/style.hxx> 37 #include <vcl/wrkwin.hxx> 38 #define _OUTLINER_CXX 39 #include <editeng/outliner.hxx> 40 #include <paralist.hxx> 41 #include <editeng/outlobj.hxx> 42 #include <outleeng.hxx> 43 #include <outlundo.hxx> 44 #include <editeng/eeitem.hxx> 45 #include <editeng/editstat.hxx> 46 #include <editeng/scripttypeitem.hxx> 47 #include <editeng/editobj.hxx> 48 #include <svl/itemset.hxx> 49 #include <svl/whiter.hxx> 50 #include <vcl/metric.hxx> 51 #include <editeng/numitem.hxx> 52 #include <editeng/adjitem.hxx> 53 #include <vcl/graph.hxx> 54 #include <vcl/gdimtf.hxx> 55 #include <vcl/metaact.hxx> 56 #include <svtools/grfmgr.hxx> 57 #include <editeng/svxfont.hxx> 58 #include <editeng/brshitem.hxx> 59 #include <svl/itempool.hxx> 60 61 // #101498# calculate if it's RTL or not 62 #include <unicode/ubidi.h> 63 64 #define DEFAULT_SCALE 75 65 66 static const sal_uInt16 nDefStyles = 3; // Sonderbehandlung fuer die ersten 3 Ebenen 67 static const sal_uInt16 nDefBulletIndent = 800; 68 static const sal_uInt16 nDefBulletWidth = 700; 69 static const sal_uInt16 pDefBulletIndents[nDefStyles]= { 1400, 800, 800 }; 70 static const sal_uInt16 pDefBulletWidths[nDefStyles] = { 1000, 850, 700 }; 71 72 sal_uInt16 lcl_ImplGetDefBulletWidth( sal_Int16 nDepth ) 73 { 74 return ( nDepth < nDefStyles ) ? pDefBulletWidths[nDepth] : nDefBulletWidth; 75 } 76 77 sal_uInt16 lcl_ImplGetDefBulletIndent( sal_Int16 nDepth ) 78 { 79 sal_uInt16 nI = 0; 80 81 if( nDepth >= 0 ) 82 { 83 for ( sal_Int16 n = 0; n <= nDepth; n++ ) 84 nI = nI + 85 ( ( n < nDefStyles ) ? pDefBulletIndents[n] : nDefBulletIndent ); 86 } 87 return nI; 88 } 89 90 91 // ---------------------------------------------------------------------- 92 // Outliner 93 // ---------------------------------------------------------------------- 94 DBG_NAME(Outliner); 95 96 void Outliner::ImplCheckDepth( sal_Int16& rnDepth ) const 97 { 98 if( rnDepth < nMinDepth ) 99 rnDepth = nMinDepth; 100 else if( rnDepth > nMaxDepth ) 101 rnDepth = nMaxDepth; 102 } 103 104 Paragraph* Outliner::Insert(const XubString& rText, sal_uLong nAbsPos, sal_Int16 nDepth) 105 { 106 DBG_CHKTHIS(Outliner,0); 107 DBG_ASSERT(pParaList->GetParagraphCount(),"Insert:No Paras"); 108 109 Paragraph* pPara; 110 111 ImplCheckDepth( nDepth ); 112 113 sal_uLong nParagraphCount = pParaList->GetParagraphCount(); 114 if( nAbsPos > nParagraphCount ) 115 nAbsPos = nParagraphCount; 116 117 if( bFirstParaIsEmpty ) 118 { 119 pPara = pParaList->GetParagraph( 0 ); 120 if( pPara->GetDepth() != nDepth ) 121 { 122 nDepthChangedHdlPrevDepth = pPara->GetDepth(); 123 mnDepthChangeHdlPrevFlags = pPara->nFlags; 124 pPara->SetDepth( nDepth ); 125 pHdlParagraph = pPara; 126 DepthChangedHdl(); 127 } 128 pPara->nFlags |= PARAFLAG_HOLDDEPTH; 129 SetText( rText, pPara ); 130 } 131 else 132 { 133 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 134 pEditEngine->SetUpdateMode( sal_False ); 135 ImplBlockInsertionCallbacks( sal_True ); 136 pPara = new Paragraph( nDepth ); 137 pParaList->Insert( pPara, nAbsPos ); 138 pEditEngine->InsertParagraph( (sal_uInt16)nAbsPos, String() ); 139 DBG_ASSERT(pPara==pParaList->GetParagraph(nAbsPos),"Insert:Failed"); 140 ImplInitDepth( (sal_uInt16)nAbsPos, nDepth, sal_False ); 141 pHdlParagraph = pPara; 142 ParagraphInsertedHdl(); 143 pPara->nFlags |= PARAFLAG_HOLDDEPTH; 144 SetText( rText, pPara ); 145 ImplBlockInsertionCallbacks( sal_False ); 146 pEditEngine->SetUpdateMode( bUpdate ); 147 } 148 bFirstParaIsEmpty = sal_False; 149 DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed"); 150 return pPara; 151 } 152 153 154 void Outliner::ParagraphInserted( sal_uInt16 nPara ) 155 { 156 DBG_CHKTHIS(Outliner,0); 157 158 if ( bBlockInsCallback ) 159 return; 160 161 if( bPasting || pEditEngine->IsInUndo() ) 162 { 163 Paragraph* pPara = new Paragraph( -1 ); 164 pParaList->Insert( pPara, nPara ); 165 if( pEditEngine->IsInUndo() ) 166 { 167 pPara->nFlags = PARAFLAG_SETBULLETTEXT; 168 pPara->bVisible = sal_True; 169 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); 170 pPara->SetDepth( rLevel.GetValue() ); 171 } 172 } 173 else 174 { 175 sal_Int16 nDepth = -1; 176 Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 ); 177 if ( pParaBefore ) 178 nDepth = pParaBefore->GetDepth(); 179 180 Paragraph* pPara = new Paragraph( nDepth ); 181 pParaList->Insert( pPara, nPara ); 182 183 if( !pEditEngine->IsInUndo() ) 184 { 185 ImplCalcBulletText( nPara, sal_True, sal_False ); 186 pHdlParagraph = pPara; 187 ParagraphInsertedHdl(); 188 } 189 } 190 } 191 192 void Outliner::ParagraphDeleted( sal_uInt16 nPara ) 193 { 194 DBG_CHKTHIS(Outliner,0); 195 196 if ( bBlockInsCallback || ( nPara == EE_PARA_ALL ) ) 197 return; 198 199 Paragraph* pPara = pParaList->GetParagraph( nPara ); 200 if (!pPara) 201 return; 202 203 sal_Int16 nDepth = pPara->GetDepth(); 204 205 if( !pEditEngine->IsInUndo() ) 206 { 207 pHdlParagraph = pPara; 208 ParagraphRemovingHdl(); 209 } 210 211 pParaList->Remove( nPara ); 212 delete pPara; 213 214 if( !pEditEngine->IsInUndo() && !bPasting ) 215 { 216 pPara = pParaList->GetParagraph( nPara ); 217 if ( pPara && ( pPara->GetDepth() > nDepth ) ) 218 { 219 ImplCalcBulletText( nPara, sal_True, sal_False ); 220 // naechsten auf gleicher Ebene suchen... 221 while ( pPara && pPara->GetDepth() > nDepth ) 222 pPara = pParaList->GetParagraph( ++nPara ); 223 } 224 225 if ( pPara && ( pPara->GetDepth() == nDepth ) ) 226 ImplCalcBulletText( nPara, sal_True, sal_False ); 227 } 228 } 229 230 void Outliner::Init( sal_uInt16 nMode ) 231 { 232 nOutlinerMode = nMode; 233 234 Clear(); 235 236 sal_uLong nCtrl = pEditEngine->GetControlWord(); 237 nCtrl &= ~(EE_CNTRL_OUTLINER|EE_CNTRL_OUTLINER2); 238 239 SetMaxDepth( 9 ); 240 241 switch ( ImplGetOutlinerMode() ) 242 { 243 case OUTLINERMODE_TEXTOBJECT: 244 case OUTLINERMODE_TITLEOBJECT: 245 break; 246 247 case OUTLINERMODE_OUTLINEOBJECT: 248 nCtrl |= EE_CNTRL_OUTLINER2; 249 break; 250 case OUTLINERMODE_OUTLINEVIEW: 251 nCtrl |= EE_CNTRL_OUTLINER; 252 break; 253 254 default: DBG_ERROR( "Outliner::Init - Invalid Mode!" ); 255 } 256 257 pEditEngine->SetControlWord( nCtrl ); 258 259 ImplInitDepth( 0, GetMinDepth(), sal_False ); 260 261 GetUndoManager().Clear(); 262 } 263 264 void Outliner::SetMaxDepth( sal_Int16 nDepth, sal_Bool bCheckParagraphs ) 265 { 266 if( nMaxDepth != nDepth ) 267 { 268 nMaxDepth = Min( nDepth, (sal_Int16)(SVX_MAX_NUM-1) ); 269 270 if( bCheckParagraphs ) 271 { 272 sal_uInt16 nParagraphs = (sal_uInt16)pParaList->GetParagraphCount(); 273 for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ ) 274 { 275 Paragraph* pPara = pParaList->GetParagraph( nPara ); 276 if( pPara && pPara->GetDepth() > nMaxDepth ) 277 { 278 SetDepth( pPara, nMaxDepth ); 279 } 280 } 281 } 282 } 283 } 284 285 sal_Int16 Outliner::GetDepth( sal_uLong nPara ) const 286 { 287 Paragraph* pPara = pParaList->GetParagraph( nPara ); 288 DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" ); 289 return pPara ? pPara->GetDepth() : -1; 290 } 291 292 void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth ) 293 { 294 DBG_CHKTHIS(Outliner,0); 295 296 ImplCheckDepth( nNewDepth ); 297 298 if ( nNewDepth != pPara->GetDepth() ) 299 { 300 nDepthChangedHdlPrevDepth = pPara->GetDepth(); 301 mnDepthChangeHdlPrevFlags = pPara->nFlags; 302 pHdlParagraph = pPara; 303 304 sal_uInt16 nPara = (sal_uInt16)GetAbsPos( pPara ); 305 ImplInitDepth( nPara, nNewDepth, sal_True ); 306 ImplCalcBulletText( nPara, sal_False, sal_False ); 307 308 if ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) 309 ImplSetLevelDependendStyleSheet( nPara ); 310 311 DepthChangedHdl(); 312 } 313 } 314 315 sal_Int16 Outliner::GetNumberingStartValue( sal_uInt16 nPara ) 316 { 317 Paragraph* pPara = pParaList->GetParagraph( nPara ); 318 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" ); 319 return pPara ? pPara->GetNumberingStartValue() : -1; 320 } 321 322 void Outliner::SetNumberingStartValue( sal_uInt16 nPara, sal_Int16 nNumberingStartValue ) 323 { 324 Paragraph* pPara = pParaList->GetParagraph( nPara ); 325 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" ); 326 if( pPara && pPara->GetNumberingStartValue() != nNumberingStartValue ) 327 { 328 if( IsUndoEnabled() && !IsInUndo() ) 329 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara, 330 pPara->GetNumberingStartValue(), nNumberingStartValue, 331 pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) ); 332 333 pPara->SetNumberingStartValue( nNumberingStartValue ); 334 // --> OD 2009-03-10 #i100014# 335 // It is not a good idea to substract 1 from a count and cast the result 336 // to sal_uInt16 without check, if the count is 0. 337 ImplCheckParagraphs( nPara, (sal_uInt16) (pParaList->GetParagraphCount()) ); 338 // <-- 339 pEditEngine->SetModified(); 340 } 341 } 342 343 sal_Bool Outliner::IsParaIsNumberingRestart( sal_uInt16 nPara ) 344 { 345 Paragraph* pPara = pParaList->GetParagraph( nPara ); 346 DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" ); 347 return pPara ? pPara->IsParaIsNumberingRestart() : sal_False; 348 } 349 350 void Outliner::SetParaIsNumberingRestart( sal_uInt16 nPara, sal_Bool bParaIsNumberingRestart ) 351 { 352 Paragraph* pPara = pParaList->GetParagraph( nPara ); 353 DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" ); 354 if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) ) 355 { 356 if( IsUndoEnabled() && !IsInUndo() ) 357 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara, 358 pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(), 359 pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) ); 360 361 pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart ); 362 // --> OD 2009-03-10 #i100014# 363 // It is not a good idea to substract 1 from a count and cast the result 364 // to sal_uInt16 without check, if the count is 0. 365 ImplCheckParagraphs( nPara, (sal_uInt16) (pParaList->GetParagraphCount()) ); 366 // <-- 367 pEditEngine->SetModified(); 368 } 369 } 370 371 OutlinerParaObject* Outliner::CreateParaObject( sal_uInt16 nStartPara, sal_uInt16 nCount ) const 372 { 373 DBG_CHKTHIS(Outliner,0); 374 375 if ( sal::static_int_cast< sal_uLong >( nStartPara + nCount ) > 376 pParaList->GetParagraphCount() ) 377 nCount = sal::static_int_cast< sal_uInt16 >( 378 pParaList->GetParagraphCount() - nStartPara ); 379 380 // When a new OutlinerParaObject is created because a paragraph is just beeing deleted, 381 // it can happen that the ParaList is not updated yet... 382 if ( ( nStartPara + nCount ) > pEditEngine->GetParagraphCount() ) 383 nCount = pEditEngine->GetParagraphCount() - nStartPara; 384 385 if( !nCount ) 386 return NULL; 387 388 EditTextObject* pText = pEditEngine->CreateTextObject( nStartPara, nCount ); 389 const bool bIsEditDoc(OUTLINERMODE_TEXTOBJECT == ImplGetOutlinerMode()); 390 ParagraphDataVector aParagraphDataVector(nCount); 391 const sal_uInt16 nLastPara(nStartPara + nCount - 1); 392 393 for(sal_uInt16 nPara(nStartPara); nPara <= nLastPara; nPara++) 394 { 395 aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara); 396 } 397 398 OutlinerParaObject* pPObj = new OutlinerParaObject(*pText, aParagraphDataVector, bIsEditDoc); 399 pPObj->SetOutlinerMode(GetMode()); 400 delete pText; 401 402 return pPObj; 403 } 404 405 void Outliner::SetText( const XubString& rText, Paragraph* pPara ) 406 { 407 DBG_CHKTHIS(Outliner,0); 408 DBG_ASSERT(pPara,"SetText:No Para"); 409 410 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 411 pEditEngine->SetUpdateMode( sal_False ); 412 ImplBlockInsertionCallbacks( sal_True ); 413 414 sal_uInt16 nPara = (sal_uInt16)pParaList->GetAbsPos( pPara ); 415 416 if( !rText.Len() ) 417 { 418 pEditEngine->SetText( nPara, rText ); 419 ImplInitDepth( nPara, pPara->GetDepth(), sal_False ); 420 } 421 else 422 { 423 XubString aText( rText ); 424 aText.ConvertLineEnd( LINEEND_LF ); 425 426 if( aText.GetChar( aText.Len()-1 ) == '\x0A' ) 427 aText.Erase( aText.Len()-1, 1 ); // letzten Umbruch loeschen 428 429 sal_uInt16 nCount = aText.GetTokenCount( '\x0A' ); 430 sal_uInt16 nPos = 0; 431 sal_uInt16 nInsPos = nPara+1; 432 while( nCount > nPos ) 433 { 434 XubString aStr = aText.GetToken( nPos, '\x0A' ); 435 436 sal_Int16 nCurDepth; 437 if( nPos ) 438 { 439 pPara = new Paragraph( -1 ); 440 nCurDepth = -1; 441 } 442 else 443 nCurDepth = pPara->GetDepth(); 444 445 // Im Outliner-Modus die Tabulatoren filtern und die 446 // Einrueckung ueber ein LRSpaceItem einstellen 447 // Im EditEngine-Modus ueber Maltes Tabulatoren einruecken 448 if( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || 449 ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ) ) 450 { 451 // Tabs raus 452 sal_uInt16 nTabs = 0; 453 while ( ( nTabs < aStr.Len() ) && ( aStr.GetChar( nTabs ) == '\t' ) ) 454 nTabs++; 455 if ( nTabs ) 456 aStr.Erase( 0, nTabs ); 457 458 // Tiefe beibehalten ? (siehe Outliner::Insert) 459 if( !(pPara->nFlags & PARAFLAG_HOLDDEPTH) ) 460 { 461 nCurDepth = nTabs-1; 462 ImplCheckDepth( nCurDepth ); 463 pPara->SetDepth( nCurDepth ); 464 pPara->nFlags &= (~PARAFLAG_HOLDDEPTH); 465 } 466 } 467 if( nPos ) // nicht mit dem ersten Absatz 468 { 469 pParaList->Insert( pPara, nInsPos ); 470 pEditEngine->InsertParagraph( nInsPos, aStr ); 471 pHdlParagraph = pPara; 472 ParagraphInsertedHdl(); 473 } 474 else 475 { 476 nInsPos--; 477 pEditEngine->SetText( nInsPos, aStr ); 478 } 479 ImplInitDepth( nInsPos, nCurDepth, sal_False ); 480 nInsPos++; 481 nPos++; 482 } 483 } 484 485 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"SetText failed!"); 486 bFirstParaIsEmpty = sal_False; 487 ImplBlockInsertionCallbacks( sal_False ); 488 pEditEngine->SetUpdateMode( bUpdate ); 489 } 490 491 // pView == 0 -> Tabulatoren nicht beachten 492 493 bool Outliner::ImpConvertEdtToOut( sal_uInt32 nPara,EditView* pView) 494 { 495 DBG_CHKTHIS(Outliner,0); 496 497 bool bConverted = false; 498 sal_uInt16 nTabs = 0; 499 ESelection aDelSel; 500 501 // const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (sal_uInt16)nPara ); 502 // bool bAlreadyOutliner = rAttrs.GetItemState( EE_PARA_OUTLLRSPACE ) == SFX_ITEM_ON ? true : false; 503 504 XubString aName; 505 XubString aHeading_US( RTL_CONSTASCII_USTRINGPARAM( "heading" ) ); 506 XubString aNumber_US( RTL_CONSTASCII_USTRINGPARAM( "Numbering" ) ); 507 508 XubString aStr( pEditEngine->GetText( (sal_uInt16)nPara ) ); 509 xub_Unicode* pPtr = (xub_Unicode*)aStr.GetBuffer(); 510 511 sal_uInt16 nHeadingNumberStart = 0; 512 sal_uInt16 nNumberingNumberStart = 0; 513 SfxStyleSheet* pStyle= pEditEngine->GetStyleSheet( (sal_uInt16)nPara ); 514 if( pStyle ) 515 { 516 aName = pStyle->GetName(); 517 sal_uInt16 nSearch; 518 if ( ( nSearch = aName.Search( aHeading_US ) ) != STRING_NOTFOUND ) 519 nHeadingNumberStart = nSearch + aHeading_US.Len(); 520 else if ( ( nSearch = aName.Search( aNumber_US ) ) != STRING_NOTFOUND ) 521 nNumberingNumberStart = nSearch + aNumber_US.Len(); 522 } 523 524 if ( nHeadingNumberStart || nNumberingNumberStart ) 525 { 526 // PowerPoint-Import ? 527 if( nHeadingNumberStart && ( aStr.Len() >= 2 ) && 528 ( pPtr[0] != '\t' ) && ( pPtr[1] == '\t' ) ) 529 { 530 // Bullet & Tab raus 531 aDelSel = ESelection( (sal_uInt16)nPara, 0, (sal_uInt16)nPara, 2 ); 532 } 533 534 sal_uInt16 nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart; 535 String aLevel = aName.Copy( nPos ); 536 aLevel.EraseLeadingChars( ' ' ); 537 nTabs = sal::static_int_cast< sal_uInt16 >(aLevel.ToInt32()); 538 if( nTabs ) 539 nTabs--; // ebene 0 = "heading 1" 540 bConverted = sal_True; 541 } 542 else 543 { 544 // Fuehrende Tabulatoren filtern 545 while( *pPtr == '\t' ) 546 { 547 pPtr++; 548 nTabs++; 549 } 550 // Tabulatoren aus dem Text entfernen 551 if( nTabs ) 552 aDelSel = ESelection( (sal_uInt16)nPara, 0, (sal_uInt16)nPara, nTabs ); 553 } 554 555 if ( aDelSel.HasRange() ) 556 { 557 if ( pView ) 558 { 559 pView->SetSelection( aDelSel ); 560 pView->DeleteSelected(); 561 } 562 else 563 pEditEngine->QuickDelete( aDelSel ); 564 } 565 566 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( sal::static_int_cast< sal_uInt16 >(nPara), EE_PARA_OUTLLEVEL ); 567 sal_Int16 nOutlLevel = rLevel.GetValue(); 568 569 ImplCheckDepth( nOutlLevel ); 570 ImplInitDepth( sal::static_int_cast< sal_uInt16 >(nPara), nOutlLevel, sal_False ); 571 572 return bConverted; 573 } 574 575 void Outliner::SetText( const OutlinerParaObject& rPObj ) 576 { 577 DBG_CHKTHIS(Outliner,0); 578 579 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 580 pEditEngine->SetUpdateMode( sal_False ); 581 582 sal_Bool bUndo = pEditEngine->IsUndoEnabled(); 583 EnableUndo( sal_False ); 584 585 Init( rPObj.GetOutlinerMode() ); 586 587 ImplBlockInsertionCallbacks( sal_True ); 588 pEditEngine->SetText(rPObj.GetTextObject()); 589 if( rPObj.Count() != pEditEngine->GetParagraphCount() ) 590 { 591 int nop=0;nop++; 592 } 593 594 bFirstParaIsEmpty = sal_False; 595 596 pParaList->Clear( sal_True ); 597 for( sal_uInt16 nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ ) 598 { 599 Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(nCurPara)); 600 ImplCheckDepth( pPara->nDepth ); 601 602 pParaList->Insert( pPara, LIST_APPEND ); 603 ImplCheckNumBulletItem( nCurPara ); 604 } 605 606 // --> OD 2009-03-10 #i100014# 607 // It is not a good idea to substract 1 from a count and cast the result 608 // to sal_uInt16 without check, if the count is 0. 609 ImplCheckParagraphs( 0, (sal_uInt16) (pParaList->GetParagraphCount()) ); 610 // <-- 611 612 EnableUndo( bUndo ); 613 ImplBlockInsertionCallbacks( sal_False ); 614 pEditEngine->SetUpdateMode( bUpdate ); 615 616 DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed"); 617 DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed"); 618 } 619 620 void Outliner::AddText( const OutlinerParaObject& rPObj ) 621 { 622 DBG_CHKTHIS(Outliner,0); 623 Paragraph* pPara; 624 625 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 626 pEditEngine->SetUpdateMode( sal_False ); 627 628 ImplBlockInsertionCallbacks( sal_True ); 629 sal_uLong nPara; 630 if( bFirstParaIsEmpty ) 631 { 632 pParaList->Clear( sal_True ); 633 pEditEngine->SetText(rPObj.GetTextObject()); 634 nPara = 0; 635 } 636 else 637 { 638 nPara = pParaList->GetParagraphCount(); 639 pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() ); 640 } 641 bFirstParaIsEmpty = sal_False; 642 643 for( sal_uInt16 n = 0; n < rPObj.Count(); n++ ) 644 { 645 pPara = new Paragraph( rPObj.GetParagraphData(n) ); 646 pParaList->Insert( pPara, LIST_APPEND ); 647 sal_uInt16 nP = sal::static_int_cast< sal_uInt16 >(nPara+n); 648 DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync"); 649 ImplInitDepth( nP, pPara->GetDepth(), sal_False ); 650 } 651 DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" ); 652 653 // --> OD 2009-03-10 #i100014# 654 // It is not a good idea to substract 1 from a count and cast the result 655 // to sal_uInt16 without check, if the count is 0. 656 ImplCheckParagraphs( (sal_uInt16)nPara, (sal_uInt16) (pParaList->GetParagraphCount()) ); 657 // <-- 658 659 ImplBlockInsertionCallbacks( sal_False ); 660 pEditEngine->SetUpdateMode( bUpdate ); 661 } 662 663 void __EXPORT Outliner::FieldClicked( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos ) 664 { 665 DBG_CHKTHIS(Outliner,0); 666 667 if ( aFieldClickedHdl.IsSet() ) 668 { 669 EditFieldInfo aFldInfo( this, rField, nPara, nPos ); 670 aFldInfo.SetSimpleClick( sal_True ); 671 aFieldClickedHdl.Call( &aFldInfo ); 672 } 673 } 674 675 676 void __EXPORT Outliner::FieldSelected( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos ) 677 { 678 DBG_CHKTHIS(Outliner,0); 679 if ( !aFieldClickedHdl.IsSet() ) 680 return; 681 682 EditFieldInfo aFldInfo( this, rField, nPara, nPos ); 683 aFldInfo.SetSimpleClick( sal_False ); 684 aFieldClickedHdl.Call( &aFldInfo ); 685 } 686 687 688 XubString __EXPORT Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor ) 689 { 690 DBG_CHKTHIS(Outliner,0); 691 if ( !aCalcFieldValueHdl.IsSet() ) 692 return String( ' ' ); 693 694 EditFieldInfo aFldInfo( this, rField, nPara, nPos ); 695 // Die FldColor ist mit COL_LIGHTGRAY voreingestellt. 696 if ( rpFldColor ) 697 aFldInfo.SetFldColor( *rpFldColor ); 698 699 aCalcFieldValueHdl.Call( &aFldInfo ); 700 if ( aFldInfo.GetTxtColor() ) 701 { 702 delete rpTxtColor; 703 rpTxtColor = new Color( *aFldInfo.GetTxtColor() ); 704 } 705 706 delete rpFldColor; 707 rpFldColor = aFldInfo.GetFldColor() ? new Color( *aFldInfo.GetFldColor() ) : 0; 708 709 return aFldInfo.GetRepresentation(); 710 } 711 712 void Outliner::SetStyleSheet( sal_uLong nPara, SfxStyleSheet* pStyle ) 713 { 714 DBG_CHKTHIS(Outliner,0); 715 Paragraph* pPara = pParaList->GetParagraph( nPara ); 716 if (pPara) 717 { 718 pEditEngine->SetStyleSheet( (sal_uInt16)nPara, pStyle ); 719 pPara->nFlags |= PARAFLAG_SETBULLETTEXT; 720 ImplCheckNumBulletItem( (sal_uInt16) nPara ); 721 } 722 } 723 724 void Outliner::SetVisible( Paragraph* pPara, sal_Bool bVisible ) 725 { 726 DBG_CHKTHIS(Outliner,0); 727 DBG_ASSERT( pPara, "SetVisible: pPara = NULL" ); 728 729 if (pPara) 730 { 731 pPara->bVisible = bVisible; 732 sal_uLong nPara = pParaList->GetAbsPos( pPara ); 733 pEditEngine->ShowParagraph( (sal_uInt16)nPara, bVisible ); 734 } 735 } 736 737 void Outliner::ImplCheckNumBulletItem( sal_uInt16 nPara ) 738 { 739 Paragraph* pPara = pParaList->GetParagraph( nPara ); 740 if (pPara) 741 pPara->aBulSize.Width() = -1; 742 } 743 744 void Outliner::ImplSetLevelDependendStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pLevelStyle ) 745 { 746 DBG_CHKTHIS(Outliner,0); 747 748 DBG_ASSERT( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ), "SetLevelDependendStyleSheet: Wrong Mode!" ); 749 750 SfxStyleSheet* pStyle = pLevelStyle; 751 if ( !pStyle ) 752 pStyle = GetStyleSheet( nPara ); 753 754 if ( pStyle ) 755 { 756 sal_Int16 nDepth = GetDepth( nPara ); 757 if( nDepth < 0 ) 758 nDepth = 0; 759 760 String aNewStyleSheetName( pStyle->GetName() ); 761 aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 ); 762 aNewStyleSheetName += String::CreateFromInt32( nDepth+1 ); 763 SfxStyleSheet* pNewStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( aNewStyleSheetName, pStyle->GetFamily() ); 764 DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" ); 765 if ( pNewStyle && ( pNewStyle != GetStyleSheet( nPara ) ) ) 766 { 767 SfxItemSet aOldAttrs( GetParaAttribs( nPara ) ); 768 SetStyleSheet( nPara, pNewStyle ); 769 if ( aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON ) 770 { 771 SfxItemSet aAttrs( GetParaAttribs( nPara ) ); 772 aAttrs.Put( aOldAttrs.Get( EE_PARA_NUMBULLET ) ); 773 SetParaAttribs( nPara, aAttrs ); 774 } 775 } 776 } 777 } 778 779 void Outliner::ImplInitDepth( sal_uInt16 nPara, sal_Int16 nDepth, sal_Bool bCreateUndo, sal_Bool bUndoAction ) 780 { 781 DBG_CHKTHIS(Outliner,0); 782 783 DBG_ASSERT( ( nDepth >= nMinDepth ) && ( nDepth <= nMaxDepth ), "ImplInitDepth - Depth is invalid!" ); 784 785 Paragraph* pPara = pParaList->GetParagraph( nPara ); 786 if (!pPara) 787 return; 788 sal_Int16 nOldDepth = pPara->GetDepth(); 789 pPara->SetDepth( nDepth ); 790 791 // Bei IsInUndo brauchen Attribute und Style nicht eingestellt werden, 792 // dort werden die alten Werte durch die EditEngine restauriert. 793 794 if( !IsInUndo() ) 795 { 796 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 797 pEditEngine->SetUpdateMode( sal_False ); 798 799 sal_Bool bUndo = bCreateUndo && IsUndoEnabled(); 800 if ( bUndo && bUndoAction ) 801 UndoActionStart( OLUNDO_DEPTH ); 802 803 SfxItemSet aAttrs( pEditEngine->GetParaAttribs( nPara ) ); 804 aAttrs.Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nDepth ) ); 805 pEditEngine->SetParaAttribs( nPara, aAttrs ); 806 ImplCheckNumBulletItem( nPara ); 807 ImplCalcBulletText( nPara, sal_False, sal_False ); 808 809 if ( bUndo ) 810 { 811 InsertUndo( new OutlinerUndoChangeDepth( this, nPara, nOldDepth, nDepth ) ); 812 if ( bUndoAction ) 813 UndoActionEnd( OLUNDO_DEPTH ); 814 } 815 816 pEditEngine->SetUpdateMode( bUpdate ); 817 } 818 } 819 820 void Outliner::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet ) 821 { 822 DBG_CHKTHIS(Outliner,0); 823 824 pEditEngine->SetParaAttribs( nPara, rSet ); 825 } 826 827 sal_Bool Outliner::Expand( Paragraph* pPara ) 828 { 829 DBG_CHKTHIS(Outliner,0); 830 831 if ( pParaList->HasHiddenChilds( pPara ) ) 832 { 833 OLUndoExpand* pUndo = 0; 834 sal_Bool bUndo = IsUndoEnabled() && !IsInUndo(); 835 if( bUndo ) 836 { 837 UndoActionStart( OLUNDO_EXPAND ); 838 pUndo = new OLUndoExpand( this, OLUNDO_EXPAND ); 839 pUndo->pParas = 0; 840 pUndo->nCount = (sal_uInt16)pParaList->GetAbsPos( pPara ); 841 } 842 pHdlParagraph = pPara; 843 bIsExpanding = sal_True; 844 pParaList->Expand( pPara ); 845 ExpandHdl(); 846 InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) ); 847 if( bUndo ) 848 { 849 InsertUndo( pUndo ); 850 UndoActionEnd( OLUNDO_EXPAND ); 851 } 852 return sal_True; 853 } 854 return sal_False; 855 } 856 857 858 sal_Bool Outliner::Collapse( Paragraph* pPara ) 859 { 860 DBG_CHKTHIS(Outliner,0); 861 if ( pParaList->HasVisibleChilds( pPara ) ) // expandiert 862 { 863 OLUndoExpand* pUndo = 0; 864 sal_Bool bUndo = sal_False; 865 866 if( !IsInUndo() && IsUndoEnabled() ) 867 bUndo = sal_True; 868 if( bUndo ) 869 { 870 UndoActionStart( OLUNDO_COLLAPSE ); 871 pUndo = new OLUndoExpand( this, OLUNDO_COLLAPSE ); 872 pUndo->pParas = 0; 873 pUndo->nCount = (sal_uInt16)pParaList->GetAbsPos( pPara ); 874 } 875 876 pHdlParagraph = pPara; 877 bIsExpanding = sal_False; 878 pParaList->Collapse( pPara ); 879 ExpandHdl(); 880 InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) ); 881 if( bUndo ) 882 { 883 InsertUndo( pUndo ); 884 UndoActionEnd( OLUNDO_COLLAPSE ); 885 } 886 return sal_True; 887 } 888 return sal_False; 889 } 890 891 892 Font Outliner::ImpCalcBulletFont( sal_uInt16 nPara ) const 893 { 894 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 895 DBG_ASSERT( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ), "ImpCalcBulletFont: Missing or BitmapBullet!" ); 896 897 Font aStdFont; //#107508# 898 if ( !pEditEngine->IsFlatMode() ) 899 { 900 ESelection aSel( nPara, 0, nPara, 0 ); 901 aStdFont = EditEngine::CreateFontFromItemSet( pEditEngine->GetAttribs( aSel ), GetScriptType( aSel ) ); 902 } 903 else 904 { 905 aStdFont = pEditEngine->GetStandardFont( nPara ); 906 } 907 908 Font aBulletFont; 909 if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) 910 { 911 aBulletFont = *pFmt->GetBulletFont(); 912 } 913 else 914 { 915 aBulletFont = aStdFont; 916 aBulletFont.SetUnderline( UNDERLINE_NONE ); 917 aBulletFont.SetOverline( UNDERLINE_NONE ); 918 aBulletFont.SetStrikeout( STRIKEOUT_NONE ); 919 aBulletFont.SetEmphasisMark( EMPHASISMARK_NONE ); 920 aBulletFont.SetRelief( RELIEF_NONE ); 921 } 922 923 // #107508# Use original scale... 924 sal_uInt16 nScale = /* pEditEngine->IsFlatMode() ? DEFAULT_SCALE : */ pFmt->GetBulletRelSize(); 925 sal_uLong nScaledLineHeight = aStdFont.GetSize().Height(); 926 nScaledLineHeight *= nScale*10; 927 nScaledLineHeight /= 1000; 928 929 aBulletFont.SetAlign( ALIGN_BOTTOM ); 930 aBulletFont.SetSize( Size( 0, nScaledLineHeight ) ); 931 sal_Bool bVertical = IsVertical(); 932 aBulletFont.SetVertical( bVertical ); 933 aBulletFont.SetOrientation( bVertical ? 2700 : 0 ); 934 935 Color aColor( COL_AUTO ); 936 if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EE_CNTRL_NOCOLORS ) ) 937 { 938 aColor = pFmt->GetBulletColor(); 939 } 940 941 if ( ( aColor == COL_AUTO ) || ( IsForceAutoColor() ) ) 942 aColor = pEditEngine->GetAutoColor(); 943 944 aBulletFont.SetColor( aColor ); 945 return aBulletFont; 946 } 947 948 void Outliner::PaintBullet( sal_uInt16 nPara, const Point& rStartPos, 949 const Point& rOrigin, short nOrientation, OutputDevice* pOutDev ) 950 { 951 DBG_CHKTHIS(Outliner,0); 952 953 bool bDrawBullet = false; 954 if (pEditEngine) 955 { 956 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); 957 bDrawBullet = rBulletState.GetValue() ? true : false; 958 } 959 960 if ( ImplHasBullet( nPara ) && bDrawBullet) 961 { 962 sal_Bool bVertical = IsVertical(); 963 964 sal_Bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara ); 965 966 Rectangle aBulletArea( ImpCalcBulletArea( nPara, sal_True, sal_False ) ); 967 968 Paragraph* pPara = pParaList->GetParagraph( nPara ); 969 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 970 if ( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) 971 { 972 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) 973 { 974 Font aBulletFont( ImpCalcBulletFont( nPara ) ); 975 // #2338# Use base line 976 sal_Bool bSymbol = pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL; 977 aBulletFont.SetAlign( bSymbol ? ALIGN_BOTTOM : ALIGN_BASELINE ); 978 Font aOldFont = pOutDev->GetFont(); 979 pOutDev->SetFont( aBulletFont ); 980 981 ParagraphInfos aParaInfos = pEditEngine->GetParagraphInfos( nPara ); 982 Point aTextPos; 983 if ( !bVertical ) 984 { 985 // aTextPos.Y() = rStartPos.Y() + aBulletArea.Bottom(); 986 aTextPos.Y() = rStartPos.Y() + ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent ); 987 if ( !bRightToLeftPara ) 988 aTextPos.X() = rStartPos.X() + aBulletArea.Left(); 989 else 990 aTextPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left(); 991 } 992 else 993 { 994 // aTextPos.X() = rStartPos.X() - aBulletArea.Bottom(); 995 aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent ); 996 aTextPos.Y() = rStartPos.Y() + aBulletArea.Left(); 997 } 998 999 if ( nOrientation ) 1000 { 1001 // Sowohl TopLeft als auch BottomLeft nicht ganz richtig, da 1002 // in EditEngine BaseLine... 1003 double nRealOrientation = nOrientation*F_PI1800; 1004 double nCos = cos( nRealOrientation ); 1005 double nSin = sin( nRealOrientation ); 1006 Point aRotatedPos; 1007 // Translation... 1008 aTextPos -= rOrigin; 1009 // Rotation... 1010 aRotatedPos.X()=(long) (nCos*aTextPos.X() + nSin*aTextPos.Y()); 1011 aRotatedPos.Y()=(long) - (nSin*aTextPos.X() - nCos*aTextPos.Y()); 1012 aTextPos = aRotatedPos; 1013 // Translation... 1014 aTextPos += rOrigin; 1015 Font aRotatedFont( aBulletFont ); 1016 aRotatedFont.SetOrientation( nOrientation ); 1017 pOutDev->SetFont( aRotatedFont ); 1018 } 1019 1020 // #105803# VCL will care for brackets and so on... 1021 sal_uLong nLayoutMode = pOutDev->GetLayoutMode(); 1022 nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG); 1023 if ( bRightToLeftPara ) 1024 nLayoutMode |= TEXT_LAYOUT_BIDI_RTL; 1025 pOutDev->SetLayoutMode( nLayoutMode ); 1026 1027 if(bStrippingPortions) 1028 { 1029 const Font aSvxFont(pOutDev->GetFont()); 1030 sal_Int32* pBuf = new sal_Int32[ pPara->GetText().Len() ]; 1031 pOutDev->GetTextArray( pPara->GetText(), pBuf ); 1032 1033 if(bSymbol) 1034 { 1035 // aTextPos is Bottom, go to Baseline 1036 FontMetric aMetric(pOutDev->GetFontMetric()); 1037 aTextPos.Y() -= aMetric.GetDescent(); 1038 } 1039 1040 DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().Len(), pBuf, 1041 aSvxFont, nPara, 0xFFFF, 0xFF, 0, 0, false, false, true, 0, Color(), Color()); 1042 1043 delete[] pBuf; 1044 } 1045 else 1046 { 1047 pOutDev->DrawText( aTextPos, pPara->GetText() ); 1048 } 1049 1050 pOutDev->SetFont( aOldFont ); 1051 } 1052 else 1053 { 1054 if ( pFmt->GetBrush()->GetGraphicObject() ) 1055 { 1056 Point aBulletPos; 1057 if ( !bVertical ) 1058 { 1059 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Top(); 1060 if ( !bRightToLeftPara ) 1061 aBulletPos.X() = rStartPos.X() + aBulletArea.Left(); 1062 else 1063 aBulletPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right(); 1064 } 1065 else 1066 { 1067 aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom(); 1068 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left(); 1069 } 1070 1071 if(bStrippingPortions) 1072 { 1073 if(aDrawBulletHdl.IsSet()) 1074 { 1075 // call something analog to aDrawPortionHdl (if set) and feed it something 1076 // analog to DrawPortionInfo... 1077 // created aDrawBulletHdl, Set/GetDrawBulletHdl. 1078 // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx 1079 DrawBulletInfo aDrawBulletInfo( 1080 *pFmt->GetBrush()->GetGraphicObject(), 1081 aBulletPos, 1082 pPara->aBulSize); 1083 1084 aDrawBulletHdl.Call(&aDrawBulletInfo); 1085 } 1086 } 1087 else 1088 { 1089 // MT: Remove CAST when KA made the Draw-Method const 1090 ((GraphicObject*)pFmt->GetBrush()->GetGraphicObject())->Draw( pOutDev, aBulletPos, pPara->aBulSize ); 1091 } 1092 } 1093 } 1094 } 1095 1096 // Bei zusammengeklappten Absaetzen einen Strich vor den Text malen. 1097 if( pParaList->HasChilds(pPara) && !pParaList->HasVisibleChilds(pPara) && 1098 !bStrippingPortions && !nOrientation ) 1099 { 1100 long nWidth = pOutDev->PixelToLogic( Size( 10, 0 ) ).Width(); 1101 1102 Point aStartPos, aEndPos; 1103 if ( !bVertical ) 1104 { 1105 aStartPos.Y() = rStartPos.Y() + aBulletArea.Bottom(); 1106 if ( !bRightToLeftPara ) 1107 aStartPos.X() = rStartPos.X() + aBulletArea.Right(); 1108 else 1109 aStartPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left(); 1110 aEndPos = aStartPos; 1111 aEndPos.X() += nWidth; 1112 } 1113 else 1114 { 1115 aStartPos.X() = rStartPos.X() - aBulletArea.Bottom(); 1116 aStartPos.Y() = rStartPos.Y() + aBulletArea.Right(); 1117 aEndPos = aStartPos; 1118 aEndPos.Y() += nWidth; 1119 } 1120 1121 const Color& rOldLineColor = pOutDev->GetLineColor(); 1122 pOutDev->SetLineColor( Color( COL_BLACK ) ); 1123 pOutDev->DrawLine( aStartPos, aEndPos ); 1124 pOutDev->SetLineColor( rOldLineColor ); 1125 } 1126 } 1127 } 1128 1129 void Outliner::InvalidateBullet( Paragraph* /*pPara*/, sal_uLong nPara ) 1130 { 1131 DBG_CHKTHIS(Outliner,0); 1132 1133 long nLineHeight = (long)pEditEngine->GetLineHeight((sal_uInt16)nPara ); 1134 OutlinerView* pView = aViewList.First(); 1135 while( pView ) 1136 { 1137 Point aPos( pView->pEditView->GetWindowPosTopLeft((sal_uInt16)nPara ) ); 1138 Rectangle aRect( pView->GetOutputArea() ); 1139 aRect.Right() = aPos.X(); 1140 aRect.Top() = aPos.Y(); 1141 aRect.Bottom() = aPos.Y(); 1142 aRect.Bottom() += nLineHeight; 1143 1144 pView->GetWindow()->Invalidate( aRect ); 1145 pView = aViewList.Next(); 1146 } 1147 } 1148 1149 sal_uLong Outliner::Read( SvStream& rInput, const String& rBaseURL, sal_uInt16 eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) 1150 { 1151 DBG_CHKTHIS(Outliner,0); 1152 1153 sal_Bool bOldUndo = pEditEngine->IsUndoEnabled(); 1154 EnableUndo( sal_False ); 1155 1156 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 1157 pEditEngine->SetUpdateMode( sal_False ); 1158 1159 Clear(); 1160 1161 ImplBlockInsertionCallbacks( sal_True ); 1162 sal_uLong nRet = pEditEngine->Read( rInput, rBaseURL, (EETextFormat)eFormat, pHTTPHeaderAttrs ); 1163 1164 bFirstParaIsEmpty = sal_False; 1165 1166 sal_uInt16 nParas = pEditEngine->GetParagraphCount(); 1167 pParaList->Clear( sal_True ); 1168 sal_uInt16 n; 1169 for ( n = 0; n < nParas; n++ ) 1170 { 1171 Paragraph* pPara = new Paragraph( 0 ); 1172 pParaList->Insert( pPara, LIST_APPEND ); 1173 1174 if ( eFormat == EE_FORMAT_BIN ) 1175 { 1176 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( n ); 1177 const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL ); 1178 sal_Int16 nDepth = rLevel.GetValue(); 1179 ImplInitDepth( n, nDepth, sal_False ); 1180 } 1181 } 1182 1183 if ( eFormat != EE_FORMAT_BIN ) 1184 { 1185 ImpFilterIndents( 0, nParas-1 ); 1186 } 1187 1188 ImplBlockInsertionCallbacks( sal_False ); 1189 pEditEngine->SetUpdateMode( bUpdate ); 1190 EnableUndo( bOldUndo ); 1191 1192 return nRet; 1193 } 1194 1195 1196 void Outliner::ImpFilterIndents( sal_uLong nFirstPara, sal_uLong nLastPara ) 1197 { 1198 DBG_CHKTHIS(Outliner,0); 1199 1200 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 1201 pEditEngine->SetUpdateMode( sal_False ); 1202 1203 Paragraph* pLastConverted = NULL; 1204 for( sal_uLong nPara = nFirstPara; nPara <= nLastPara; nPara++ ) 1205 { 1206 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1207 if (pPara) 1208 { 1209 if( ImpConvertEdtToOut( nPara ) ) 1210 { 1211 pLastConverted = pPara; 1212 } 1213 else if ( pLastConverted ) 1214 { 1215 // Normale Absaetze unter der Ueberschrift anordnen... 1216 pPara->SetDepth( pLastConverted->GetDepth() ); 1217 } 1218 1219 ImplInitDepth( (sal_uInt16)nPara, pPara->GetDepth(), sal_False ); 1220 } 1221 } 1222 1223 pEditEngine->SetUpdateMode( bUpdate ); 1224 } 1225 1226 ::svl::IUndoManager& Outliner::GetUndoManager() 1227 { 1228 DBG_CHKTHIS(Outliner,0); 1229 return pEditEngine->GetUndoManager(); 1230 } 1231 1232 ::svl::IUndoManager* Outliner::SetUndoManager(::svl::IUndoManager* pNew) 1233 { 1234 DBG_CHKTHIS(Outliner,0); 1235 return pEditEngine->SetUndoManager(pNew); 1236 } 1237 1238 void Outliner::ImpTextPasted( sal_uLong nStartPara, sal_uInt16 nCount ) 1239 { 1240 DBG_CHKTHIS(Outliner,0); 1241 1242 sal_Bool bUpdate = pEditEngine->GetUpdateMode(); 1243 pEditEngine->SetUpdateMode( sal_False ); 1244 1245 const sal_uLong nStart = nStartPara; 1246 1247 Paragraph* pPara = pParaList->GetParagraph( nStartPara ); 1248 // Paragraph* pLastConverted = NULL; 1249 // bool bFirst = true; 1250 1251 while( nCount && pPara ) 1252 { 1253 if( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) 1254 { 1255 nDepthChangedHdlPrevDepth = pPara->GetDepth(); 1256 mnDepthChangeHdlPrevFlags = pPara->nFlags; 1257 1258 ImpConvertEdtToOut( nStartPara ); 1259 1260 pHdlParagraph = pPara; 1261 1262 if( nStartPara == nStart ) 1263 { 1264 // the existing paragraph has changed depth or flags 1265 if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != mnDepthChangeHdlPrevFlags) ) 1266 DepthChangedHdl(); 1267 } 1268 } 1269 else // EditEngine-Modus 1270 { 1271 sal_Int16 nDepth = -1; 1272 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (sal_uInt16)nStartPara ); 1273 if ( rAttrs.GetItemState( EE_PARA_OUTLLEVEL ) == SFX_ITEM_ON ) 1274 { 1275 const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL ); 1276 nDepth = rLevel.GetValue(); 1277 } 1278 if ( nDepth != GetDepth( nStartPara ) ) 1279 ImplInitDepth( (sal_uInt16)nStartPara, nDepth, sal_False ); 1280 } 1281 1282 nCount--; 1283 nStartPara++; 1284 pPara = pParaList->GetParagraph( nStartPara ); 1285 } 1286 1287 pEditEngine->SetUpdateMode( bUpdate ); 1288 1289 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed"); 1290 } 1291 1292 long Outliner::IndentingPagesHdl( OutlinerView* pView ) 1293 { 1294 DBG_CHKTHIS(Outliner,0); 1295 if( !aIndentingPagesHdl.IsSet() ) 1296 return 1; 1297 return aIndentingPagesHdl.Call( pView ); 1298 } 1299 1300 sal_Bool Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView ) 1301 { 1302 DBG_CHKTHIS(Outliner,0); 1303 // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages 1304 // schon eingestellt sein 1305 1306 // Wenn der erste Absatz auf Ebene 0 liegt darf er auf keinen Fall 1307 // eingerueckt werden, evtl folgen aber weitere auf Ebene 0. 1308 if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) ) 1309 { 1310 if ( nDepthChangedHdlPrevDepth == 1 ) // ist die einzige Seite 1311 return sal_False; 1312 else 1313 pCurView->ImpCalcSelectedPages( sal_False ); // ohne die erste 1314 } 1315 return (sal_Bool)IndentingPagesHdl( pCurView ); 1316 } 1317 1318 1319 sal_Bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView ) 1320 { 1321 DBG_CHKTHIS(Outliner,0); 1322 // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages 1323 // schon eingestellt sein 1324 return (sal_Bool)RemovingPagesHdl( pCurView ); 1325 } 1326 1327 Outliner::Outliner( SfxItemPool* pPool, sal_uInt16 nMode ) 1328 : nMinDepth( -1 ) 1329 { 1330 DBG_CTOR( Outliner, 0 ); 1331 1332 bStrippingPortions = sal_False; 1333 bPasting = sal_False; 1334 1335 nFirstPage = 1; 1336 bBlockInsCallback = sal_False; 1337 1338 nMaxDepth = 9; 1339 1340 pParaList = new ParagraphList; 1341 pParaList->SetVisibleStateChangedHdl( LINK( this, Outliner, ParaVisibleStateChangedHdl ) ); 1342 Paragraph* pPara = new Paragraph( 0 ); 1343 pParaList->Insert( pPara, LIST_APPEND ); 1344 bFirstParaIsEmpty = sal_True; 1345 1346 pEditEngine = new OutlinerEditEng( this, pPool ); 1347 pEditEngine->SetBeginMovingParagraphsHdl( LINK( this, Outliner, BeginMovingParagraphsHdl ) ); 1348 pEditEngine->SetEndMovingParagraphsHdl( LINK( this, Outliner, EndMovingParagraphsHdl ) ); 1349 pEditEngine->SetBeginPasteOrDropHdl( LINK( this, Outliner, BeginPasteOrDropHdl ) ); 1350 pEditEngine->SetEndPasteOrDropHdl( LINK( this, Outliner, EndPasteOrDropHdl ) ); 1351 1352 Init( nMode ); 1353 } 1354 1355 Outliner::~Outliner() 1356 { 1357 DBG_DTOR(Outliner,0); 1358 1359 pParaList->Clear( sal_True ); 1360 delete pParaList; 1361 delete pEditEngine; 1362 } 1363 1364 sal_uLong Outliner::InsertView( OutlinerView* pView, sal_uLong nIndex ) 1365 { 1366 DBG_CHKTHIS(Outliner,0); 1367 1368 aViewList.Insert( pView, nIndex ); 1369 pEditEngine->InsertView( pView->pEditView, (sal_uInt16)nIndex ); 1370 return aViewList.GetPos( pView ); 1371 } 1372 1373 OutlinerView* Outliner::RemoveView( OutlinerView* pView ) 1374 { 1375 DBG_CHKTHIS(Outliner,0); 1376 1377 sal_uLong nPos = aViewList.GetPos( pView ); 1378 if ( nPos != LIST_ENTRY_NOTFOUND ) 1379 { 1380 pView->pEditView->HideCursor(); // HACK wg. BugId 10006 1381 pEditEngine->RemoveView( pView->pEditView ); 1382 aViewList.Remove( nPos ); 1383 } 1384 return NULL; // MT: return ueberfluessig 1385 } 1386 1387 OutlinerView* Outliner::RemoveView( sal_uLong nIndex ) 1388 { 1389 DBG_CHKTHIS(Outliner,0); 1390 1391 EditView* pEditView = pEditEngine->GetView( (sal_uInt16)nIndex ); 1392 pEditView->HideCursor(); // HACK wg. BugId 10006 1393 1394 pEditEngine->RemoveView( (sal_uInt16)nIndex ); 1395 aViewList.Remove( nIndex ); 1396 return NULL; // MT: return ueberfluessig 1397 } 1398 1399 1400 OutlinerView* Outliner::GetView( sal_uLong nIndex ) const 1401 { 1402 DBG_CHKTHIS(Outliner,0); 1403 return aViewList.GetObject( nIndex ); 1404 } 1405 1406 sal_uLong Outliner::GetViewCount() const 1407 { 1408 DBG_CHKTHIS(Outliner,0); 1409 return aViewList.Count(); 1410 } 1411 1412 void Outliner::ParagraphInsertedHdl() 1413 { 1414 DBG_CHKTHIS(Outliner,0); 1415 if( !IsInUndo() ) 1416 aParaInsertedHdl.Call( this ); 1417 } 1418 1419 1420 void Outliner::ParagraphRemovingHdl() 1421 { 1422 DBG_CHKTHIS(Outliner,0); 1423 if( !IsInUndo() ) 1424 aParaRemovingHdl.Call( this ); 1425 } 1426 1427 1428 void Outliner::DepthChangedHdl() 1429 { 1430 DBG_CHKTHIS(Outliner,0); 1431 if( !IsInUndo() ) 1432 aDepthChangedHdl.Call( this ); 1433 } 1434 1435 1436 sal_uLong Outliner::GetAbsPos( Paragraph* pPara ) 1437 { 1438 DBG_CHKTHIS(Outliner,0); 1439 DBG_ASSERT(pPara,"GetAbsPos:No Para"); 1440 return pParaList->GetAbsPos( pPara ); 1441 } 1442 1443 sal_uLong Outliner::GetParagraphCount() const 1444 { 1445 DBG_CHKTHIS(Outliner,0); 1446 return pParaList->GetParagraphCount(); 1447 } 1448 1449 Paragraph* Outliner::GetParagraph( sal_uLong nAbsPos ) const 1450 { 1451 DBG_CHKTHIS(Outliner,0); 1452 return pParaList->GetParagraph( nAbsPos ); 1453 } 1454 1455 sal_Bool Outliner::HasChilds( Paragraph* pParagraph ) const 1456 { 1457 DBG_CHKTHIS(Outliner,0); 1458 return pParaList->HasChilds( pParagraph ); 1459 } 1460 1461 sal_Bool Outliner::ImplHasBullet( sal_uInt16 nPara ) const 1462 { 1463 return GetNumberFormat(nPara) != 0; 1464 } 1465 1466 const SvxNumberFormat* Outliner::GetNumberFormat( sal_uInt16 nPara ) const 1467 { 1468 const SvxNumberFormat* pFmt = NULL; 1469 1470 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1471 if (pPara == NULL) 1472 return NULL; 1473 1474 sal_Int16 nDepth = pPara? pPara->GetDepth() : -1; 1475 1476 if( nDepth >= 0 ) 1477 { 1478 const SvxNumBulletItem& rNumBullet = (const SvxNumBulletItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET ); 1479 if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth ) 1480 pFmt = rNumBullet.GetNumRule()->Get( nDepth ); 1481 } 1482 1483 return pFmt; 1484 } 1485 1486 Size Outliner::ImplGetBulletSize( sal_uInt16 nPara ) 1487 { 1488 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1489 if (!pPara) 1490 return Size(); 1491 1492 if( pPara->aBulSize.Width() == -1 ) 1493 { 1494 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1495 DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" ); 1496 1497 if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE ) 1498 { 1499 pPara->aBulSize = Size( 0, 0 ); 1500 } 1501 else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) 1502 { 1503 String aBulletText = ImplGetBulletText( nPara ); 1504 OutputDevice* pRefDev = pEditEngine->GetRefDevice(); 1505 Font aBulletFont( ImpCalcBulletFont( nPara ) ); 1506 Font aRefFont( pRefDev->GetFont()); 1507 pRefDev->SetFont( aBulletFont ); 1508 pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText ); 1509 pPara->aBulSize.Height() = pRefDev->GetTextHeight(); 1510 pRefDev->SetFont( aRefFont ); 1511 } 1512 else 1513 { 1514 pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() ); 1515 } 1516 } 1517 1518 return pPara->aBulSize; 1519 } 1520 1521 void Outliner::ImplCheckParagraphs( sal_uInt16 nStart, sal_uInt16 nEnd ) 1522 { 1523 DBG_CHKTHIS( Outliner, 0 ); 1524 1525 // --> OD 2009-03-10 #i100014# 1526 // assure that the following for-loop does not loop forever 1527 for ( sal_uInt16 n = nStart; n < nEnd; n++ ) 1528 // <-- 1529 { 1530 Paragraph* pPara = pParaList->GetParagraph( n ); 1531 if (pPara) 1532 { 1533 pPara->Invalidate(); 1534 ImplCalcBulletText( n, sal_False, sal_False ); 1535 } 1536 } 1537 } 1538 1539 void Outliner::SetRefDevice( OutputDevice* pRefDev ) 1540 { 1541 DBG_CHKTHIS(Outliner,0); 1542 pEditEngine->SetRefDevice( pRefDev ); 1543 for ( sal_uInt16 n = (sal_uInt16) pParaList->GetParagraphCount(); n; ) 1544 { 1545 Paragraph* pPara = pParaList->GetParagraph( --n ); 1546 pPara->Invalidate(); 1547 } 1548 } 1549 1550 void Outliner::ParaAttribsChanged( sal_uInt16 nPara ) 1551 { 1552 DBG_CHKTHIS(Outliner,0); 1553 1554 // Der Outliner hat kein eigenes Undo, wenn Absaetz getrennt/verschmolzen werden. 1555 // Beim ParagraphInserted ist das Attribut EE_PARA_OUTLLEVEL 1556 // ggf. noch nicht eingestellt, dies wird aber benoetigt um die Tiefe 1557 // des Absatzes zu bestimmen. 1558 1559 if( pEditEngine->IsInUndo() ) 1560 { 1561 if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() ) 1562 { 1563 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1564 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); 1565 if ( pPara && pPara->GetDepth() != rLevel.GetValue() ) 1566 { 1567 pPara->SetDepth( rLevel.GetValue() ); 1568 ImplCalcBulletText( nPara, sal_True, sal_True ); 1569 } 1570 } 1571 } 1572 } 1573 1574 void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle ) 1575 { 1576 DBG_CHKTHIS(Outliner,0); 1577 1578 // Die EditEngine ruft StyleSheetChanged auch fuer abgeleitete Styles. 1579 // MT: Hier wurde frueher alle Absaetze durch ein ImpRecalcParaAttribs 1580 // gejagt, die die besagte Vorlage haben, warum? 1581 // => Eigentlich kann sich nur die Bullet-Repraesentation aendern... 1582 1583 sal_uInt16 nParas = (sal_uInt16)pParaList->GetParagraphCount(); 1584 for( sal_uInt16 nPara = 0; nPara < nParas; nPara++ ) 1585 { 1586 if ( pEditEngine->GetStyleSheet( nPara ) == pStyle ) 1587 { 1588 ImplCheckNumBulletItem( nPara ); 1589 ImplCalcBulletText( nPara, sal_False, sal_False ); 1590 // #97333# EditEngine formats changed paragraphs before calling this method, 1591 // so they are not reformatted now and use wrong bullet indent 1592 pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); 1593 } 1594 } 1595 } 1596 1597 Rectangle Outliner::ImpCalcBulletArea( sal_uInt16 nPara, sal_Bool bAdjust, sal_Bool bReturnPaperPos ) 1598 { 1599 // Bullet-Bereich innerhalb des Absatzes... 1600 Rectangle aBulletArea; 1601 1602 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1603 if ( pFmt ) 1604 { 1605 Point aTopLeft; 1606 Size aBulletSize( ImplGetBulletSize( nPara ) ); 1607 1608 sal_Bool bOutlineMode = ( pEditEngine->GetControlWord() & EE_CNTRL_OUTLINER ) != 0; 1609 1610 // the ODF attribut text:space-before which holds the spacing to add to the left of the label 1611 const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset(); 1612 1613 const SvxLRSpaceItem& rLR = (const SvxLRSpaceItem&) pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); 1614 aTopLeft.X() = rLR.GetTxtLeft() + rLR.GetTxtFirstLineOfst() + nSpaceBefore; 1615 1616 long nBulletWidth = Max( (long) -rLR.GetTxtFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) ); 1617 if ( nBulletWidth < aBulletSize.Width() ) // Bullet macht sich Platz 1618 nBulletWidth = aBulletSize.Width(); 1619 1620 if ( bAdjust && !bOutlineMode ) 1621 { 1622 // Bei zentriert/rechtsbuendig anpassen 1623 const SvxAdjustItem& rItem = (const SvxAdjustItem&)pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST ); 1624 if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) || 1625 ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) ) 1626 { 1627 aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth; 1628 } 1629 } 1630 1631 // Vertikal: 1632 ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara ); 1633 if ( aInfos.bValid ) 1634 { 1635 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // #91076# nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine 1636 aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight 1637 + aInfos.nFirstLineTextHeight / 2 1638 - aBulletSize.Height() / 2; 1639 // ggf. lieber auf der Baseline ausgeben... 1640 if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) ) 1641 { 1642 Font aBulletFont( ImpCalcBulletFont( nPara ) ); 1643 if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) 1644 { 1645 OutputDevice* pRefDev = pEditEngine->GetRefDevice(); 1646 Font aOldFont = pRefDev->GetFont(); 1647 pRefDev->SetFont( aBulletFont ); 1648 FontMetric aMetric( pRefDev->GetFontMetric() ); 1649 // Leading der ersten Zeile... 1650 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent; 1651 aTopLeft.Y() -= aMetric.GetAscent(); 1652 pRefDev->SetFont( aOldFont ); 1653 } 1654 } 1655 } 1656 1657 // Horizontal: 1658 if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT ) 1659 { 1660 aTopLeft.X() += nBulletWidth - aBulletSize.Width(); 1661 } 1662 else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER ) 1663 { 1664 aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2; 1665 } 1666 1667 if ( aTopLeft.X() < 0 ) // dann draengeln 1668 aTopLeft.X() = 0; 1669 1670 aBulletArea = Rectangle( aTopLeft, aBulletSize ); 1671 } 1672 if ( bReturnPaperPos ) 1673 { 1674 Size aBulletSize( aBulletArea.GetSize() ); 1675 Point aBulletDocPos( aBulletArea.TopLeft() ); 1676 aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y(); 1677 Point aBulletPos( aBulletDocPos ); 1678 1679 if ( IsVertical() ) 1680 { 1681 aBulletPos.Y() = aBulletDocPos.X(); 1682 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y(); 1683 // Rotate: 1684 aBulletPos.X() -= aBulletSize.Height(); 1685 Size aSz( aBulletSize ); 1686 aBulletSize.Width() = aSz.Height(); 1687 aBulletSize.Height() = aSz.Width(); 1688 } 1689 else if ( pEditEngine->IsRightToLeft( nPara ) ) 1690 { 1691 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width(); 1692 } 1693 1694 aBulletArea = Rectangle( aBulletPos, aBulletSize ); 1695 } 1696 return aBulletArea; 1697 } 1698 1699 void Outliner::ExpandHdl() 1700 { 1701 DBG_CHKTHIS(Outliner,0); 1702 aExpandHdl.Call( this ); 1703 } 1704 1705 EBulletInfo Outliner::GetBulletInfo( sal_uInt16 nPara ) 1706 { 1707 EBulletInfo aInfo; 1708 1709 aInfo.nParagraph = nPara; 1710 aInfo.bVisible = ImplHasBullet( nPara ); 1711 1712 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1713 aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0; 1714 1715 if( pFmt ) 1716 { 1717 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) 1718 { 1719 aInfo.aText = ImplGetBulletText( nPara ); 1720 1721 if( pFmt->GetBulletFont() ) 1722 aInfo.aFont = *pFmt->GetBulletFont(); 1723 } 1724 else if ( pFmt->GetBrush()->GetGraphicObject() ) 1725 { 1726 aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic(); 1727 } 1728 } 1729 1730 if ( aInfo.bVisible ) 1731 { 1732 aInfo.aBounds = ImpCalcBulletArea( nPara, sal_True, sal_True ); 1733 } 1734 1735 return aInfo; 1736 } 1737 1738 XubString Outliner::GetText( Paragraph* pParagraph, sal_uLong nCount ) const 1739 { 1740 DBG_CHKTHIS(Outliner,0); 1741 1742 XubString aText; 1743 sal_uInt16 nStartPara = (sal_uInt16) pParaList->GetAbsPos( pParagraph ); 1744 for ( sal_uInt16 n = 0; n < nCount; n++ ) 1745 { 1746 aText += pEditEngine->GetText( nStartPara + n ); 1747 if ( (n+1) < (sal_uInt16)nCount ) 1748 aText += '\n'; 1749 } 1750 return aText; 1751 } 1752 1753 void Outliner::Remove( Paragraph* pPara, sal_uLong nParaCount ) 1754 { 1755 DBG_CHKTHIS(Outliner,0); 1756 1757 sal_uLong nPos = pParaList->GetAbsPos( pPara ); 1758 if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) ) 1759 { 1760 Clear(); 1761 } 1762 else 1763 { 1764 for( sal_uInt16 n = 0; n < (sal_uInt16)nParaCount; n++ ) 1765 pEditEngine->RemoveParagraph( (sal_uInt16) nPos ); 1766 } 1767 } 1768 1769 void Outliner::StripPortions() 1770 { 1771 DBG_CHKTHIS(Outliner,0); 1772 bStrippingPortions = sal_True; 1773 pEditEngine->StripPortions(); 1774 bStrippingPortions = sal_False; 1775 } 1776 1777 // #101498# 1778 void Outliner::DrawingText( const Point& rStartPos, const XubString& rText, sal_uInt16 nTextStart, sal_uInt16 nTextLen, const sal_Int32* pDXArray,const SvxFont& rFont, 1779 sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt8 nRightToLeft, 1780 const EEngineData::WrongSpellVector* pWrongSpellVector, 1781 const SvxFieldData* pFieldData, 1782 bool bEndOfLine, 1783 bool bEndOfParagraph, 1784 bool bEndOfBullet, 1785 const ::com::sun::star::lang::Locale* pLocale, 1786 const Color& rOverlineColor, 1787 const Color& rTextLineColor) 1788 { 1789 DBG_CHKTHIS(Outliner,0); 1790 1791 if(aDrawPortionHdl.IsSet()) 1792 { 1793 // #101498# 1794 DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector, 1795 pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, bEndOfLine, bEndOfParagraph, bEndOfBullet); 1796 1797 aDrawPortionHdl.Call( &aInfo ); 1798 } 1799 } 1800 1801 long Outliner::RemovingPagesHdl( OutlinerView* pView ) 1802 { 1803 DBG_CHKTHIS(Outliner,0); 1804 return aRemovingPagesHdl.IsSet() ? aRemovingPagesHdl.Call( pView ) : sal_True; 1805 } 1806 1807 sal_Bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, sal_uInt16 _nFirstPage, sal_uInt16 nPages ) 1808 { 1809 DBG_CHKTHIS(Outliner,0); 1810 1811 nDepthChangedHdlPrevDepth = nPages; 1812 mnFirstSelPage = _nFirstPage; 1813 pHdlParagraph = 0; 1814 return (sal_Bool)RemovingPagesHdl( pCurView ); 1815 } 1816 1817 SfxItemSet Outliner::GetParaAttribs( sal_uInt16 nPara ) 1818 { 1819 DBG_CHKTHIS(Outliner,0); 1820 return pEditEngine->GetParaAttribs( nPara ); 1821 } 1822 1823 IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara ) 1824 { 1825 DBG_CHKTHIS(Outliner,0); 1826 1827 sal_uLong nPara = pParaList->GetAbsPos( pPara ); 1828 pEditEngine->ShowParagraph( (sal_uInt16)nPara, pPara->IsVisible() ); 1829 1830 return 0; 1831 } 1832 1833 IMPL_LINK( Outliner, BeginMovingParagraphsHdl, MoveParagraphsInfo*, EMPTYARG ) 1834 { 1835 DBG_CHKTHIS(Outliner,0); 1836 1837 if( !IsInUndo() ) 1838 GetBeginMovingHdl().Call( this ); 1839 1840 return 0; 1841 } 1842 1843 IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos ) 1844 { 1845 UndoActionStart( EDITUNDO_DRAGANDDROP ); 1846 maBeginPasteOrDropHdl.Call(pInfos); 1847 return 0; 1848 } 1849 1850 IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos ) 1851 { 1852 bPasting = sal_False; 1853 ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); 1854 maEndPasteOrDropHdl.Call( pInfos ); 1855 UndoActionEnd( EDITUNDO_DRAGANDDROP ); 1856 return 0; 1857 } 1858 1859 IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos ) 1860 { 1861 DBG_CHKTHIS(Outliner,0); 1862 1863 pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); 1864 sal_uInt16 nChangesStart = Min( pInfos->nStartPara, pInfos->nDestPara ); 1865 sal_uInt16 nParas = (sal_uInt16)pParaList->GetParagraphCount(); 1866 for ( sal_uInt16 n = nChangesStart; n < nParas; n++ ) 1867 ImplCalcBulletText( n, sal_False, sal_False ); 1868 1869 if( !IsInUndo() ) 1870 aEndMovingHdl.Call( this ); 1871 1872 return 0; 1873 } 1874 1875 static bool isSameNumbering( const SvxNumberFormat& rN1, const SvxNumberFormat& rN2 ) 1876 { 1877 if( rN1.GetNumberingType() != rN2.GetNumberingType() ) 1878 return false; 1879 1880 if( rN1.GetNumStr(1) != rN2.GetNumStr(1) ) 1881 return false; 1882 1883 if( (rN1.GetPrefix() != rN2.GetPrefix()) || (rN1.GetSuffix() != rN2.GetSuffix()) ) 1884 return false; 1885 1886 return true; 1887 } 1888 1889 sal_uInt16 Outliner::ImplGetNumbering( sal_uInt16 nPara, const SvxNumberFormat* pParaFmt ) 1890 { 1891 sal_uInt16 nNumber = pParaFmt->GetStart() - 1; 1892 1893 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1894 const sal_Int16 nParaDepth = pPara->GetDepth(); 1895 1896 do 1897 { 1898 pPara = pParaList->GetParagraph( nPara ); 1899 const sal_Int16 nDepth = pPara->GetDepth(); 1900 1901 // ignore paragraphs that are below our paragraph or have no numbering 1902 if( (nDepth > nParaDepth) || (nDepth == -1) ) 1903 continue; 1904 1905 // stop on paragraphs that are above our paragraph 1906 if( nDepth < nParaDepth ) 1907 break; 1908 1909 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1910 1911 if( pFmt == 0 ) 1912 continue; // ignore paragraphs without bullets 1913 1914 // check if numbering is the same 1915 if( !isSameNumbering( *pFmt, *pParaFmt ) ) 1916 break; 1917 1918 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); 1919 1920 if( rBulletState.GetValue() ) 1921 nNumber += 1; 1922 1923 // same depth, same number format, check for restart 1924 const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue(); 1925 if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() ) 1926 { 1927 if( nNumberingStartValue != -1 ) 1928 nNumber += nNumberingStartValue - 1; 1929 break; 1930 } 1931 } 1932 while( nPara-- ); 1933 1934 return nNumber; 1935 } 1936 1937 void Outliner::ImplCalcBulletText( sal_uInt16 nPara, sal_Bool bRecalcLevel, sal_Bool bRecalcChilds ) 1938 { 1939 DBG_CHKTHIS(Outliner,0); 1940 1941 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1942 sal_uInt16 nRelPos = 0xFFFF; 1943 1944 while ( pPara ) 1945 { 1946 XubString aBulletText; 1947 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1948 if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) ) 1949 { 1950 aBulletText += pFmt->GetPrefix(); 1951 if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) 1952 { 1953 aBulletText += pFmt->GetBulletChar(); 1954 } 1955 else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) 1956 { 1957 aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) ); 1958 } 1959 aBulletText += pFmt->GetSuffix(); 1960 } 1961 1962 if( aBulletText != pPara->GetText() ) 1963 pPara->SetText( aBulletText ); 1964 1965 pPara->nFlags &= (~PARAFLAG_SETBULLETTEXT); 1966 1967 if ( bRecalcLevel ) 1968 { 1969 if ( nRelPos != 0xFFFF ) 1970 nRelPos++; 1971 1972 sal_Int16 nDepth = pPara->GetDepth(); 1973 pPara = pParaList->GetParagraph( ++nPara ); 1974 if ( !bRecalcChilds ) 1975 { 1976 while ( pPara && ( pPara->GetDepth() > nDepth ) ) 1977 pPara = pParaList->GetParagraph( ++nPara ); 1978 } 1979 1980 if ( pPara && ( pPara->GetDepth() < nDepth ) ) 1981 pPara = NULL; 1982 } 1983 else 1984 { 1985 pPara = NULL; 1986 } 1987 } 1988 } 1989 1990 void Outliner::Clear() 1991 { 1992 DBG_CHKTHIS(Outliner,0); 1993 1994 if( !bFirstParaIsEmpty ) 1995 { 1996 ImplBlockInsertionCallbacks( sal_True ); 1997 pEditEngine->Clear(); 1998 pParaList->Clear( sal_True ); 1999 pParaList->Insert( new Paragraph( nMinDepth ), LIST_APPEND ); 2000 bFirstParaIsEmpty = sal_True; 2001 ImplBlockInsertionCallbacks( sal_False ); 2002 } 2003 else 2004 { 2005 Paragraph* pPara = pParaList->GetParagraph( 0 ); 2006 if(pPara) 2007 pPara->SetDepth( nMinDepth ); 2008 } 2009 } 2010 2011 void Outliner::SetFlatMode( sal_Bool bFlat ) 2012 { 2013 DBG_CHKTHIS(Outliner,0); 2014 2015 if( bFlat != pEditEngine->IsFlatMode() ) 2016 { 2017 for ( sal_uInt16 nPara = (sal_uInt16)pParaList->GetParagraphCount(); nPara; ) 2018 pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1; 2019 2020 pEditEngine->SetFlatMode( bFlat ); 2021 } 2022 } 2023 2024 String Outliner::ImplGetBulletText( sal_uInt16 nPara ) 2025 { 2026 String aRes; 2027 Paragraph* pPara = pParaList->GetParagraph( nPara ); 2028 if (pPara) 2029 { 2030 // MT: Optimierung mal wieder aktivieren... 2031 // if( pPara->nFlags & PARAFLAG_SETBULLETTEXT ) 2032 ImplCalcBulletText( nPara, sal_False, sal_False ); 2033 aRes = pPara->GetText(); 2034 } 2035 return aRes; 2036 } 2037 2038 // this is needed for StarOffice Api 2039 void Outliner::SetLevelDependendStyleSheet( sal_uInt16 nPara ) 2040 { 2041 SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) ); 2042 ImplSetLevelDependendStyleSheet( nPara ); 2043 pEditEngine->SetParaAttribs( nPara, aOldAttrs ); 2044 } 2045 2046 SV_IMPL_PTRARR( NotifyList, EENotifyPtr ); 2047 2048 void Outliner::ImplBlockInsertionCallbacks( sal_Bool b ) 2049 { 2050 if ( b ) 2051 { 2052 bBlockInsCallback++; 2053 } 2054 else 2055 { 2056 DBG_ASSERT( bBlockInsCallback, "ImplBlockInsertionCallbacks ?!" ); 2057 bBlockInsCallback--; 2058 if ( !bBlockInsCallback ) 2059 { 2060 // Call blocked notify events... 2061 while ( pEditEngine->aNotifyCache.Count() ) 2062 { 2063 EENotify* pNotify = pEditEngine->aNotifyCache[0]; 2064 // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler... 2065 pEditEngine->aNotifyCache.Remove( 0 ); 2066 pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); 2067 delete pNotify; 2068 } 2069 } 2070 } 2071 } 2072 2073 IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify ) 2074 { 2075 if ( !bBlockInsCallback ) 2076 { 2077 pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); 2078 } 2079 else 2080 { 2081 EENotify* pNewNotify = new EENotify( *pNotify ); 2082 pEditEngine->aNotifyCache.Insert( pNewNotify, pEditEngine->aNotifyCache.Count() ); 2083 } 2084 2085 return 0; 2086 } 2087 2088 /** sets a link that is called at the beginning of a drag operation at an edit view */ 2089 void Outliner::SetBeginDropHdl( const Link& rLink ) 2090 { 2091 pEditEngine->SetBeginDropHdl( rLink ); 2092 } 2093 2094 Link Outliner::GetBeginDropHdl() const 2095 { 2096 return pEditEngine->GetBeginDropHdl(); 2097 } 2098 2099 /** sets a link that is called at the end of a drag operation at an edit view */ 2100 void Outliner::SetEndDropHdl( const Link& rLink ) 2101 { 2102 pEditEngine->SetEndDropHdl( rLink ); 2103 } 2104 2105 Link Outliner::GetEndDropHdl() const 2106 { 2107 return pEditEngine->GetEndDropHdl(); 2108 } 2109 2110 /** sets a link that is called before a drop or paste operation. */ 2111 void Outliner::SetBeginPasteOrDropHdl( const Link& rLink ) 2112 { 2113 maBeginPasteOrDropHdl = rLink; 2114 } 2115 2116 /** sets a link that is called after a drop or paste operation. */ 2117 void Outliner::SetEndPasteOrDropHdl( const Link& rLink ) 2118 { 2119 maEndPasteOrDropHdl = rLink; 2120 } 2121 2122 void Outliner::SetParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) 2123 { 2124 if( pPara && !pPara->HasFlag( nFlag ) ) 2125 { 2126 if( IsUndoEnabled() && !IsInUndo() ) 2127 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) ); 2128 2129 pPara->SetFlag( nFlag ); 2130 } 2131 } 2132 2133 void Outliner::RemoveParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) 2134 { 2135 if( pPara && pPara->HasFlag( nFlag ) ) 2136 { 2137 if( IsUndoEnabled() && !IsInUndo() ) 2138 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags & ~nFlag ) ); 2139 2140 pPara->RemoveFlag( nFlag ); 2141 } 2142 } 2143 2144 bool Outliner::HasParaFlag( const Paragraph* pPara, sal_uInt16 nFlag ) const 2145 { 2146 return pPara && pPara->HasFlag( nFlag ); 2147 } 2148 2149 2150 sal_Bool DrawPortionInfo::IsRTL() const 2151 { 2152 if(0xFF == mnBiDiLevel) 2153 { 2154 // Use Bidi functions from icu 2.0 to calculate if this portion 2155 // is RTL or not. 2156 UErrorCode nError(U_ZERO_ERROR); 2157 UBiDi* pBidi = ubidi_openSized(mrText.Len(), 0, &nError); 2158 nError = U_ZERO_ERROR; 2159 2160 // I do not have this info here. Is it necessary? I'll have to ask MT. 2161 const sal_uInt8 nDefaultDir = UBIDI_LTR; //IsRightToLeft( nPara ) ? UBIDI_RTL : UBIDI_LTR; 2162 2163 ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(mrText.GetBuffer()), mrText.Len(), nDefaultDir, NULL, &nError); // UChar != sal_Unicode in MinGW 2164 nError = U_ZERO_ERROR; 2165 2166 // sal_Int32 nCount(ubidi_countRuns(pBidi, &nError)); 2167 2168 int32_t nStart(0); 2169 int32_t nEnd; 2170 UBiDiLevel nCurrDir; 2171 2172 ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir); 2173 2174 ubidi_close(pBidi); 2175 2176 // remember on-demand calculated state 2177 ((DrawPortionInfo*)this)->mnBiDiLevel = nCurrDir; 2178 } 2179 2180 return (1 == (mnBiDiLevel % 2)); 2181 } 2182 2183 // eof 2184