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 if ( GetNumberFormat(nPara) ) 1514 { 1515 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); 1516 return rBulletState.GetValue(); 1517 } 1518 else 1519 return sal_False; 1520 } 1521 1522 const SvxNumberFormat* Outliner::GetNumberFormat( sal_uInt16 nPara ) const 1523 { 1524 const SvxNumberFormat* pFmt = NULL; 1525 1526 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1527 if (pPara == NULL) 1528 return NULL; 1529 1530 sal_Int16 nDepth = pPara? pPara->GetDepth() : -1; 1531 1532 if( nDepth >= 0 ) 1533 { 1534 const SvxNumBulletItem& rNumBullet = (const SvxNumBulletItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET ); 1535 if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth ) 1536 pFmt = rNumBullet.GetNumRule()->Get( nDepth ); 1537 } 1538 1539 return pFmt; 1540 } 1541 1542 Size Outliner::ImplGetBulletSize( sal_uInt16 nPara ) 1543 { 1544 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1545 if (!pPara) 1546 return Size(); 1547 1548 if( pPara->aBulSize.Width() == -1 ) 1549 { 1550 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1551 DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" ); 1552 1553 if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE ) 1554 { 1555 pPara->aBulSize = Size( 0, 0 ); 1556 } 1557 else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) 1558 { 1559 String aBulletText = ImplGetBulletText( nPara ); 1560 OutputDevice* pRefDev = pEditEngine->GetRefDevice(); 1561 Font aBulletFont( ImpCalcBulletFont( nPara ) ); 1562 Font aRefFont( pRefDev->GetFont()); 1563 pRefDev->SetFont( aBulletFont ); 1564 pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText ); 1565 pPara->aBulSize.Height() = pRefDev->GetTextHeight(); 1566 pRefDev->SetFont( aRefFont ); 1567 } 1568 else 1569 { 1570 pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() ); 1571 } 1572 } 1573 1574 return pPara->aBulSize; 1575 } 1576 1577 void Outliner::ImplCheckParagraphs( sal_uInt16 nStart, sal_uInt16 nEnd ) 1578 { 1579 DBG_CHKTHIS( Outliner, 0 ); 1580 1581 // --> OD 2009-03-10 #i100014# 1582 // assure that the following for-loop does not loop forever 1583 for ( sal_uInt16 n = nStart; n < nEnd; n++ ) 1584 // <-- 1585 { 1586 Paragraph* pPara = pParaList->GetParagraph( n ); 1587 if (pPara) 1588 { 1589 pPara->Invalidate(); 1590 ImplCalcBulletText( n, sal_False, sal_False ); 1591 } 1592 } 1593 } 1594 1595 void Outliner::SetRefDevice( OutputDevice* pRefDev ) 1596 { 1597 DBG_CHKTHIS(Outliner,0); 1598 pEditEngine->SetRefDevice( pRefDev ); 1599 for ( sal_uInt16 n = (sal_uInt16) pParaList->GetParagraphCount(); n; ) 1600 { 1601 Paragraph* pPara = pParaList->GetParagraph( --n ); 1602 pPara->Invalidate(); 1603 } 1604 } 1605 1606 void Outliner::ParaAttribsChanged( sal_uInt16 nPara ) 1607 { 1608 DBG_CHKTHIS(Outliner,0); 1609 1610 // Der Outliner hat kein eigenes Undo, wenn Absaetz getrennt/verschmolzen werden. 1611 // Beim ParagraphInserted ist das Attribut EE_PARA_OUTLLEVEL 1612 // ggf. noch nicht eingestellt, dies wird aber benoetigt um die Tiefe 1613 // des Absatzes zu bestimmen. 1614 1615 if( pEditEngine->IsInUndo() ) 1616 { 1617 if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() ) 1618 { 1619 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1620 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); 1621 if ( pPara && pPara->GetDepth() != rLevel.GetValue() ) 1622 { 1623 pPara->SetDepth( rLevel.GetValue() ); 1624 ImplCalcBulletText( nPara, sal_True, sal_True ); 1625 } 1626 } 1627 } 1628 } 1629 1630 void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle ) 1631 { 1632 DBG_CHKTHIS(Outliner,0); 1633 1634 // Die EditEngine ruft StyleSheetChanged auch fuer abgeleitete Styles. 1635 // MT: Hier wurde frueher alle Absaetze durch ein ImpRecalcParaAttribs 1636 // gejagt, die die besagte Vorlage haben, warum? 1637 // => Eigentlich kann sich nur die Bullet-Repraesentation aendern... 1638 1639 sal_uInt16 nParas = (sal_uInt16)pParaList->GetParagraphCount(); 1640 for( sal_uInt16 nPara = 0; nPara < nParas; nPara++ ) 1641 { 1642 if ( pEditEngine->GetStyleSheet( nPara ) == pStyle ) 1643 { 1644 ImplCheckNumBulletItem( nPara ); 1645 ImplCalcBulletText( nPara, sal_False, sal_False ); 1646 // #97333# EditEngine formats changed paragraphs before calling this method, 1647 // so they are not reformatted now and use wrong bullet indent 1648 pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); 1649 } 1650 } 1651 } 1652 1653 Rectangle Outliner::ImpCalcBulletArea( sal_uInt16 nPara, sal_Bool bAdjust, sal_Bool bReturnPaperPos ) 1654 { 1655 // Bullet-Bereich innerhalb des Absatzes... 1656 Rectangle aBulletArea; 1657 1658 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1659 if ( pFmt ) 1660 { 1661 Point aTopLeft; 1662 Size aBulletSize( ImplGetBulletSize( nPara ) ); 1663 1664 sal_Bool bOutlineMode = ( pEditEngine->GetControlWord() & EE_CNTRL_OUTLINER ) != 0; 1665 1666 // the ODF attribut text:space-before which holds the spacing to add to the left of the label 1667 const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset(); 1668 1669 const SvxLRSpaceItem& rLR = (const SvxLRSpaceItem&) pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); 1670 aTopLeft.X() = rLR.GetTxtLeft() + rLR.GetTxtFirstLineOfst() + nSpaceBefore; 1671 1672 long nBulletWidth = Max( (long) -rLR.GetTxtFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) ); 1673 if ( nBulletWidth < aBulletSize.Width() ) // Bullet macht sich Platz 1674 nBulletWidth = aBulletSize.Width(); 1675 1676 if ( bAdjust && !bOutlineMode ) 1677 { 1678 // Bei zentriert/rechtsbuendig anpassen 1679 const SvxAdjustItem& rItem = (const SvxAdjustItem&)pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST ); 1680 if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) || 1681 ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) ) 1682 { 1683 aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth; 1684 } 1685 } 1686 1687 // Vertikal: 1688 ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara ); 1689 if ( aInfos.bValid ) 1690 { 1691 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // #91076# nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine 1692 aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight 1693 + aInfos.nFirstLineTextHeight / 2 1694 - aBulletSize.Height() / 2; 1695 // ggf. lieber auf der Baseline ausgeben... 1696 if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) ) 1697 { 1698 Font aBulletFont( ImpCalcBulletFont( nPara ) ); 1699 if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) 1700 { 1701 OutputDevice* pRefDev = pEditEngine->GetRefDevice(); 1702 Font aOldFont = pRefDev->GetFont(); 1703 pRefDev->SetFont( aBulletFont ); 1704 FontMetric aMetric( pRefDev->GetFontMetric() ); 1705 // Leading der ersten Zeile... 1706 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent; 1707 aTopLeft.Y() -= aMetric.GetAscent(); 1708 pRefDev->SetFont( aOldFont ); 1709 } 1710 } 1711 } 1712 1713 // Horizontal: 1714 if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT ) 1715 { 1716 aTopLeft.X() += nBulletWidth - aBulletSize.Width(); 1717 } 1718 else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER ) 1719 { 1720 aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2; 1721 } 1722 1723 if ( aTopLeft.X() < 0 ) // dann draengeln 1724 aTopLeft.X() = 0; 1725 1726 aBulletArea = Rectangle( aTopLeft, aBulletSize ); 1727 } 1728 if ( bReturnPaperPos ) 1729 { 1730 Size aBulletSize( aBulletArea.GetSize() ); 1731 Point aBulletDocPos( aBulletArea.TopLeft() ); 1732 aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y(); 1733 Point aBulletPos( aBulletDocPos ); 1734 1735 if ( IsVertical() ) 1736 { 1737 aBulletPos.Y() = aBulletDocPos.X(); 1738 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y(); 1739 // Rotate: 1740 aBulletPos.X() -= aBulletSize.Height(); 1741 Size aSz( aBulletSize ); 1742 aBulletSize.Width() = aSz.Height(); 1743 aBulletSize.Height() = aSz.Width(); 1744 } 1745 else if ( pEditEngine->IsRightToLeft( nPara ) ) 1746 { 1747 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width(); 1748 } 1749 1750 aBulletArea = Rectangle( aBulletPos, aBulletSize ); 1751 } 1752 return aBulletArea; 1753 } 1754 1755 void Outliner::ExpandHdl() 1756 { 1757 DBG_CHKTHIS(Outliner,0); 1758 aExpandHdl.Call( this ); 1759 } 1760 1761 EBulletInfo Outliner::GetBulletInfo( sal_uInt16 nPara ) 1762 { 1763 EBulletInfo aInfo; 1764 1765 aInfo.nParagraph = nPara; 1766 aInfo.bVisible = ImplHasBullet( nPara ); 1767 1768 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1769 aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0; 1770 1771 if( pFmt ) 1772 { 1773 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) 1774 { 1775 aInfo.aText = ImplGetBulletText( nPara ); 1776 1777 if( pFmt->GetBulletFont() ) 1778 aInfo.aFont = *pFmt->GetBulletFont(); 1779 } 1780 else if ( pFmt->GetBrush()->GetGraphicObject() ) 1781 { 1782 aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic(); 1783 } 1784 } 1785 1786 if ( aInfo.bVisible ) 1787 { 1788 aInfo.aBounds = ImpCalcBulletArea( nPara, sal_True, sal_True ); 1789 } 1790 1791 return aInfo; 1792 } 1793 1794 XubString Outliner::GetText( Paragraph* pParagraph, sal_uLong nCount ) const 1795 { 1796 DBG_CHKTHIS(Outliner,0); 1797 1798 XubString aText; 1799 sal_uInt16 nStartPara = (sal_uInt16) pParaList->GetAbsPos( pParagraph ); 1800 for ( sal_uInt16 n = 0; n < nCount; n++ ) 1801 { 1802 aText += pEditEngine->GetText( nStartPara + n ); 1803 if ( (n+1) < (sal_uInt16)nCount ) 1804 aText += '\n'; 1805 } 1806 return aText; 1807 } 1808 1809 void Outliner::Remove( Paragraph* pPara, sal_uLong nParaCount ) 1810 { 1811 DBG_CHKTHIS(Outliner,0); 1812 1813 sal_uLong nPos = pParaList->GetAbsPos( pPara ); 1814 if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) ) 1815 { 1816 Clear(); 1817 } 1818 else 1819 { 1820 for( sal_uInt16 n = 0; n < (sal_uInt16)nParaCount; n++ ) 1821 pEditEngine->RemoveParagraph( (sal_uInt16) nPos ); 1822 } 1823 } 1824 1825 void Outliner::StripPortions() 1826 { 1827 DBG_CHKTHIS(Outliner,0); 1828 bStrippingPortions = sal_True; 1829 pEditEngine->StripPortions(); 1830 bStrippingPortions = sal_False; 1831 } 1832 1833 // #101498# 1834 void Outliner::DrawingText( const Point& rStartPos, const XubString& rText, sal_uInt16 nTextStart, sal_uInt16 nTextLen, const sal_Int32* pDXArray,const SvxFont& rFont, 1835 sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt8 nRightToLeft, 1836 const EEngineData::WrongSpellVector* pWrongSpellVector, 1837 const SvxFieldData* pFieldData, 1838 bool bEndOfLine, 1839 bool bEndOfParagraph, 1840 bool bEndOfBullet, 1841 const ::com::sun::star::lang::Locale* pLocale, 1842 const Color& rOverlineColor, 1843 const Color& rTextLineColor) 1844 { 1845 DBG_CHKTHIS(Outliner,0); 1846 1847 if(aDrawPortionHdl.IsSet()) 1848 { 1849 // #101498# 1850 DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector, 1851 pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, bEndOfLine, bEndOfParagraph, bEndOfBullet); 1852 1853 aDrawPortionHdl.Call( &aInfo ); 1854 } 1855 } 1856 1857 long Outliner::RemovingPagesHdl( OutlinerView* pView ) 1858 { 1859 DBG_CHKTHIS(Outliner,0); 1860 return aRemovingPagesHdl.IsSet() ? aRemovingPagesHdl.Call( pView ) : sal_True; 1861 } 1862 1863 sal_Bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, sal_uInt16 _nFirstPage, sal_uInt16 nPages ) 1864 { 1865 DBG_CHKTHIS(Outliner,0); 1866 1867 nDepthChangedHdlPrevDepth = nPages; 1868 mnFirstSelPage = _nFirstPage; 1869 pHdlParagraph = 0; 1870 return (sal_Bool)RemovingPagesHdl( pCurView ); 1871 } 1872 1873 SfxItemSet Outliner::GetParaAttribs( sal_uInt16 nPara ) 1874 { 1875 DBG_CHKTHIS(Outliner,0); 1876 return pEditEngine->GetParaAttribs( nPara ); 1877 } 1878 1879 IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara ) 1880 { 1881 DBG_CHKTHIS(Outliner,0); 1882 1883 sal_uLong nPara = pParaList->GetAbsPos( pPara ); 1884 pEditEngine->ShowParagraph( (sal_uInt16)nPara, pPara->IsVisible() ); 1885 1886 return 0; 1887 } 1888 1889 IMPL_LINK( Outliner, BeginMovingParagraphsHdl, MoveParagraphsInfo*, EMPTYARG ) 1890 { 1891 DBG_CHKTHIS(Outliner,0); 1892 1893 if( !IsInUndo() ) 1894 GetBeginMovingHdl().Call( this ); 1895 1896 return 0; 1897 } 1898 1899 IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos ) 1900 { 1901 UndoActionStart( EDITUNDO_DRAGANDDROP ); 1902 maBeginPasteOrDropHdl.Call(pInfos); 1903 return 0; 1904 } 1905 1906 IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos ) 1907 { 1908 bPasting = sal_False; 1909 ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); 1910 maEndPasteOrDropHdl.Call( pInfos ); 1911 UndoActionEnd( EDITUNDO_DRAGANDDROP ); 1912 return 0; 1913 } 1914 1915 IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos ) 1916 { 1917 DBG_CHKTHIS(Outliner,0); 1918 1919 pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); 1920 sal_uInt16 nChangesStart = Min( pInfos->nStartPara, pInfos->nDestPara ); 1921 sal_uInt16 nParas = (sal_uInt16)pParaList->GetParagraphCount(); 1922 for ( sal_uInt16 n = nChangesStart; n < nParas; n++ ) 1923 ImplCalcBulletText( n, sal_False, sal_False ); 1924 1925 if( !IsInUndo() ) 1926 aEndMovingHdl.Call( this ); 1927 1928 return 0; 1929 } 1930 1931 static bool isSameNumbering( const SvxNumberFormat& rN1, const SvxNumberFormat& rN2 ) 1932 { 1933 if( rN1.GetNumberingType() != rN2.GetNumberingType() ) 1934 return false; 1935 1936 if( rN1.GetNumStr(1) != rN2.GetNumStr(1) ) 1937 return false; 1938 1939 if( (rN1.GetPrefix() != rN2.GetPrefix()) || (rN1.GetSuffix() != rN2.GetSuffix()) ) 1940 return false; 1941 1942 return true; 1943 } 1944 1945 sal_uInt16 Outliner::ImplGetNumbering( sal_uInt16 nPara, const SvxNumberFormat* pParaFmt ) 1946 { 1947 sal_uInt16 nNumber = pParaFmt->GetStart() - 1; 1948 1949 Paragraph* pPara = pParaList->GetParagraph( nPara ); 1950 const sal_Int16 nParaDepth = pPara->GetDepth(); 1951 1952 do 1953 { 1954 pPara = pParaList->GetParagraph( nPara ); 1955 const sal_Int16 nDepth = pPara->GetDepth(); 1956 1957 // ignore paragraphs that are below our paragraph or have no numbering 1958 if( (nDepth > nParaDepth) || (nDepth == -1) ) 1959 continue; 1960 1961 // stop on paragraphs that are above our paragraph 1962 if( nDepth < nParaDepth ) 1963 break; 1964 1965 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 1966 1967 if( pFmt == 0 ) 1968 continue; // ignore paragraphs without bullets 1969 1970 // check if numbering less than or equal to pParaFmt 1971 if( !isSameNumbering( *pFmt, *pParaFmt ) || ( pFmt->GetStart() < pParaFmt->GetStart() ) ) 1972 break; 1973 1974 if ( pFmt->GetStart() > pParaFmt->GetStart() ) 1975 { 1976 nNumber += pFmt->GetStart() - pParaFmt->GetStart(); 1977 pParaFmt = pFmt; 1978 } 1979 1980 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); 1981 1982 if( rBulletState.GetValue() ) 1983 nNumber += 1; 1984 1985 // same depth, same number format, check for restart 1986 const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue(); 1987 if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() ) 1988 { 1989 if( nNumberingStartValue != -1 ) 1990 nNumber += nNumberingStartValue - 1; 1991 break; 1992 } 1993 } 1994 while( nPara-- ); 1995 1996 return nNumber; 1997 } 1998 1999 void Outliner::ImplCalcBulletText( sal_uInt16 nPara, sal_Bool bRecalcLevel, sal_Bool bRecalcChilds ) 2000 { 2001 DBG_CHKTHIS(Outliner,0); 2002 2003 Paragraph* pPara = pParaList->GetParagraph( nPara ); 2004 sal_uInt16 nRelPos = 0xFFFF; 2005 2006 while ( pPara ) 2007 { 2008 XubString aBulletText; 2009 const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); 2010 if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) ) 2011 { 2012 aBulletText += pFmt->GetPrefix(); 2013 if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) 2014 { 2015 aBulletText += pFmt->GetBulletChar(); 2016 } 2017 else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) 2018 { 2019 aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) ); 2020 } 2021 aBulletText += pFmt->GetSuffix(); 2022 } 2023 2024 if( aBulletText != pPara->GetText() ) 2025 pPara->SetText( aBulletText ); 2026 2027 pPara->nFlags &= (~PARAFLAG_SETBULLETTEXT); 2028 2029 if ( bRecalcLevel ) 2030 { 2031 if ( nRelPos != 0xFFFF ) 2032 nRelPos++; 2033 2034 sal_Int16 nDepth = pPara->GetDepth(); 2035 pPara = pParaList->GetParagraph( ++nPara ); 2036 if ( !bRecalcChilds ) 2037 { 2038 while ( pPara && ( pPara->GetDepth() > nDepth ) ) 2039 pPara = pParaList->GetParagraph( ++nPara ); 2040 } 2041 2042 if ( pPara && ( pPara->GetDepth() < nDepth ) ) 2043 pPara = NULL; 2044 } 2045 else 2046 { 2047 pPara = NULL; 2048 } 2049 } 2050 } 2051 2052 void Outliner::Clear() 2053 { 2054 DBG_CHKTHIS(Outliner,0); 2055 2056 if( !bFirstParaIsEmpty ) 2057 { 2058 ImplBlockInsertionCallbacks( sal_True ); 2059 pEditEngine->Clear(); 2060 pParaList->Clear( sal_True ); 2061 pParaList->Insert( new Paragraph( nMinDepth ), LIST_APPEND ); 2062 bFirstParaIsEmpty = sal_True; 2063 ImplBlockInsertionCallbacks( sal_False ); 2064 } 2065 else 2066 { 2067 Paragraph* pPara = pParaList->GetParagraph( 0 ); 2068 if(pPara) 2069 pPara->SetDepth( nMinDepth ); 2070 } 2071 } 2072 2073 void Outliner::SetFlatMode( sal_Bool bFlat ) 2074 { 2075 DBG_CHKTHIS(Outliner,0); 2076 2077 if( bFlat != pEditEngine->IsFlatMode() ) 2078 { 2079 for ( sal_uInt16 nPara = (sal_uInt16)pParaList->GetParagraphCount(); nPara; ) 2080 pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1; 2081 2082 pEditEngine->SetFlatMode( bFlat ); 2083 } 2084 } 2085 2086 String Outliner::ImplGetBulletText( sal_uInt16 nPara ) 2087 { 2088 String aRes; 2089 Paragraph* pPara = pParaList->GetParagraph( nPara ); 2090 if (pPara) 2091 { 2092 // MT: Optimierung mal wieder aktivieren... 2093 // if( pPara->nFlags & PARAFLAG_SETBULLETTEXT ) 2094 ImplCalcBulletText( nPara, sal_False, sal_False ); 2095 aRes = pPara->GetText(); 2096 } 2097 return aRes; 2098 } 2099 2100 // this is needed for StarOffice Api 2101 void Outliner::SetLevelDependendStyleSheet( sal_uInt16 nPara ) 2102 { 2103 SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) ); 2104 ImplSetLevelDependendStyleSheet( nPara ); 2105 pEditEngine->SetParaAttribs( nPara, aOldAttrs ); 2106 } 2107 2108 SV_IMPL_PTRARR( NotifyList, EENotifyPtr ); 2109 2110 void Outliner::ImplBlockInsertionCallbacks( sal_Bool b ) 2111 { 2112 if ( b ) 2113 { 2114 bBlockInsCallback++; 2115 } 2116 else 2117 { 2118 DBG_ASSERT( bBlockInsCallback, "ImplBlockInsertionCallbacks ?!" ); 2119 bBlockInsCallback--; 2120 if ( !bBlockInsCallback ) 2121 { 2122 // Call blocked notify events... 2123 while ( pEditEngine->aNotifyCache.Count() ) 2124 { 2125 EENotify* pNotify = pEditEngine->aNotifyCache[0]; 2126 // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler... 2127 pEditEngine->aNotifyCache.Remove( 0 ); 2128 pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); 2129 delete pNotify; 2130 } 2131 } 2132 } 2133 } 2134 2135 IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify ) 2136 { 2137 if ( !bBlockInsCallback ) 2138 { 2139 pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); 2140 } 2141 else 2142 { 2143 EENotify* pNewNotify = new EENotify( *pNotify ); 2144 pEditEngine->aNotifyCache.Insert( pNewNotify, pEditEngine->aNotifyCache.Count() ); 2145 } 2146 2147 return 0; 2148 } 2149 2150 /** sets a link that is called at the beginning of a drag operation at an edit view */ 2151 void Outliner::SetBeginDropHdl( const Link& rLink ) 2152 { 2153 pEditEngine->SetBeginDropHdl( rLink ); 2154 } 2155 2156 Link Outliner::GetBeginDropHdl() const 2157 { 2158 return pEditEngine->GetBeginDropHdl(); 2159 } 2160 2161 /** sets a link that is called at the end of a drag operation at an edit view */ 2162 void Outliner::SetEndDropHdl( const Link& rLink ) 2163 { 2164 pEditEngine->SetEndDropHdl( rLink ); 2165 } 2166 2167 Link Outliner::GetEndDropHdl() const 2168 { 2169 return pEditEngine->GetEndDropHdl(); 2170 } 2171 2172 /** sets a link that is called before a drop or paste operation. */ 2173 void Outliner::SetBeginPasteOrDropHdl( const Link& rLink ) 2174 { 2175 maBeginPasteOrDropHdl = rLink; 2176 } 2177 2178 /** sets a link that is called after a drop or paste operation. */ 2179 void Outliner::SetEndPasteOrDropHdl( const Link& rLink ) 2180 { 2181 maEndPasteOrDropHdl = rLink; 2182 } 2183 2184 void Outliner::SetParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) 2185 { 2186 if( pPara && !pPara->HasFlag( nFlag ) ) 2187 { 2188 if( IsUndoEnabled() && !IsInUndo() ) 2189 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) ); 2190 2191 pPara->SetFlag( nFlag ); 2192 } 2193 } 2194 2195 void Outliner::RemoveParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) 2196 { 2197 if( pPara && pPara->HasFlag( nFlag ) ) 2198 { 2199 if( IsUndoEnabled() && !IsInUndo() ) 2200 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags & ~nFlag ) ); 2201 2202 pPara->RemoveFlag( nFlag ); 2203 } 2204 } 2205 2206 bool Outliner::HasParaFlag( const Paragraph* pPara, sal_uInt16 nFlag ) const 2207 { 2208 return pPara && pPara->HasFlag( nFlag ); 2209 } 2210 2211 2212 sal_Bool DrawPortionInfo::IsRTL() const 2213 { 2214 if(0xFF == mnBiDiLevel) 2215 { 2216 // Use Bidi functions from icu 2.0 to calculate if this portion 2217 // is RTL or not. 2218 UErrorCode nError(U_ZERO_ERROR); 2219 UBiDi* pBidi = ubidi_openSized(mrText.Len(), 0, &nError); 2220 nError = U_ZERO_ERROR; 2221 2222 // I do not have this info here. Is it necessary? I'll have to ask MT. 2223 const sal_uInt8 nDefaultDir = UBIDI_LTR; //IsRightToLeft( nPara ) ? UBIDI_RTL : UBIDI_LTR; 2224 2225 ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(mrText.GetBuffer()), mrText.Len(), nDefaultDir, NULL, &nError); // UChar != sal_Unicode in MinGW 2226 nError = U_ZERO_ERROR; 2227 2228 // sal_Int32 nCount(ubidi_countRuns(pBidi, &nError)); 2229 2230 int32_t nStart(0); 2231 int32_t nEnd; 2232 UBiDiLevel nCurrDir; 2233 2234 ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir); 2235 2236 ubidi_close(pBidi); 2237 2238 // remember on-demand calculated state 2239 ((DrawPortionInfo*)this)->mnBiDiLevel = nCurrDir; 2240 } 2241 2242 return (1 == (mnBiDiLevel % 2)); 2243 } 2244 2245 // eof 2246