Update ooo320-m1
[ooovba.git] / svx / source / outliner / outliner.cxx
blobca7150afcbe19728f6fd0e773a2852f82394334d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: outliner.cxx,v $
10 * $Revision: 1.75.20.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <outl_pch.hxx>
36 #include <math.h>
37 #include <svtools/style.hxx>
38 #include <vcl/wrkwin.hxx>
39 #define _OUTLINER_CXX
40 #include <svx/outliner.hxx>
41 #include <paralist.hxx>
42 #include <svx/outlobj.hxx>
43 #include <outleeng.hxx>
44 #include <outlundo.hxx>
45 #include <svx/eeitem.hxx>
46 #include <editstat.hxx>
47 #include <svx/scripttypeitem.hxx>
48 #include <svx/editobj.hxx>
49 #include <svtools/itemset.hxx>
50 #include <svtools/whiter.hxx>
51 #include <vcl/metric.hxx>
52 #include <svx/numitem.hxx>
53 #include <svx/adjitem.hxx>
54 #include <vcl/graph.hxx>
55 #include <vcl/gdimtf.hxx>
56 #include <vcl/metaact.hxx>
57 #include <goodies/grfmgr.hxx>
58 #include <svx/svxfont.hxx>
59 #include <svx/brshitem.hxx>
60 #include <svtools/itempool.hxx>
62 // #101498# calculate if it's RTL or not
63 #include <unicode/ubidi.h>
65 #define DEFAULT_SCALE 75
67 static const USHORT nDefStyles = 3; // Sonderbehandlung fuer die ersten 3 Ebenen
68 static const USHORT nDefBulletIndent = 800;
69 static const USHORT nDefBulletWidth = 700;
70 static const USHORT pDefBulletIndents[nDefStyles]= { 1400, 800, 800 };
71 static const USHORT pDefBulletWidths[nDefStyles] = { 1000, 850, 700 };
73 USHORT lcl_ImplGetDefBulletWidth( sal_Int16 nDepth )
75 return ( nDepth < nDefStyles ) ? pDefBulletWidths[nDepth] : nDefBulletWidth;
78 USHORT lcl_ImplGetDefBulletIndent( sal_Int16 nDepth )
80 USHORT nI = 0;
82 if( nDepth >= 0 )
84 for ( sal_Int16 n = 0; n <= nDepth; n++ )
85 nI = nI +
86 ( ( n < nDefStyles ) ? pDefBulletIndents[n] : nDefBulletIndent );
88 return nI;
92 // ----------------------------------------------------------------------
93 // Outliner
94 // ----------------------------------------------------------------------
95 DBG_NAME(Outliner);
97 void Outliner::ImplCheckDepth( sal_Int16& rnDepth ) const
99 if( rnDepth < nMinDepth )
100 rnDepth = nMinDepth;
101 else if( rnDepth > nMaxDepth )
102 rnDepth = nMaxDepth;
105 Paragraph* Outliner::Insert(const XubString& rText, ULONG nAbsPos, sal_Int16 nDepth)
107 DBG_CHKTHIS(Outliner,0);
108 DBG_ASSERT(pParaList->GetParagraphCount(),"Insert:No Paras");
110 Paragraph* pPara;
112 ImplCheckDepth( nDepth );
114 ULONG nParagraphCount = pParaList->GetParagraphCount();
115 if( nAbsPos > nParagraphCount )
116 nAbsPos = nParagraphCount;
118 if( bFirstParaIsEmpty )
120 pPara = pParaList->GetParagraph( 0 );
121 if( pPara->GetDepth() != nDepth )
123 nDepthChangedHdlPrevDepth = pPara->GetDepth();
124 mnDepthChangeHdlPrevFlags = pPara->nFlags;
125 pPara->SetDepth( nDepth );
126 pHdlParagraph = pPara;
127 DepthChangedHdl();
129 pPara->nFlags |= PARAFLAG_HOLDDEPTH;
130 SetText( rText, pPara );
132 else
134 BOOL bUpdate = pEditEngine->GetUpdateMode();
135 pEditEngine->SetUpdateMode( FALSE );
136 ImplBlockInsertionCallbacks( TRUE );
137 pPara = new Paragraph( nDepth );
138 pParaList->Insert( pPara, nAbsPos );
139 pEditEngine->InsertParagraph( (USHORT)nAbsPos, String() );
140 DBG_ASSERT(pPara==pParaList->GetParagraph(nAbsPos),"Insert:Failed");
141 ImplInitDepth( (USHORT)nAbsPos, nDepth, FALSE );
142 pHdlParagraph = pPara;
143 ParagraphInsertedHdl();
144 pPara->nFlags |= PARAFLAG_HOLDDEPTH;
145 SetText( rText, pPara );
146 ImplBlockInsertionCallbacks( FALSE );
147 pEditEngine->SetUpdateMode( bUpdate );
149 bFirstParaIsEmpty = FALSE;
150 DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed");
151 return pPara;
155 void Outliner::ParagraphInserted( USHORT nPara )
157 DBG_CHKTHIS(Outliner,0);
159 if ( bBlockInsCallback )
160 return;
162 if( bPasting || pEditEngine->IsInUndo() )
164 Paragraph* pPara = new Paragraph( -1 );
165 pParaList->Insert( pPara, nPara );
166 if( pEditEngine->IsInUndo() )
168 pPara->nFlags = PARAFLAG_SETBULLETTEXT;
169 pPara->bVisible = TRUE;
170 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL );
171 pPara->SetDepth( rLevel.GetValue() );
174 else
176 sal_Int16 nDepth = -1;
177 Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 );
178 if ( pParaBefore )
179 nDepth = pParaBefore->GetDepth();
181 Paragraph* pPara = new Paragraph( nDepth );
182 pParaList->Insert( pPara, nPara );
184 if( !pEditEngine->IsInUndo() )
186 ImplCalcBulletText( nPara, TRUE, FALSE );
187 pHdlParagraph = pPara;
188 ParagraphInsertedHdl();
193 void Outliner::ParagraphDeleted( USHORT nPara )
195 DBG_CHKTHIS(Outliner,0);
197 if ( bBlockInsCallback || ( nPara == EE_PARA_ALL ) )
198 return;
200 Paragraph* pPara = pParaList->GetParagraph( nPara );
201 if (!pPara)
202 return;
204 sal_Int16 nDepth = pPara->GetDepth();
206 if( !pEditEngine->IsInUndo() )
208 pHdlParagraph = pPara;
209 ParagraphRemovingHdl();
212 pParaList->Remove( nPara );
213 delete pPara;
215 if( !pEditEngine->IsInUndo() && !bPasting )
217 pPara = pParaList->GetParagraph( nPara );
218 if ( pPara && ( pPara->GetDepth() > nDepth ) )
220 ImplCalcBulletText( nPara, TRUE, FALSE );
221 // naechsten auf gleicher Ebene suchen...
222 while ( pPara && pPara->GetDepth() > nDepth )
223 pPara = pParaList->GetParagraph( ++nPara );
226 if ( pPara && ( pPara->GetDepth() == nDepth ) )
227 ImplCalcBulletText( nPara, TRUE, FALSE );
231 void Outliner::Init( USHORT nMode )
233 nOutlinerMode = nMode;
235 Clear();
237 ULONG nCtrl = pEditEngine->GetControlWord();
238 nCtrl &= ~(EE_CNTRL_OUTLINER|EE_CNTRL_OUTLINER2);
240 SetMaxDepth( 9 );
242 switch ( ImplGetOutlinerMode() )
244 case OUTLINERMODE_TEXTOBJECT:
245 case OUTLINERMODE_TITLEOBJECT:
246 break;
248 case OUTLINERMODE_OUTLINEOBJECT:
249 nCtrl |= EE_CNTRL_OUTLINER2;
250 break;
251 case OUTLINERMODE_OUTLINEVIEW:
252 nCtrl |= EE_CNTRL_OUTLINER;
253 break;
255 default: DBG_ERROR( "Outliner::Init - Invalid Mode!" );
258 pEditEngine->SetControlWord( nCtrl );
260 ImplInitDepth( 0, GetMinDepth(), FALSE );
262 GetUndoManager().Clear();
265 void Outliner::SetMaxDepth( sal_Int16 nDepth, BOOL bCheckParagraphs )
267 if( nMaxDepth != nDepth )
269 nMaxDepth = Min( nDepth, (sal_Int16)(SVX_MAX_NUM-1) );
271 if( bCheckParagraphs )
273 USHORT nParagraphs = (USHORT)pParaList->GetParagraphCount();
274 for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
276 Paragraph* pPara = pParaList->GetParagraph( nPara );
277 if( pPara && pPara->GetDepth() > nMaxDepth )
279 SetDepth( pPara, nMaxDepth );
286 sal_Int16 Outliner::GetDepth( ULONG nPara ) const
288 Paragraph* pPara = pParaList->GetParagraph( nPara );
289 DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" );
290 return pPara ? pPara->GetDepth() : -1;
293 void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth )
295 DBG_CHKTHIS(Outliner,0);
297 ImplCheckDepth( nNewDepth );
299 if ( nNewDepth != pPara->GetDepth() )
301 nDepthChangedHdlPrevDepth = pPara->GetDepth();
302 mnDepthChangeHdlPrevFlags = pPara->nFlags;
303 pHdlParagraph = pPara;
305 USHORT nPara = (USHORT)GetAbsPos( pPara );
306 ImplInitDepth( nPara, nNewDepth, TRUE );
307 ImplCalcBulletText( nPara, FALSE, FALSE );
309 if ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT )
310 ImplSetLevelDependendStyleSheet( nPara );
312 DepthChangedHdl();
316 sal_Int16 Outliner::GetNumberingStartValue( sal_uInt16 nPara )
318 Paragraph* pPara = pParaList->GetParagraph( nPara );
319 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
320 return pPara ? pPara->GetNumberingStartValue() : -1;
323 void Outliner::SetNumberingStartValue( sal_uInt16 nPara, sal_Int16 nNumberingStartValue )
325 Paragraph* pPara = pParaList->GetParagraph( nPara );
326 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
327 if( pPara && pPara->GetNumberingStartValue() != nNumberingStartValue )
329 if( IsUndoEnabled() && !IsInUndo() )
330 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
331 pPara->GetNumberingStartValue(), nNumberingStartValue,
332 pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) );
334 pPara->SetNumberingStartValue( nNumberingStartValue );
335 // --> OD 2009-03-10 #i100014#
336 // It is not a good idea to substract 1 from a count and cast the result
337 // to USHORT without check, if the count is 0.
338 ImplCheckParagraphs( nPara, (USHORT) (pParaList->GetParagraphCount()) );
339 // <--
340 pEditEngine->SetModified();
344 sal_Bool Outliner::IsParaIsNumberingRestart( sal_uInt16 nPara )
346 Paragraph* pPara = pParaList->GetParagraph( nPara );
347 DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" );
348 return pPara ? pPara->IsParaIsNumberingRestart() : sal_False;
351 void Outliner::SetParaIsNumberingRestart( sal_uInt16 nPara, sal_Bool bParaIsNumberingRestart )
353 Paragraph* pPara = pParaList->GetParagraph( nPara );
354 DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" );
355 if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) )
357 if( IsUndoEnabled() && !IsInUndo() )
358 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
359 pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(),
360 pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) );
362 pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart );
363 // --> OD 2009-03-10 #i100014#
364 // It is not a good idea to substract 1 from a count and cast the result
365 // to USHORT without check, if the count is 0.
366 ImplCheckParagraphs( nPara, (USHORT) (pParaList->GetParagraphCount()) );
367 // <--
368 pEditEngine->SetModified();
372 OutlinerParaObject* Outliner::CreateParaObject( USHORT nStartPara, USHORT nCount ) const
374 DBG_CHKTHIS(Outliner,0);
376 if ( sal::static_int_cast< ULONG >( nStartPara + nCount ) >
377 pParaList->GetParagraphCount() )
378 nCount = sal::static_int_cast< USHORT >(
379 pParaList->GetParagraphCount() - nStartPara );
381 // When a new OutlinerParaObject is created because a paragraph is just beeing deleted,
382 // it can happen that the ParaList is not updated yet...
383 if ( ( nStartPara + nCount ) > pEditEngine->GetParagraphCount() )
384 nCount = pEditEngine->GetParagraphCount() - nStartPara;
386 if( !nCount )
387 return NULL;
389 EditTextObject* pText = pEditEngine->CreateTextObject( nStartPara, nCount );
390 const bool bIsEditDoc(OUTLINERMODE_TEXTOBJECT == ImplGetOutlinerMode());
391 ParagraphDataVector aParagraphDataVector(nCount);
392 const sal_uInt16 nLastPara(nStartPara + nCount - 1);
394 for(sal_uInt16 nPara(nStartPara); nPara <= nLastPara; nPara++)
396 aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara);
399 OutlinerParaObject* pPObj = new OutlinerParaObject(*pText, aParagraphDataVector, bIsEditDoc);
400 pPObj->SetOutlinerMode(GetMode());
401 delete pText;
403 return pPObj;
406 void Outliner::SetText( const XubString& rText, Paragraph* pPara )
408 DBG_CHKTHIS(Outliner,0);
409 DBG_ASSERT(pPara,"SetText:No Para");
411 BOOL bUpdate = pEditEngine->GetUpdateMode();
412 pEditEngine->SetUpdateMode( FALSE );
413 ImplBlockInsertionCallbacks( TRUE );
415 USHORT nPara = (USHORT)pParaList->GetAbsPos( pPara );
417 if( !rText.Len() )
419 pEditEngine->SetText( nPara, rText );
420 ImplInitDepth( nPara, pPara->GetDepth(), FALSE );
422 else
424 XubString aText( rText );
425 aText.ConvertLineEnd( LINEEND_LF );
427 if( aText.GetChar( aText.Len()-1 ) == '\x0A' )
428 aText.Erase( aText.Len()-1, 1 ); // letzten Umbruch loeschen
430 USHORT nCount = aText.GetTokenCount( '\x0A' );
431 USHORT nPos = 0;
432 USHORT nInsPos = nPara+1;
433 while( nCount > nPos )
435 XubString aStr = aText.GetToken( nPos, '\x0A' );
437 sal_Int16 nCurDepth;
438 if( nPos )
440 pPara = new Paragraph( -1 );
441 nCurDepth = -1;
443 else
444 nCurDepth = pPara->GetDepth();
446 // Im Outliner-Modus die Tabulatoren filtern und die
447 // Einrueckung ueber ein LRSpaceItem einstellen
448 // Im EditEngine-Modus ueber Maltes Tabulatoren einruecken
449 if( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) ||
450 ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ) )
452 // Tabs raus
453 USHORT nTabs = 0;
454 while ( ( nTabs < aStr.Len() ) && ( aStr.GetChar( nTabs ) == '\t' ) )
455 nTabs++;
456 if ( nTabs )
457 aStr.Erase( 0, nTabs );
459 // Tiefe beibehalten ? (siehe Outliner::Insert)
460 if( !(pPara->nFlags & PARAFLAG_HOLDDEPTH) )
462 nCurDepth = nTabs-1;
463 ImplCheckDepth( nCurDepth );
464 pPara->SetDepth( nCurDepth );
465 pPara->nFlags &= (~PARAFLAG_HOLDDEPTH);
468 if( nPos ) // nicht mit dem ersten Absatz
470 pParaList->Insert( pPara, nInsPos );
471 pEditEngine->InsertParagraph( nInsPos, aStr );
472 pHdlParagraph = pPara;
473 ParagraphInsertedHdl();
475 else
477 nInsPos--;
478 pEditEngine->SetText( nInsPos, aStr );
480 ImplInitDepth( nInsPos, nCurDepth, FALSE );
481 nInsPos++;
482 nPos++;
486 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"SetText failed!");
487 bFirstParaIsEmpty = FALSE;
488 ImplBlockInsertionCallbacks( FALSE );
489 pEditEngine->SetUpdateMode( bUpdate );
492 // pView == 0 -> Tabulatoren nicht beachten
494 bool Outliner::ImpConvertEdtToOut( sal_uInt32 nPara,EditView* pView)
496 DBG_CHKTHIS(Outliner,0);
498 bool bConverted = false;
499 USHORT nTabs = 0;
500 ESelection aDelSel;
502 // const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (sal_uInt16)nPara );
503 // bool bAlreadyOutliner = rAttrs.GetItemState( EE_PARA_OUTLLRSPACE ) == SFX_ITEM_ON ? true : false;
505 XubString aName;
506 XubString aHeading_US( RTL_CONSTASCII_USTRINGPARAM( "heading" ) );
507 XubString aNumber_US( RTL_CONSTASCII_USTRINGPARAM( "Numbering" ) );
509 XubString aStr( pEditEngine->GetText( (USHORT)nPara ) );
510 xub_Unicode* pPtr = (xub_Unicode*)aStr.GetBuffer();
512 USHORT nHeadingNumberStart = 0;
513 USHORT nNumberingNumberStart = 0;
514 SfxStyleSheet* pStyle= pEditEngine->GetStyleSheet( (USHORT)nPara );
515 if( pStyle )
517 aName = pStyle->GetName();
518 USHORT nSearch;
519 if ( ( nSearch = aName.Search( aHeading_US ) ) != STRING_NOTFOUND )
520 nHeadingNumberStart = nSearch + aHeading_US.Len();
521 else if ( ( nSearch = aName.Search( aNumber_US ) ) != STRING_NOTFOUND )
522 nNumberingNumberStart = nSearch + aNumber_US.Len();
525 if ( nHeadingNumberStart || nNumberingNumberStart )
527 // PowerPoint-Import ?
528 if( nHeadingNumberStart && ( aStr.Len() >= 2 ) &&
529 ( pPtr[0] != '\t' ) && ( pPtr[1] == '\t' ) )
531 // Bullet & Tab raus
532 aDelSel = ESelection( (USHORT)nPara, 0, (USHORT)nPara, 2 );
535 USHORT nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart;
536 String aLevel = aName.Copy( nPos );
537 aLevel.EraseLeadingChars( ' ' );
538 nTabs = sal::static_int_cast< USHORT >(aLevel.ToInt32());
539 if( nTabs )
540 nTabs--; // ebene 0 = "heading 1"
541 bConverted = TRUE;
543 else
545 // Fuehrende Tabulatoren filtern
546 while( *pPtr == '\t' )
548 pPtr++;
549 nTabs++;
551 // Tabulatoren aus dem Text entfernen
552 if( nTabs )
553 aDelSel = ESelection( (USHORT)nPara, 0, (USHORT)nPara, nTabs );
556 if ( aDelSel.HasRange() )
558 if ( pView )
560 pView->SetSelection( aDelSel );
561 pView->DeleteSelected();
563 else
564 pEditEngine->QuickDelete( aDelSel );
567 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( sal::static_int_cast< sal_uInt16 >(nPara), EE_PARA_OUTLLEVEL );
568 sal_Int16 nOutlLevel = rLevel.GetValue();
570 ImplCheckDepth( nOutlLevel );
571 ImplInitDepth( sal::static_int_cast< sal_uInt16 >(nPara), nOutlLevel, FALSE );
573 return bConverted;
576 void Outliner::SetText( const OutlinerParaObject& rPObj )
578 DBG_CHKTHIS(Outliner,0);
580 BOOL bUpdate = pEditEngine->GetUpdateMode();
581 pEditEngine->SetUpdateMode( FALSE );
583 BOOL bUndo = pEditEngine->IsUndoEnabled();
584 EnableUndo( FALSE );
586 Init( rPObj.GetOutlinerMode() );
588 ImplBlockInsertionCallbacks( TRUE );
589 pEditEngine->SetText(rPObj.GetTextObject());
590 if( rPObj.Count() != pEditEngine->GetParagraphCount() )
592 int nop=0;nop++;
595 bFirstParaIsEmpty = FALSE;
597 pParaList->Clear( TRUE );
598 for( USHORT nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ )
600 Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(nCurPara));
601 ImplCheckDepth( pPara->nDepth );
603 pParaList->Insert( pPara, LIST_APPEND );
604 ImplCheckNumBulletItem( nCurPara );
607 // --> OD 2009-03-10 #i100014#
608 // It is not a good idea to substract 1 from a count and cast the result
609 // to USHORT without check, if the count is 0.
610 ImplCheckParagraphs( 0, (USHORT) (pParaList->GetParagraphCount()) );
611 // <--
613 EnableUndo( bUndo );
614 ImplBlockInsertionCallbacks( FALSE );
615 pEditEngine->SetUpdateMode( bUpdate );
617 DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed");
618 DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed");
621 void Outliner::AddText( const OutlinerParaObject& rPObj )
623 DBG_CHKTHIS(Outliner,0);
624 Paragraph* pPara;
626 BOOL bUpdate = pEditEngine->GetUpdateMode();
627 pEditEngine->SetUpdateMode( FALSE );
629 ImplBlockInsertionCallbacks( TRUE );
630 ULONG nPara;
631 if( bFirstParaIsEmpty )
633 pParaList->Clear( TRUE );
634 pEditEngine->SetText(rPObj.GetTextObject());
635 nPara = 0;
637 else
639 nPara = pParaList->GetParagraphCount();
640 pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() );
642 bFirstParaIsEmpty = FALSE;
644 for( USHORT n = 0; n < rPObj.Count(); n++ )
646 pPara = new Paragraph( rPObj.GetParagraphData(n) );
647 pParaList->Insert( pPara, LIST_APPEND );
648 USHORT nP = sal::static_int_cast< USHORT >(nPara+n);
649 DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync");
650 ImplInitDepth( nP, pPara->GetDepth(), FALSE );
652 DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" );
654 // --> OD 2009-03-10 #i100014#
655 // It is not a good idea to substract 1 from a count and cast the result
656 // to USHORT without check, if the count is 0.
657 ImplCheckParagraphs( (USHORT)nPara, (USHORT) (pParaList->GetParagraphCount()) );
658 // <--
660 ImplBlockInsertionCallbacks( FALSE );
661 pEditEngine->SetUpdateMode( bUpdate );
664 void __EXPORT Outliner::FieldClicked( const SvxFieldItem& rField, USHORT nPara, USHORT nPos )
666 DBG_CHKTHIS(Outliner,0);
668 if ( aFieldClickedHdl.IsSet() )
670 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
671 aFldInfo.SetSimpleClick( TRUE );
672 aFieldClickedHdl.Call( &aFldInfo );
677 void __EXPORT Outliner::FieldSelected( const SvxFieldItem& rField, USHORT nPara, USHORT nPos )
679 DBG_CHKTHIS(Outliner,0);
680 if ( !aFieldClickedHdl.IsSet() )
681 return;
683 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
684 aFldInfo.SetSimpleClick( FALSE );
685 aFieldClickedHdl.Call( &aFldInfo );
689 XubString __EXPORT Outliner::CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rpTxtColor, Color*& rpFldColor )
691 DBG_CHKTHIS(Outliner,0);
692 if ( !aCalcFieldValueHdl.IsSet() )
693 return String( ' ' );
695 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
696 // Die FldColor ist mit COL_LIGHTGRAY voreingestellt.
697 if ( rpFldColor )
698 aFldInfo.SetFldColor( *rpFldColor );
700 aCalcFieldValueHdl.Call( &aFldInfo );
701 if ( aFldInfo.GetTxtColor() )
703 delete rpTxtColor;
704 rpTxtColor = new Color( *aFldInfo.GetTxtColor() );
707 delete rpFldColor;
708 rpFldColor = aFldInfo.GetFldColor() ? new Color( *aFldInfo.GetFldColor() ) : 0;
710 return aFldInfo.GetRepresentation();
713 void Outliner::SetStyleSheet( ULONG nPara, SfxStyleSheet* pStyle )
715 DBG_CHKTHIS(Outliner,0);
716 Paragraph* pPara = pParaList->GetParagraph( nPara );
717 if (pPara)
719 pEditEngine->SetStyleSheet( (USHORT)nPara, pStyle );
720 pPara->nFlags |= PARAFLAG_SETBULLETTEXT;
721 ImplCheckNumBulletItem( (USHORT) nPara );
725 void Outliner::SetVisible( Paragraph* pPara, BOOL bVisible )
727 DBG_CHKTHIS(Outliner,0);
728 DBG_ASSERT( pPara, "SetVisible: pPara = NULL" );
730 if (pPara)
732 pPara->bVisible = bVisible;
733 ULONG nPara = pParaList->GetAbsPos( pPara );
734 pEditEngine->ShowParagraph( (USHORT)nPara, bVisible );
738 void Outliner::ImplCheckNumBulletItem( USHORT nPara )
740 Paragraph* pPara = pParaList->GetParagraph( nPara );
741 if (pPara)
742 pPara->aBulSize.Width() = -1;
745 void Outliner::ImplSetLevelDependendStyleSheet( USHORT nPara, SfxStyleSheet* pLevelStyle )
747 DBG_CHKTHIS(Outliner,0);
749 DBG_ASSERT( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ), "SetLevelDependendStyleSheet: Wrong Mode!" );
751 SfxStyleSheet* pStyle = pLevelStyle;
752 if ( !pStyle )
753 pStyle = GetStyleSheet( nPara );
755 if ( pStyle )
757 sal_Int16 nDepth = GetDepth( nPara );
758 if( nDepth < 0 )
759 nDepth = 0;
761 String aNewStyleSheetName( pStyle->GetName() );
762 aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 );
763 aNewStyleSheetName += String::CreateFromInt32( nDepth+1 );
764 SfxStyleSheet* pNewStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( aNewStyleSheetName, pStyle->GetFamily() );
765 DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
766 if ( pNewStyle && ( pNewStyle != GetStyleSheet( nPara ) ) )
768 SfxItemSet aOldAttrs( GetParaAttribs( nPara ) );
769 SetStyleSheet( nPara, pNewStyle );
770 if ( aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON )
772 SfxItemSet aAttrs( GetParaAttribs( nPara ) );
773 aAttrs.Put( aOldAttrs.Get( EE_PARA_NUMBULLET ) );
774 SetParaAttribs( nPara, aAttrs );
780 void Outliner::ImplInitDepth( USHORT nPara, sal_Int16 nDepth, BOOL bCreateUndo, BOOL bUndoAction )
782 DBG_CHKTHIS(Outliner,0);
784 DBG_ASSERT( ( nDepth >= nMinDepth ) && ( nDepth <= nMaxDepth ), "ImplInitDepth - Depth is invalid!" );
786 Paragraph* pPara = pParaList->GetParagraph( nPara );
787 if (!pPara)
788 return;
789 sal_Int16 nOldDepth = pPara->GetDepth();
790 pPara->SetDepth( nDepth );
792 // Bei IsInUndo brauchen Attribute und Style nicht eingestellt werden,
793 // dort werden die alten Werte durch die EditEngine restauriert.
795 if( !IsInUndo() )
797 BOOL bUpdate = pEditEngine->GetUpdateMode();
798 pEditEngine->SetUpdateMode( FALSE );
800 BOOL bUndo = bCreateUndo && IsUndoEnabled();
801 if ( bUndo && bUndoAction )
802 UndoActionStart( OLUNDO_DEPTH );
804 SfxItemSet aAttrs( pEditEngine->GetParaAttribs( nPara ) );
805 aAttrs.Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nDepth ) );
806 pEditEngine->SetParaAttribs( nPara, aAttrs );
807 ImplCheckNumBulletItem( nPara );
808 ImplCalcBulletText( nPara, FALSE, FALSE );
810 if ( bUndo )
812 InsertUndo( new OutlinerUndoChangeDepth( this, nPara, nOldDepth, nDepth ) );
813 if ( bUndoAction )
814 UndoActionEnd( OLUNDO_DEPTH );
817 pEditEngine->SetUpdateMode( bUpdate );
821 void Outliner::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet )
823 DBG_CHKTHIS(Outliner,0);
825 pEditEngine->SetParaAttribs( nPara, rSet );
828 BOOL Outliner::Expand( Paragraph* pPara )
830 DBG_CHKTHIS(Outliner,0);
832 if ( pParaList->HasHiddenChilds( pPara ) )
834 OLUndoExpand* pUndo = 0;
835 BOOL bUndo = IsUndoEnabled() && !IsInUndo();
836 if( bUndo )
838 UndoActionStart( OLUNDO_EXPAND );
839 pUndo = new OLUndoExpand( this, OLUNDO_EXPAND );
840 pUndo->pParas = 0;
841 pUndo->nCount = (USHORT)pParaList->GetAbsPos( pPara );
843 pHdlParagraph = pPara;
844 bIsExpanding = TRUE;
845 pParaList->Expand( pPara );
846 ExpandHdl();
847 InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) );
848 if( bUndo )
850 InsertUndo( pUndo );
851 UndoActionEnd( OLUNDO_EXPAND );
853 return TRUE;
855 return FALSE;
859 BOOL Outliner::Collapse( Paragraph* pPara )
861 DBG_CHKTHIS(Outliner,0);
862 if ( pParaList->HasVisibleChilds( pPara ) ) // expandiert
864 OLUndoExpand* pUndo = 0;
865 BOOL bUndo = FALSE;
867 if( !IsInUndo() && IsUndoEnabled() )
868 bUndo = TRUE;
869 if( bUndo )
871 UndoActionStart( OLUNDO_COLLAPSE );
872 pUndo = new OLUndoExpand( this, OLUNDO_COLLAPSE );
873 pUndo->pParas = 0;
874 pUndo->nCount = (USHORT)pParaList->GetAbsPos( pPara );
877 pHdlParagraph = pPara;
878 bIsExpanding = FALSE;
879 pParaList->Collapse( pPara );
880 ExpandHdl();
881 InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) );
882 if( bUndo )
884 InsertUndo( pUndo );
885 UndoActionEnd( OLUNDO_COLLAPSE );
887 return TRUE;
889 return FALSE;
893 Font Outliner::ImpCalcBulletFont( USHORT nPara ) const
895 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
896 DBG_ASSERT( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ), "ImpCalcBulletFont: Missing or BitmapBullet!" );
898 Font aStdFont; //#107508#
899 if ( !pEditEngine->IsFlatMode() )
901 ESelection aSel( nPara, 0, nPara, 0 );
902 aStdFont = EditEngine::CreateFontFromItemSet( pEditEngine->GetAttribs( aSel ), GetScriptType( aSel ) );
904 else
906 aStdFont = pEditEngine->GetStandardFont( nPara );
909 Font aBulletFont;
910 if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
912 aBulletFont = *pFmt->GetBulletFont();
914 else
916 aBulletFont = aStdFont;
917 aBulletFont.SetUnderline( UNDERLINE_NONE );
918 aBulletFont.SetOverline( UNDERLINE_NONE );
919 aBulletFont.SetStrikeout( STRIKEOUT_NONE );
920 aBulletFont.SetEmphasisMark( EMPHASISMARK_NONE );
921 aBulletFont.SetRelief( RELIEF_NONE );
924 // #107508# Use original scale...
925 USHORT nStretchX, nStretchY;
926 const_cast<Outliner*>(this)->GetGlobalCharStretching(nStretchX, nStretchY);
928 USHORT nScale = pFmt->GetBulletRelSize() * nStretchY / 100;
929 ULONG nScaledLineHeight = aStdFont.GetSize().Height();
930 nScaledLineHeight *= nScale*10;
931 nScaledLineHeight /= 1000;
933 aBulletFont.SetAlign( ALIGN_BOTTOM );
934 aBulletFont.SetSize( Size( 0, nScaledLineHeight ) );
935 BOOL bVertical = IsVertical();
936 aBulletFont.SetVertical( bVertical );
937 aBulletFont.SetOrientation( bVertical ? 2700 : 0 );
939 Color aColor( COL_AUTO );
940 if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EE_CNTRL_NOCOLORS ) )
942 aColor = pFmt->GetBulletColor();
945 if ( ( aColor == COL_AUTO ) || ( IsForceAutoColor() ) )
946 aColor = pEditEngine->GetAutoColor();
948 aBulletFont.SetColor( aColor );
949 return aBulletFont;
952 void Outliner::PaintBullet( USHORT nPara, const Point& rStartPos,
953 const Point& rOrigin, short nOrientation, OutputDevice* pOutDev )
955 DBG_CHKTHIS(Outliner,0);
957 bool bDrawBullet = false;
958 if (pEditEngine)
960 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE );
961 bDrawBullet = rBulletState.GetValue() ? true : false;
964 if ( ImplHasBullet( nPara ) && bDrawBullet)
966 BOOL bVertical = IsVertical();
968 BOOL bRightToLeftPara = pEditEngine->IsRightToLeft( nPara );
970 Rectangle aBulletArea( ImpCalcBulletArea( nPara, TRUE, FALSE ) );
971 USHORT nStretchX, nStretchY;
972 GetGlobalCharStretching(nStretchX, nStretchY);
973 aBulletArea = Rectangle( Point(aBulletArea.Left()*nStretchX/100,
974 aBulletArea.Top()),
975 Size(aBulletArea.GetWidth()*nStretchX/100,
976 aBulletArea.GetHeight()) );
978 Paragraph* pPara = pParaList->GetParagraph( nPara );
979 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
980 if ( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) )
982 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
984 Font aBulletFont( ImpCalcBulletFont( nPara ) );
985 // #2338# Use base line
986 BOOL bSymbol = pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
987 aBulletFont.SetAlign( bSymbol ? ALIGN_BOTTOM : ALIGN_BASELINE );
988 Font aOldFont = pOutDev->GetFont();
989 pOutDev->SetFont( aBulletFont );
991 ParagraphInfos aParaInfos = pEditEngine->GetParagraphInfos( nPara );
992 Point aTextPos;
993 if ( !bVertical )
995 // aTextPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
996 aTextPos.Y() = rStartPos.Y() + ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
997 if ( !bRightToLeftPara )
998 aTextPos.X() = rStartPos.X() + aBulletArea.Left();
999 else
1000 aTextPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left();
1002 else
1004 // aTextPos.X() = rStartPos.X() - aBulletArea.Bottom();
1005 aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
1006 aTextPos.Y() = rStartPos.Y() + aBulletArea.Left();
1009 if ( nOrientation )
1011 // Sowohl TopLeft als auch BottomLeft nicht ganz richtig, da
1012 // in EditEngine BaseLine...
1013 double nRealOrientation = nOrientation*F_PI1800;
1014 double nCos = cos( nRealOrientation );
1015 double nSin = sin( nRealOrientation );
1016 Point aRotatedPos;
1017 // Translation...
1018 aTextPos -= rOrigin;
1019 // Rotation...
1020 aRotatedPos.X()=(long) (nCos*aTextPos.X() + nSin*aTextPos.Y());
1021 aRotatedPos.Y()=(long) - (nSin*aTextPos.X() - nCos*aTextPos.Y());
1022 aTextPos = aRotatedPos;
1023 // Translation...
1024 aTextPos += rOrigin;
1025 Font aRotatedFont( aBulletFont );
1026 aRotatedFont.SetOrientation( nOrientation );
1027 pOutDev->SetFont( aRotatedFont );
1030 // #105803# VCL will care for brackets and so on...
1031 ULONG nLayoutMode = pOutDev->GetLayoutMode();
1032 nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG);
1033 if ( bRightToLeftPara )
1034 nLayoutMode |= TEXT_LAYOUT_BIDI_RTL;
1035 pOutDev->SetLayoutMode( nLayoutMode );
1037 if(bStrippingPortions)
1039 const Font aSvxFont(pOutDev->GetFont());
1040 sal_Int32* pBuf = new sal_Int32[ pPara->GetText().Len() ];
1041 pOutDev->GetTextArray( pPara->GetText(), pBuf );
1043 if(bSymbol)
1045 // aTextPos is Bottom, go to Baseline
1046 FontMetric aMetric(pOutDev->GetFontMetric());
1047 aTextPos.Y() -= aMetric.GetDescent();
1050 DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().Len(), pBuf,
1051 aSvxFont, nPara, 0xFFFF, 0xFF, 0, 0, false, false, true, 0, Color(), Color());
1053 delete[] pBuf;
1055 else
1057 pOutDev->DrawText( aTextPos, pPara->GetText() );
1060 pOutDev->SetFont( aOldFont );
1062 else
1064 if ( pFmt->GetBrush()->GetGraphicObject() )
1066 Point aBulletPos;
1067 if ( !bVertical )
1069 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Top();
1070 if ( !bRightToLeftPara )
1071 aBulletPos.X() = rStartPos.X() + aBulletArea.Left();
1072 else
1073 aBulletPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right();
1075 else
1077 aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom();
1078 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left();
1081 if(bStrippingPortions)
1083 if(aDrawBulletHdl.IsSet())
1085 // call something analog to aDrawPortionHdl (if set) and feed it something
1086 // analog to DrawPortionInfo...
1087 // created aDrawBulletHdl, Set/GetDrawBulletHdl.
1088 // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx
1089 DrawBulletInfo aDrawBulletInfo(
1090 *pFmt->GetBrush()->GetGraphicObject(),
1091 aBulletPos,
1092 pPara->aBulSize);
1094 aDrawBulletHdl.Call(&aDrawBulletInfo);
1097 else
1099 // MT: Remove CAST when KA made the Draw-Method const
1100 ((GraphicObject*)pFmt->GetBrush()->GetGraphicObject())->Draw( pOutDev, aBulletPos, pPara->aBulSize );
1106 // Bei zusammengeklappten Absaetzen einen Strich vor den Text malen.
1107 if( pParaList->HasChilds(pPara) && !pParaList->HasVisibleChilds(pPara) &&
1108 !bStrippingPortions && !nOrientation )
1110 long nWidth = pOutDev->PixelToLogic( Size( 10, 0 ) ).Width();
1112 Point aStartPos, aEndPos;
1113 if ( !bVertical )
1115 aStartPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
1116 if ( !bRightToLeftPara )
1117 aStartPos.X() = rStartPos.X() + aBulletArea.Right();
1118 else
1119 aStartPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left();
1120 aEndPos = aStartPos;
1121 aEndPos.X() += nWidth;
1123 else
1125 aStartPos.X() = rStartPos.X() - aBulletArea.Bottom();
1126 aStartPos.Y() = rStartPos.Y() + aBulletArea.Right();
1127 aEndPos = aStartPos;
1128 aEndPos.Y() += nWidth;
1131 const Color& rOldLineColor = pOutDev->GetLineColor();
1132 pOutDev->SetLineColor( Color( COL_BLACK ) );
1133 pOutDev->DrawLine( aStartPos, aEndPos );
1134 pOutDev->SetLineColor( rOldLineColor );
1139 void Outliner::InvalidateBullet( Paragraph* /*pPara*/, ULONG nPara )
1141 DBG_CHKTHIS(Outliner,0);
1143 long nLineHeight = (long)pEditEngine->GetLineHeight((USHORT)nPara );
1144 OutlinerView* pView = aViewList.First();
1145 while( pView )
1147 Point aPos( pView->pEditView->GetWindowPosTopLeft((USHORT)nPara ) );
1148 Rectangle aRect( pView->GetOutputArea() );
1149 aRect.Right() = aPos.X();
1150 aRect.Top() = aPos.Y();
1151 aRect.Bottom() = aPos.Y();
1152 aRect.Bottom() += nLineHeight;
1154 pView->GetWindow()->Invalidate( aRect );
1155 pView = aViewList.Next();
1159 ULONG Outliner::Read( SvStream& rInput, const String& rBaseURL, USHORT eFormat, SvKeyValueIterator* pHTTPHeaderAttrs )
1161 DBG_CHKTHIS(Outliner,0);
1163 BOOL bOldUndo = pEditEngine->IsUndoEnabled();
1164 EnableUndo( FALSE );
1166 BOOL bUpdate = pEditEngine->GetUpdateMode();
1167 pEditEngine->SetUpdateMode( FALSE );
1169 Clear();
1171 ImplBlockInsertionCallbacks( TRUE );
1172 ULONG nRet = pEditEngine->Read( rInput, rBaseURL, (EETextFormat)eFormat, pHTTPHeaderAttrs );
1174 bFirstParaIsEmpty = FALSE;
1176 USHORT nParas = pEditEngine->GetParagraphCount();
1177 pParaList->Clear( TRUE );
1178 USHORT n;
1179 for ( n = 0; n < nParas; n++ )
1181 Paragraph* pPara = new Paragraph( 0 );
1182 pParaList->Insert( pPara, LIST_APPEND );
1184 if ( eFormat == EE_FORMAT_BIN )
1186 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( n );
1187 const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL );
1188 sal_Int16 nDepth = rLevel.GetValue();
1189 ImplInitDepth( n, nDepth, FALSE );
1193 if ( eFormat != EE_FORMAT_BIN )
1195 ImpFilterIndents( 0, nParas-1 );
1198 ImplBlockInsertionCallbacks( FALSE );
1199 pEditEngine->SetUpdateMode( bUpdate );
1200 EnableUndo( bOldUndo );
1202 return nRet;
1206 void Outliner::ImpFilterIndents( ULONG nFirstPara, ULONG nLastPara )
1208 DBG_CHKTHIS(Outliner,0);
1210 BOOL bUpdate = pEditEngine->GetUpdateMode();
1211 pEditEngine->SetUpdateMode( FALSE );
1213 Paragraph* pLastConverted = NULL;
1214 for( ULONG nPara = nFirstPara; nPara <= nLastPara; nPara++ )
1216 Paragraph* pPara = pParaList->GetParagraph( nPara );
1217 if (pPara)
1219 if( ImpConvertEdtToOut( nPara ) )
1221 pLastConverted = pPara;
1223 else if ( pLastConverted )
1225 // Normale Absaetze unter der Ueberschrift anordnen...
1226 pPara->SetDepth( pLastConverted->GetDepth() );
1229 ImplInitDepth( (USHORT)nPara, pPara->GetDepth(), FALSE );
1233 pEditEngine->SetUpdateMode( bUpdate );
1236 SfxUndoManager& Outliner::GetUndoManager()
1238 DBG_CHKTHIS(Outliner,0);
1239 return pEditEngine->GetUndoManager();
1242 void Outliner::ImpTextPasted( ULONG nStartPara, USHORT nCount )
1244 DBG_CHKTHIS(Outliner,0);
1246 BOOL bUpdate = pEditEngine->GetUpdateMode();
1247 pEditEngine->SetUpdateMode( FALSE );
1249 const ULONG nStart = nStartPara;
1251 Paragraph* pPara = pParaList->GetParagraph( nStartPara );
1252 // Paragraph* pLastConverted = NULL;
1253 // bool bFirst = true;
1255 while( nCount && pPara )
1257 if( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT )
1259 nDepthChangedHdlPrevDepth = pPara->GetDepth();
1260 mnDepthChangeHdlPrevFlags = pPara->nFlags;
1262 ImpConvertEdtToOut( nStartPara );
1264 pHdlParagraph = pPara;
1266 if( nStartPara == nStart )
1268 // the existing paragraph has changed depth or flags
1269 if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != mnDepthChangeHdlPrevFlags) )
1270 DepthChangedHdl();
1273 else // EditEngine-Modus
1275 sal_Int16 nDepth = -1;
1276 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (USHORT)nStartPara );
1277 if ( rAttrs.GetItemState( EE_PARA_OUTLLEVEL ) == SFX_ITEM_ON )
1279 const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL );
1280 nDepth = rLevel.GetValue();
1282 if ( nDepth != GetDepth( nStartPara ) )
1283 ImplInitDepth( (USHORT)nStartPara, nDepth, FALSE );
1286 nCount--;
1287 nStartPara++;
1288 pPara = pParaList->GetParagraph( nStartPara );
1291 pEditEngine->SetUpdateMode( bUpdate );
1293 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed");
1296 long Outliner::IndentingPagesHdl( OutlinerView* pView )
1298 DBG_CHKTHIS(Outliner,0);
1299 if( !aIndentingPagesHdl.IsSet() )
1300 return 1;
1301 return aIndentingPagesHdl.Call( pView );
1304 BOOL Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView )
1306 DBG_CHKTHIS(Outliner,0);
1307 // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages
1308 // schon eingestellt sein
1310 // Wenn der erste Absatz auf Ebene 0 liegt darf er auf keinen Fall
1311 // eingerueckt werden, evtl folgen aber weitere auf Ebene 0.
1312 if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) )
1314 if ( nDepthChangedHdlPrevDepth == 1 ) // ist die einzige Seite
1315 return FALSE;
1316 else
1317 pCurView->ImpCalcSelectedPages( FALSE ); // ohne die erste
1319 return (BOOL)IndentingPagesHdl( pCurView );
1323 BOOL Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView )
1325 DBG_CHKTHIS(Outliner,0);
1326 // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages
1327 // schon eingestellt sein
1328 return (BOOL)RemovingPagesHdl( pCurView );
1331 Outliner::Outliner( SfxItemPool* pPool, USHORT nMode )
1332 : nMinDepth( -1 )
1334 DBG_CTOR( Outliner, 0 );
1336 bStrippingPortions = FALSE;
1337 bPasting = FALSE;
1339 nFirstPage = 1;
1340 bBlockInsCallback = FALSE;
1342 nMaxDepth = 9;
1344 pParaList = new ParagraphList;
1345 pParaList->SetVisibleStateChangedHdl( LINK( this, Outliner, ParaVisibleStateChangedHdl ) );
1346 Paragraph* pPara = new Paragraph( 0 );
1347 pParaList->Insert( pPara, LIST_APPEND );
1348 bFirstParaIsEmpty = TRUE;
1350 pEditEngine = new OutlinerEditEng( this, pPool );
1351 pEditEngine->SetBeginMovingParagraphsHdl( LINK( this, Outliner, BeginMovingParagraphsHdl ) );
1352 pEditEngine->SetEndMovingParagraphsHdl( LINK( this, Outliner, EndMovingParagraphsHdl ) );
1353 pEditEngine->SetBeginPasteOrDropHdl( LINK( this, Outliner, BeginPasteOrDropHdl ) );
1354 pEditEngine->SetEndPasteOrDropHdl( LINK( this, Outliner, EndPasteOrDropHdl ) );
1356 Init( nMode );
1359 Outliner::~Outliner()
1361 DBG_DTOR(Outliner,0);
1363 pParaList->Clear( TRUE );
1364 delete pParaList;
1365 delete pEditEngine;
1368 ULONG Outliner::InsertView( OutlinerView* pView, ULONG nIndex )
1370 DBG_CHKTHIS(Outliner,0);
1372 aViewList.Insert( pView, nIndex );
1373 pEditEngine->InsertView( pView->pEditView, (USHORT)nIndex );
1374 return aViewList.GetPos( pView );
1377 OutlinerView* Outliner::RemoveView( OutlinerView* pView )
1379 DBG_CHKTHIS(Outliner,0);
1381 ULONG nPos = aViewList.GetPos( pView );
1382 if ( nPos != LIST_ENTRY_NOTFOUND )
1384 pView->pEditView->HideCursor(); // HACK wg. BugId 10006
1385 pEditEngine->RemoveView( pView->pEditView );
1386 aViewList.Remove( nPos );
1388 return NULL; // MT: return ueberfluessig
1391 OutlinerView* Outliner::RemoveView( ULONG nIndex )
1393 DBG_CHKTHIS(Outliner,0);
1395 EditView* pEditView = pEditEngine->GetView( (USHORT)nIndex );
1396 pEditView->HideCursor(); // HACK wg. BugId 10006
1398 pEditEngine->RemoveView( (USHORT)nIndex );
1399 aViewList.Remove( nIndex );
1400 return NULL; // MT: return ueberfluessig
1404 OutlinerView* Outliner::GetView( ULONG nIndex ) const
1406 DBG_CHKTHIS(Outliner,0);
1407 return aViewList.GetObject( nIndex );
1410 ULONG Outliner::GetViewCount() const
1412 DBG_CHKTHIS(Outliner,0);
1413 return aViewList.Count();
1416 void Outliner::ParagraphInsertedHdl()
1418 DBG_CHKTHIS(Outliner,0);
1419 if( !IsInUndo() )
1420 aParaInsertedHdl.Call( this );
1424 void Outliner::ParagraphRemovingHdl()
1426 DBG_CHKTHIS(Outliner,0);
1427 if( !IsInUndo() )
1428 aParaRemovingHdl.Call( this );
1432 void Outliner::DepthChangedHdl()
1434 DBG_CHKTHIS(Outliner,0);
1435 if( !IsInUndo() )
1436 aDepthChangedHdl.Call( this );
1440 ULONG Outliner::GetAbsPos( Paragraph* pPara )
1442 DBG_CHKTHIS(Outliner,0);
1443 DBG_ASSERT(pPara,"GetAbsPos:No Para");
1444 return pParaList->GetAbsPos( pPara );
1447 ULONG Outliner::GetParagraphCount() const
1449 DBG_CHKTHIS(Outliner,0);
1450 return pParaList->GetParagraphCount();
1453 Paragraph* Outliner::GetParagraph( ULONG nAbsPos ) const
1455 DBG_CHKTHIS(Outliner,0);
1456 return pParaList->GetParagraph( nAbsPos );
1459 BOOL Outliner::HasChilds( Paragraph* pParagraph ) const
1461 DBG_CHKTHIS(Outliner,0);
1462 return pParaList->HasChilds( pParagraph );
1465 BOOL Outliner::ImplHasBullet( USHORT nPara ) const
1467 return GetNumberFormat(nPara) != 0;
1470 const SvxNumberFormat* Outliner::GetNumberFormat( USHORT nPara ) const
1472 const SvxNumberFormat* pFmt = NULL;
1474 Paragraph* pPara = pParaList->GetParagraph( nPara );
1475 if (pPara == NULL)
1476 return NULL;
1478 sal_Int16 nDepth = pPara? pPara->GetDepth() : -1;
1480 if( nDepth >= 0 )
1482 const SvxNumBulletItem& rNumBullet = (const SvxNumBulletItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET );
1483 if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth )
1484 pFmt = rNumBullet.GetNumRule()->Get( nDepth );
1487 return pFmt;
1490 Size Outliner::ImplGetBulletSize( USHORT nPara )
1492 Paragraph* pPara = pParaList->GetParagraph( nPara );
1493 if (!pPara)
1494 return Size();
1496 if( pPara->aBulSize.Width() == -1 )
1498 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1499 DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" );
1501 if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE )
1503 pPara->aBulSize = Size( 0, 0 );
1505 else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1507 String aBulletText = ImplGetBulletText( nPara );
1508 OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1509 Font aBulletFont( ImpCalcBulletFont( nPara ) );
1510 Font aRefFont( pRefDev->GetFont());
1511 pRefDev->SetFont( aBulletFont );
1512 pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText );
1513 pPara->aBulSize.Height() = pRefDev->GetTextHeight();
1514 pRefDev->SetFont( aRefFont );
1516 else
1518 pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() );
1522 return pPara->aBulSize;
1525 void Outliner::ImplCheckParagraphs( USHORT nStart, USHORT nEnd )
1527 DBG_CHKTHIS( Outliner, 0 );
1529 // --> OD 2009-03-10 #i100014#
1530 // assure that the following for-loop does not loop forever
1531 for ( USHORT n = nStart; n < nEnd; n++ )
1532 // <--
1534 Paragraph* pPara = pParaList->GetParagraph( n );
1535 if (pPara)
1537 pPara->Invalidate();
1538 ImplCalcBulletText( n, FALSE, FALSE );
1543 void Outliner::SetRefDevice( OutputDevice* pRefDev )
1545 DBG_CHKTHIS(Outliner,0);
1546 pEditEngine->SetRefDevice( pRefDev );
1547 for ( USHORT n = (USHORT) pParaList->GetParagraphCount(); n; )
1549 Paragraph* pPara = pParaList->GetParagraph( --n );
1550 pPara->Invalidate();
1554 void Outliner::ParaAttribsChanged( USHORT nPara )
1556 DBG_CHKTHIS(Outliner,0);
1558 // Der Outliner hat kein eigenes Undo, wenn Absaetz getrennt/verschmolzen werden.
1559 // Beim ParagraphInserted ist das Attribut EE_PARA_OUTLLEVEL
1560 // ggf. noch nicht eingestellt, dies wird aber benoetigt um die Tiefe
1561 // des Absatzes zu bestimmen.
1563 if( pEditEngine->IsInUndo() )
1565 if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() )
1567 Paragraph* pPara = pParaList->GetParagraph( nPara );
1568 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL );
1569 if ( pPara && pPara->GetDepth() != rLevel.GetValue() )
1571 pPara->SetDepth( rLevel.GetValue() );
1572 ImplCalcBulletText( nPara, TRUE, TRUE );
1578 void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle )
1580 DBG_CHKTHIS(Outliner,0);
1582 // Die EditEngine ruft StyleSheetChanged auch fuer abgeleitete Styles.
1583 // MT: Hier wurde frueher alle Absaetze durch ein ImpRecalcParaAttribs
1584 // gejagt, die die besagte Vorlage haben, warum?
1585 // => Eigentlich kann sich nur die Bullet-Repraesentation aendern...
1587 USHORT nParas = (USHORT)pParaList->GetParagraphCount();
1588 for( USHORT nPara = 0; nPara < nParas; nPara++ )
1590 if ( pEditEngine->GetStyleSheet( nPara ) == pStyle )
1592 ImplCheckNumBulletItem( nPara );
1593 ImplCalcBulletText( nPara, FALSE, FALSE );
1594 // #97333# EditEngine formats changed paragraphs before calling this method,
1595 // so they are not reformatted now and use wrong bullet indent
1596 pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) );
1601 Rectangle Outliner::ImpCalcBulletArea( USHORT nPara, BOOL bAdjust, BOOL bReturnPaperPos )
1603 // Bullet-Bereich innerhalb des Absatzes...
1604 Rectangle aBulletArea;
1606 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1607 if ( pFmt )
1609 Point aTopLeft;
1610 Size aBulletSize( ImplGetBulletSize( nPara ) );
1612 BOOL bOutlineMode = ( pEditEngine->GetControlWord() & EE_CNTRL_OUTLINER ) != 0;
1614 // the ODF attribut text:space-before which holds the spacing to add to the left of the label
1615 const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset();
1617 const SvxLRSpaceItem& rLR = (const SvxLRSpaceItem&) pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE );
1618 aTopLeft.X() = rLR.GetTxtLeft() + rLR.GetTxtFirstLineOfst() + nSpaceBefore;
1620 long nBulletWidth = Max( (long) -rLR.GetTxtFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) );
1621 if ( nBulletWidth < aBulletSize.Width() ) // Bullet macht sich Platz
1622 nBulletWidth = aBulletSize.Width();
1624 if ( bAdjust && !bOutlineMode )
1626 // Bei zentriert/rechtsbuendig anpassen
1627 const SvxAdjustItem& rItem = (const SvxAdjustItem&)pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST );
1628 if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) ||
1629 ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) )
1631 aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth;
1635 // Vertikal:
1636 ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara );
1637 if ( aInfos.bValid )
1639 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // #91076# nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine
1640 aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight
1641 + aInfos.nFirstLineTextHeight / 2
1642 - aBulletSize.Height() / 2;
1643 // ggf. lieber auf der Baseline ausgeben...
1644 if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) )
1646 Font aBulletFont( ImpCalcBulletFont( nPara ) );
1647 if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL )
1649 OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1650 Font aOldFont = pRefDev->GetFont();
1651 pRefDev->SetFont( aBulletFont );
1652 FontMetric aMetric( pRefDev->GetFontMetric() );
1653 // Leading der ersten Zeile...
1654 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent;
1655 aTopLeft.Y() -= aMetric.GetAscent();
1656 pRefDev->SetFont( aOldFont );
1661 // Horizontal:
1662 if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT )
1664 aTopLeft.X() += nBulletWidth - aBulletSize.Width();
1666 else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER )
1668 aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2;
1671 if ( aTopLeft.X() < 0 ) // dann draengeln
1672 aTopLeft.X() = 0;
1674 aBulletArea = Rectangle( aTopLeft, aBulletSize );
1676 if ( bReturnPaperPos )
1678 Size aBulletSize( aBulletArea.GetSize() );
1679 Point aBulletDocPos( aBulletArea.TopLeft() );
1680 aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y();
1681 Point aBulletPos( aBulletDocPos );
1683 if ( IsVertical() )
1685 aBulletPos.Y() = aBulletDocPos.X();
1686 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y();
1687 // Rotate:
1688 aBulletPos.X() -= aBulletSize.Height();
1689 Size aSz( aBulletSize );
1690 aBulletSize.Width() = aSz.Height();
1691 aBulletSize.Height() = aSz.Width();
1693 else if ( pEditEngine->IsRightToLeft( nPara ) )
1695 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width();
1698 aBulletArea = Rectangle( aBulletPos, aBulletSize );
1700 return aBulletArea;
1703 void Outliner::ExpandHdl()
1705 DBG_CHKTHIS(Outliner,0);
1706 aExpandHdl.Call( this );
1709 EBulletInfo Outliner::GetBulletInfo( USHORT nPara )
1711 EBulletInfo aInfo;
1713 aInfo.nParagraph = nPara;
1714 aInfo.bVisible = ImplHasBullet( nPara );
1716 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1717 aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0;
1719 if( pFmt )
1721 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1723 aInfo.aText = ImplGetBulletText( nPara );
1725 if( pFmt->GetBulletFont() )
1726 aInfo.aFont = *pFmt->GetBulletFont();
1728 else if ( pFmt->GetBrush()->GetGraphicObject() )
1730 aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic();
1734 if ( aInfo.bVisible )
1736 aInfo.aBounds = ImpCalcBulletArea( nPara, TRUE, TRUE );
1739 return aInfo;
1742 XubString Outliner::GetText( Paragraph* pParagraph, ULONG nCount ) const
1744 DBG_CHKTHIS(Outliner,0);
1746 XubString aText;
1747 USHORT nStartPara = (USHORT) pParaList->GetAbsPos( pParagraph );
1748 for ( USHORT n = 0; n < nCount; n++ )
1750 aText += pEditEngine->GetText( nStartPara + n );
1751 if ( (n+1) < (USHORT)nCount )
1752 aText += '\n';
1754 return aText;
1757 void Outliner::Remove( Paragraph* pPara, ULONG nParaCount )
1759 DBG_CHKTHIS(Outliner,0);
1761 ULONG nPos = pParaList->GetAbsPos( pPara );
1762 if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) )
1764 Clear();
1766 else
1768 for( USHORT n = 0; n < (USHORT)nParaCount; n++ )
1769 pEditEngine->RemoveParagraph( (USHORT) nPos );
1773 void Outliner::StripPortions()
1775 DBG_CHKTHIS(Outliner,0);
1776 bStrippingPortions = TRUE;
1777 pEditEngine->StripPortions();
1778 bStrippingPortions = FALSE;
1781 // #101498#
1782 void Outliner::DrawingText( const Point& rStartPos, const XubString& rText, USHORT nTextStart, USHORT nTextLen, const sal_Int32* pDXArray,const SvxFont& rFont,
1783 USHORT nPara, USHORT nIndex, BYTE nRightToLeft,
1784 const EEngineData::WrongSpellVector* pWrongSpellVector,
1785 const SvxFieldData* pFieldData,
1786 bool bEndOfLine,
1787 bool bEndOfParagraph,
1788 bool bEndOfBullet,
1789 const ::com::sun::star::lang::Locale* pLocale,
1790 const Color& rOverlineColor,
1791 const Color& rTextLineColor)
1793 DBG_CHKTHIS(Outliner,0);
1795 if(aDrawPortionHdl.IsSet())
1797 // #101498#
1798 DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector,
1799 pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, bEndOfLine, bEndOfParagraph, bEndOfBullet);
1801 aDrawPortionHdl.Call( &aInfo );
1805 long Outliner::RemovingPagesHdl( OutlinerView* pView )
1807 DBG_CHKTHIS(Outliner,0);
1808 return aRemovingPagesHdl.IsSet() ? aRemovingPagesHdl.Call( pView ) : TRUE;
1811 BOOL Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, USHORT _nFirstPage, USHORT nPages )
1813 DBG_CHKTHIS(Outliner,0);
1815 nDepthChangedHdlPrevDepth = nPages;
1816 mnFirstSelPage = _nFirstPage;
1817 pHdlParagraph = 0;
1818 return (BOOL)RemovingPagesHdl( pCurView );
1821 SfxItemSet Outliner::GetParaAttribs( USHORT nPara )
1823 DBG_CHKTHIS(Outliner,0);
1824 return pEditEngine->GetParaAttribs( nPara );
1827 IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara )
1829 DBG_CHKTHIS(Outliner,0);
1831 ULONG nPara = pParaList->GetAbsPos( pPara );
1832 pEditEngine->ShowParagraph( (USHORT)nPara, pPara->IsVisible() );
1834 return 0;
1837 IMPL_LINK( Outliner, BeginMovingParagraphsHdl, MoveParagraphsInfo*, EMPTYARG )
1839 DBG_CHKTHIS(Outliner,0);
1841 if( !IsInUndo() )
1842 GetBeginMovingHdl().Call( this );
1844 return 0;
1847 IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1849 UndoActionStart( EDITUNDO_DRAGANDDROP );
1850 maBeginPasteOrDropHdl.Call(pInfos);
1851 return 0;
1854 IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1856 bPasting = FALSE;
1857 ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1858 maEndPasteOrDropHdl.Call( pInfos );
1859 UndoActionEnd( EDITUNDO_DRAGANDDROP );
1860 return 0;
1863 IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos )
1865 DBG_CHKTHIS(Outliner,0);
1867 pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1868 USHORT nChangesStart = Min( pInfos->nStartPara, pInfos->nDestPara );
1869 USHORT nParas = (USHORT)pParaList->GetParagraphCount();
1870 for ( USHORT n = nChangesStart; n < nParas; n++ )
1871 ImplCalcBulletText( n, FALSE, FALSE );
1873 if( !IsInUndo() )
1874 aEndMovingHdl.Call( this );
1876 return 0;
1879 sal_uInt16 Outliner::ImplGetNumbering( USHORT nPara, const SvxNumberFormat* pParaFmt )
1881 sal_uInt16 nNumber = pParaFmt->GetStart() - 1;
1883 Paragraph* pPara = pParaList->GetParagraph( nPara );
1884 const sal_Int16 nParaDepth = pPara->GetDepth();
1888 pPara = pParaList->GetParagraph( nPara );
1889 const sal_Int16 nDepth = pPara->GetDepth();
1891 // ignore paragraphs that are below our paragraph
1892 if( nDepth > nParaDepth )
1893 continue;
1895 // stop on paragraphs that are above our paragraph
1896 if( nDepth < nParaDepth )
1897 break;
1899 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1900 if( pFmt == 0 ||
1901 pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
1902 pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE )
1903 break; // no number format, or no numbering - stop here
1905 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE );
1907 if( rBulletState.GetValue() )
1908 nNumber += 1;
1910 // same depth, same number format, check for restart
1911 const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue();
1912 if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() )
1914 if( nNumberingStartValue != -1 )
1915 nNumber += nNumberingStartValue - 1;
1916 break;
1919 while( nPara-- );
1921 return nNumber;
1924 void Outliner::ImplCalcBulletText( USHORT nPara, BOOL bRecalcLevel, BOOL bRecalcChilds )
1926 DBG_CHKTHIS(Outliner,0);
1928 Paragraph* pPara = pParaList->GetParagraph( nPara );
1929 USHORT nRelPos = 0xFFFF;
1931 while ( pPara )
1933 XubString aBulletText;
1934 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1935 if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) )
1937 aBulletText += pFmt->GetPrefix();
1938 if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
1940 aBulletText += pFmt->GetBulletChar();
1942 else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE )
1944 aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) );
1946 aBulletText += pFmt->GetSuffix();
1949 if( aBulletText != pPara->GetText() )
1950 pPara->SetText( aBulletText );
1952 pPara->nFlags &= (~PARAFLAG_SETBULLETTEXT);
1954 if ( bRecalcLevel )
1956 if ( nRelPos != 0xFFFF )
1957 nRelPos++;
1959 sal_Int16 nDepth = pPara->GetDepth();
1960 pPara = pParaList->GetParagraph( ++nPara );
1961 if ( !bRecalcChilds )
1963 while ( pPara && ( pPara->GetDepth() > nDepth ) )
1964 pPara = pParaList->GetParagraph( ++nPara );
1967 if ( pPara && ( pPara->GetDepth() < nDepth ) )
1968 pPara = NULL;
1970 else
1972 pPara = NULL;
1977 void Outliner::Clear()
1979 DBG_CHKTHIS(Outliner,0);
1981 if( !bFirstParaIsEmpty )
1983 ImplBlockInsertionCallbacks( TRUE );
1984 pEditEngine->Clear();
1985 pParaList->Clear( TRUE );
1986 pParaList->Insert( new Paragraph( nMinDepth ), LIST_APPEND );
1987 bFirstParaIsEmpty = TRUE;
1988 ImplBlockInsertionCallbacks( FALSE );
1990 else
1992 Paragraph* pPara = pParaList->GetParagraph( 0 );
1993 if(pPara)
1994 pPara->SetDepth( nMinDepth );
1998 void Outliner::SetFlatMode( BOOL bFlat )
2000 DBG_CHKTHIS(Outliner,0);
2002 if( bFlat != pEditEngine->IsFlatMode() )
2004 for ( USHORT nPara = (USHORT)pParaList->GetParagraphCount(); nPara; )
2005 pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1;
2007 pEditEngine->SetFlatMode( bFlat );
2011 String Outliner::ImplGetBulletText( USHORT nPara )
2013 String aRes;
2014 Paragraph* pPara = pParaList->GetParagraph( nPara );
2015 if (pPara)
2017 // MT: Optimierung mal wieder aktivieren...
2018 // if( pPara->nFlags & PARAFLAG_SETBULLETTEXT )
2019 ImplCalcBulletText( nPara, FALSE, FALSE );
2020 aRes = pPara->GetText();
2022 return aRes;
2025 // this is needed for StarOffice Api
2026 void Outliner::SetLevelDependendStyleSheet( USHORT nPara )
2028 SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) );
2029 ImplSetLevelDependendStyleSheet( nPara );
2030 pEditEngine->SetParaAttribs( nPara, aOldAttrs );
2033 SV_IMPL_PTRARR( NotifyList, EENotifyPtr );
2035 void Outliner::ImplBlockInsertionCallbacks( BOOL b )
2037 if ( b )
2039 bBlockInsCallback++;
2041 else
2043 DBG_ASSERT( bBlockInsCallback, "ImplBlockInsertionCallbacks ?!" );
2044 bBlockInsCallback--;
2045 if ( !bBlockInsCallback )
2047 // Call blocked notify events...
2048 while ( pEditEngine->aNotifyCache.Count() )
2050 EENotify* pNotify = pEditEngine->aNotifyCache[0];
2051 // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
2052 pEditEngine->aNotifyCache.Remove( 0 );
2053 pEditEngine->aOutlinerNotifyHdl.Call( pNotify );
2054 delete pNotify;
2060 IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify )
2062 if ( !bBlockInsCallback )
2064 pEditEngine->aOutlinerNotifyHdl.Call( pNotify );
2066 else
2068 EENotify* pNewNotify = new EENotify( *pNotify );
2069 pEditEngine->aNotifyCache.Insert( pNewNotify, pEditEngine->aNotifyCache.Count() );
2072 return 0;
2075 /** sets a link that is called at the beginning of a drag operation at an edit view */
2076 void Outliner::SetBeginDropHdl( const Link& rLink )
2078 pEditEngine->SetBeginDropHdl( rLink );
2081 Link Outliner::GetBeginDropHdl() const
2083 return pEditEngine->GetBeginDropHdl();
2086 /** sets a link that is called at the end of a drag operation at an edit view */
2087 void Outliner::SetEndDropHdl( const Link& rLink )
2089 pEditEngine->SetEndDropHdl( rLink );
2092 Link Outliner::GetEndDropHdl() const
2094 return pEditEngine->GetEndDropHdl();
2097 /** sets a link that is called before a drop or paste operation. */
2098 void Outliner::SetBeginPasteOrDropHdl( const Link& rLink )
2100 maBeginPasteOrDropHdl = rLink;
2103 /** sets a link that is called after a drop or paste operation. */
2104 void Outliner::SetEndPasteOrDropHdl( const Link& rLink )
2106 maEndPasteOrDropHdl = rLink;
2109 void Outliner::SetParaFlag( Paragraph* pPara, sal_uInt16 nFlag )
2111 if( pPara && !pPara->HasFlag( nFlag ) )
2113 if( IsUndoEnabled() && !IsInUndo() )
2114 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) );
2116 pPara->SetFlag( nFlag );
2120 void Outliner::RemoveParaFlag( Paragraph* pPara, sal_uInt16 nFlag )
2122 if( pPara && pPara->HasFlag( nFlag ) )
2124 if( IsUndoEnabled() && !IsInUndo() )
2125 InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags & ~nFlag ) );
2127 pPara->RemoveFlag( nFlag );
2131 bool Outliner::HasParaFlag( const Paragraph* pPara, sal_uInt16 nFlag ) const
2133 return pPara && pPara->HasFlag( nFlag );
2137 sal_Bool DrawPortionInfo::IsRTL() const
2139 if(0xFF == mnBiDiLevel)
2141 // Use Bidi functions from icu 2.0 to calculate if this portion
2142 // is RTL or not.
2143 UErrorCode nError(U_ZERO_ERROR);
2144 UBiDi* pBidi = ubidi_openSized(mrText.Len(), 0, &nError);
2145 nError = U_ZERO_ERROR;
2147 // I do not have this info here. Is it necessary? I'll have to ask MT.
2148 const BYTE nDefaultDir = UBIDI_LTR; //IsRightToLeft( nPara ) ? UBIDI_RTL : UBIDI_LTR;
2150 ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(mrText.GetBuffer()), mrText.Len(), nDefaultDir, NULL, &nError); // UChar != sal_Unicode in MinGW
2151 nError = U_ZERO_ERROR;
2153 // sal_Int32 nCount(ubidi_countRuns(pBidi, &nError));
2155 int32_t nStart(0);
2156 int32_t nEnd;
2157 UBiDiLevel nCurrDir;
2159 ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir);
2161 ubidi_close(pBidi);
2163 // remember on-demand calculated state
2164 ((DrawPortionInfo*)this)->mnBiDiLevel = nCurrDir;
2167 return (1 == (mnBiDiLevel % 2));
2170 // eof