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