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