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