Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <svl/intitem.hxx>
22 : #include <editeng/editeng.hxx>
23 : #include <editeng/editview.hxx>
24 : #include <editeng/editdata.hxx>
25 : #include <editeng/eerdll.hxx>
26 : #include <editeng/lrspitem.hxx>
27 : #include <editeng/fhgtitem.hxx>
28 :
29 : #include <math.h>
30 : #include <svl/style.hxx>
31 : #include <vcl/wrkwin.hxx>
32 : #include <editeng/outliner.hxx>
33 : #include <paralist.hxx>
34 : #include <editeng/outlobj.hxx>
35 : #include <outleeng.hxx>
36 : #include <outlundo.hxx>
37 : #include <editeng/eeitem.hxx>
38 : #include <editeng/editstat.hxx>
39 : #include <editeng/scripttypeitem.hxx>
40 : #include <editeng/editobj.hxx>
41 : #include <svl/itemset.hxx>
42 : #include <svl/whiter.hxx>
43 : #include <vcl/metric.hxx>
44 : #include <editeng/numitem.hxx>
45 : #include <editeng/adjustitem.hxx>
46 : #include <vcl/graph.hxx>
47 : #include <vcl/gdimtf.hxx>
48 : #include <vcl/metaact.hxx>
49 : #include <svtools/grfmgr.hxx>
50 : #include <editeng/svxfont.hxx>
51 : #include <editeng/brushitem.hxx>
52 : #include <svl/itempool.hxx>
53 :
54 : // calculate if it's RTL or not
55 : #include <unicode/ubidi.h>
56 : #include <cassert>
57 : #include <boost/scoped_array.hpp>
58 : using ::std::advance;
59 :
60 :
61 : // Outliner
62 :
63 :
64 221984 : void Outliner::ImplCheckDepth( sal_Int16& rnDepth ) const
65 : {
66 221984 : if( rnDepth < nMinDepth )
67 0 : rnDepth = nMinDepth;
68 221984 : else if( rnDepth > nMaxDepth )
69 0 : rnDepth = nMaxDepth;
70 221984 : }
71 :
72 906 : Paragraph* Outliner::Insert(const OUString& rText, sal_Int32 nAbsPos, sal_Int16 nDepth)
73 : {
74 : DBG_ASSERT(pParaList->GetParagraphCount(),"Insert:No Paras");
75 :
76 : Paragraph* pPara;
77 :
78 906 : ImplCheckDepth( nDepth );
79 :
80 906 : sal_Int32 nParagraphCount = pParaList->GetParagraphCount();
81 906 : if( nAbsPos > nParagraphCount )
82 13 : nAbsPos = nParagraphCount;
83 :
84 906 : if( bFirstParaIsEmpty )
85 : {
86 669 : pPara = pParaList->GetParagraph( 0 );
87 669 : if( pPara->GetDepth() != nDepth )
88 : {
89 669 : nDepthChangedHdlPrevDepth = pPara->GetDepth();
90 669 : mnDepthChangeHdlPrevFlags = pPara->nFlags;
91 669 : pPara->SetDepth( nDepth );
92 669 : pHdlParagraph = pPara;
93 669 : DepthChangedHdl();
94 : }
95 669 : pPara->nFlags |= ParaFlag::HOLDDEPTH;
96 669 : SetText( rText, pPara );
97 : }
98 : else
99 : {
100 237 : bool bUpdate = pEditEngine->GetUpdateMode();
101 237 : pEditEngine->SetUpdateMode( false );
102 237 : ImplBlockInsertionCallbacks( true );
103 237 : pPara = new Paragraph( nDepth );
104 237 : pParaList->Insert( pPara, nAbsPos );
105 237 : pEditEngine->InsertParagraph( nAbsPos, OUString() );
106 : DBG_ASSERT(pPara==pParaList->GetParagraph(nAbsPos),"Insert:Failed");
107 237 : ImplInitDepth( nAbsPos, nDepth, false );
108 237 : pHdlParagraph = pPara;
109 237 : ParagraphInsertedHdl();
110 237 : pPara->nFlags |= ParaFlag::HOLDDEPTH;
111 237 : SetText( rText, pPara );
112 237 : ImplBlockInsertionCallbacks( false );
113 237 : pEditEngine->SetUpdateMode( bUpdate );
114 : }
115 906 : bFirstParaIsEmpty = false;
116 : DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed");
117 906 : return pPara;
118 : }
119 :
120 :
121 437412 : void Outliner::ParagraphInserted( sal_Int32 nPara )
122 : {
123 :
124 437412 : if ( nBlockInsCallback )
125 871584 : return;
126 :
127 3240 : if( bPasting || pEditEngine->IsInUndo() )
128 : {
129 0 : Paragraph* pPara = new Paragraph( -1 );
130 0 : pParaList->Insert( pPara, nPara );
131 0 : if( pEditEngine->IsInUndo() )
132 : {
133 0 : pPara->nFlags = ParaFlag::SETBULLETTEXT;
134 0 : pPara->bVisible = true;
135 0 : const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
136 0 : pPara->SetDepth( rLevel.GetValue() );
137 : }
138 : }
139 : else
140 : {
141 3240 : sal_Int16 nDepth = -1;
142 3240 : Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 );
143 3240 : if ( pParaBefore )
144 3240 : nDepth = pParaBefore->GetDepth();
145 :
146 3240 : Paragraph* pPara = new Paragraph( nDepth );
147 3240 : pParaList->Insert( pPara, nPara );
148 :
149 3240 : if( !pEditEngine->IsInUndo() )
150 : {
151 3240 : ImplCalcBulletText( nPara, true, false );
152 3240 : pHdlParagraph = pPara;
153 3240 : ParagraphInsertedHdl();
154 : }
155 : }
156 : }
157 :
158 421303 : void Outliner::ParagraphDeleted( sal_Int32 nPara )
159 : {
160 :
161 421303 : if ( nBlockInsCallback || ( nPara == EE_PARA_ALL ) )
162 419767 : return;
163 :
164 1536 : Paragraph* pPara = pParaList->GetParagraph( nPara );
165 1536 : if (!pPara)
166 0 : return;
167 :
168 1536 : sal_Int16 nDepth = pPara->GetDepth();
169 :
170 1536 : if( !pEditEngine->IsInUndo() )
171 : {
172 1536 : pHdlParagraph = pPara;
173 1536 : ParagraphRemovingHdl();
174 : }
175 :
176 1536 : pParaList->Remove( nPara );
177 1536 : delete pPara;
178 :
179 1536 : if( !pEditEngine->IsInUndo() && !bPasting )
180 : {
181 1536 : pPara = pParaList->GetParagraph( nPara );
182 1536 : if ( pPara && ( pPara->GetDepth() > nDepth ) )
183 : {
184 0 : ImplCalcBulletText( nPara, true, false );
185 : // Search for next on the this level ...
186 0 : while ( pPara && pPara->GetDepth() > nDepth )
187 0 : pPara = pParaList->GetParagraph( ++nPara );
188 : }
189 :
190 1536 : if ( pPara && ( pPara->GetDepth() == nDepth ) )
191 16 : ImplCalcBulletText( nPara, true, false );
192 : }
193 : }
194 :
195 686318 : void Outliner::Init( sal_uInt16 nMode )
196 : {
197 686318 : nOutlinerMode = nMode;
198 :
199 686318 : Clear();
200 :
201 686318 : EEControlBits nCtrl = pEditEngine->GetControlWord();
202 686318 : nCtrl &= ~EEControlBits(EEControlBits::OUTLINER|EEControlBits::OUTLINER2);
203 :
204 686318 : SetMaxDepth( 9 );
205 :
206 686318 : switch ( ImplGetOutlinerMode() )
207 : {
208 : case OUTLINERMODE_TEXTOBJECT:
209 : case OUTLINERMODE_TITLEOBJECT:
210 658664 : break;
211 :
212 : case OUTLINERMODE_OUTLINEOBJECT:
213 27654 : nCtrl |= EEControlBits::OUTLINER2;
214 27654 : break;
215 : case OUTLINERMODE_OUTLINEVIEW:
216 0 : nCtrl |= EEControlBits::OUTLINER;
217 0 : break;
218 :
219 : default: OSL_FAIL( "Outliner::Init - Invalid Mode!" );
220 : }
221 :
222 686318 : pEditEngine->SetControlWord( nCtrl );
223 :
224 686318 : const bool bWasUndoEnabled(IsUndoEnabled());
225 686318 : EnableUndo(false);
226 686318 : ImplInitDepth( 0, -1, false );
227 686318 : GetUndoManager().Clear();
228 686318 : EnableUndo(bWasUndoEnabled);
229 686318 : }
230 :
231 686318 : void Outliner::SetMaxDepth( sal_Int16 nDepth, bool bCheckParagraphs )
232 : {
233 686318 : if( nMaxDepth != nDepth )
234 : {
235 0 : nMaxDepth = std::min( nDepth, (sal_Int16)(SVX_MAX_NUM-1) );
236 :
237 0 : if( bCheckParagraphs )
238 : {
239 0 : sal_Int32 nParagraphs = pParaList->GetParagraphCount();
240 0 : for ( sal_Int32 nPara = 0; nPara < nParagraphs; nPara++ )
241 : {
242 0 : Paragraph* pPara = pParaList->GetParagraph( nPara );
243 0 : if( pPara && pPara->GetDepth() > nMaxDepth )
244 : {
245 0 : SetDepth( pPara, nMaxDepth );
246 : }
247 : }
248 : }
249 : }
250 686318 : }
251 :
252 5982 : sal_Int16 Outliner::GetDepth( sal_Int32 nPara ) const
253 : {
254 5982 : Paragraph* pPara = pParaList->GetParagraph( nPara );
255 : DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" );
256 5982 : return pPara ? pPara->GetDepth() : -1;
257 : }
258 :
259 2861 : void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth )
260 : {
261 :
262 2861 : ImplCheckDepth( nNewDepth );
263 :
264 2861 : if ( nNewDepth != pPara->GetDepth() )
265 : {
266 2453 : nDepthChangedHdlPrevDepth = pPara->GetDepth();
267 2453 : mnDepthChangeHdlPrevFlags = pPara->nFlags;
268 2453 : pHdlParagraph = pPara;
269 :
270 2453 : sal_Int32 nPara = GetAbsPos( pPara );
271 2453 : ImplInitDepth( nPara, nNewDepth, true );
272 2453 : ImplCalcBulletText( nPara, false, false );
273 :
274 2453 : if ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT )
275 152 : ImplSetLevelDependendStyleSheet( nPara );
276 :
277 2453 : DepthChangedHdl();
278 : }
279 2861 : }
280 :
281 2 : sal_Int16 Outliner::GetNumberingStartValue( sal_Int32 nPara )
282 : {
283 2 : Paragraph* pPara = pParaList->GetParagraph( nPara );
284 : DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
285 2 : return pPara ? pPara->GetNumberingStartValue() : -1;
286 : }
287 :
288 0 : void Outliner::SetNumberingStartValue( sal_Int32 nPara, sal_Int16 nNumberingStartValue )
289 : {
290 0 : Paragraph* pPara = pParaList->GetParagraph( nPara );
291 : DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
292 0 : if( pPara && pPara->GetNumberingStartValue() != nNumberingStartValue )
293 : {
294 0 : if( IsUndoEnabled() && !IsInUndo() )
295 : InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
296 0 : pPara->GetNumberingStartValue(), nNumberingStartValue,
297 0 : pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) );
298 :
299 0 : pPara->SetNumberingStartValue( nNumberingStartValue );
300 0 : ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
301 0 : pEditEngine->SetModified();
302 : }
303 0 : }
304 :
305 10 : bool Outliner::IsParaIsNumberingRestart( sal_Int32 nPara )
306 : {
307 10 : Paragraph* pPara = pParaList->GetParagraph( nPara );
308 : DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" );
309 10 : return pPara && pPara->IsParaIsNumberingRestart();
310 : }
311 :
312 4 : void Outliner::SetParaIsNumberingRestart( sal_Int32 nPara, bool bParaIsNumberingRestart )
313 : {
314 4 : Paragraph* pPara = pParaList->GetParagraph( nPara );
315 : DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" );
316 4 : if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) )
317 : {
318 4 : if( IsUndoEnabled() && !IsInUndo() )
319 : InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
320 8 : pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(),
321 8 : pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) );
322 :
323 4 : pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart );
324 4 : ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
325 4 : pEditEngine->SetModified();
326 : }
327 4 : }
328 :
329 0 : sal_Int32 Outliner::GetBulletsNumberingStatus(
330 : const sal_Int32 nParaStart,
331 : const sal_Int32 nParaEnd ) const
332 : {
333 0 : if ( nParaStart > nParaEnd
334 0 : || nParaEnd >= pParaList->GetParagraphCount() )
335 : {
336 : DBG_ASSERT( false,"<Outliner::GetBulletsNumberingStatus> - unexpected parameter values" );
337 0 : return 2;
338 : }
339 :
340 0 : sal_Int32 nBulletsCount = 0;
341 0 : sal_Int32 nNumberingCount = 0;
342 0 : for (sal_Int32 nPara = nParaStart; nPara <= nParaEnd; ++nPara)
343 : {
344 0 : if ( !pParaList->GetParagraph(nPara) )
345 : {
346 0 : break;
347 : }
348 0 : const SvxNumberFormat* pFmt = GetNumberFormat(nPara);
349 0 : if (!pFmt)
350 : {
351 : // At least, exists one paragraph that has no Bullets/Numbering.
352 0 : break;
353 : }
354 0 : else if ((pFmt->GetNumberingType() == SVX_NUM_BITMAP) || (pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL))
355 : {
356 : // Having Bullets in this paragraph.
357 0 : nBulletsCount++;
358 : }
359 : else
360 : {
361 : // Having Numbering in this paragraph.
362 0 : nNumberingCount++;
363 : }
364 : }
365 :
366 0 : const sal_Int32 nParaCount = nParaEnd - nParaStart + 1;
367 0 : if ( nBulletsCount == nParaCount )
368 : {
369 0 : return 0;
370 : }
371 0 : else if ( nNumberingCount == nParaCount )
372 : {
373 0 : return 1;
374 : }
375 0 : return 2;
376 : }
377 :
378 0 : sal_Int32 Outliner::GetBulletsNumberingStatus() const
379 : {
380 0 : return pParaList->GetParagraphCount() > 0
381 0 : ? GetBulletsNumberingStatus( 0, pParaList->GetParagraphCount()-1 )
382 0 : : 2;
383 : }
384 :
385 111087 : OutlinerParaObject* Outliner::CreateParaObject( sal_Int32 nStartPara, sal_Int32 nCount ) const
386 : {
387 222174 : if ( static_cast<sal_uLong>(nStartPara) + nCount >
388 111087 : static_cast<sal_uLong>(pParaList->GetParagraphCount()) )
389 34849 : nCount = pParaList->GetParagraphCount() - nStartPara;
390 :
391 : // When a new OutlinerParaObject is created because a paragraph is just being deleted,
392 : // it can happen that the ParaList is not updated yet...
393 111087 : if ( ( nStartPara + nCount ) > pEditEngine->GetParagraphCount() )
394 0 : nCount = pEditEngine->GetParagraphCount() - nStartPara;
395 :
396 111087 : if (nCount <= 0)
397 0 : return NULL;
398 :
399 111087 : EditTextObject* pText = pEditEngine->CreateTextObject( nStartPara, nCount );
400 111087 : const bool bIsEditDoc(OUTLINERMODE_TEXTOBJECT == ImplGetOutlinerMode());
401 111087 : ParagraphDataVector aParagraphDataVector(nCount);
402 111087 : const sal_Int32 nLastPara(nStartPara + nCount - 1);
403 :
404 232404 : for(sal_Int32 nPara(nStartPara); nPara <= nLastPara; nPara++)
405 : {
406 121317 : aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara);
407 : }
408 :
409 111087 : OutlinerParaObject* pPObj = new OutlinerParaObject(*pText, aParagraphDataVector, bIsEditDoc);
410 111087 : pPObj->SetOutlinerMode(GetMode());
411 111087 : delete pText;
412 :
413 111087 : return pPObj;
414 : }
415 :
416 30545 : void Outliner::SetText( const OUString& rText, Paragraph* pPara )
417 : {
418 : DBG_ASSERT(pPara,"SetText:No Para");
419 :
420 30545 : bool bUpdate = pEditEngine->GetUpdateMode();
421 30545 : pEditEngine->SetUpdateMode( false );
422 30545 : ImplBlockInsertionCallbacks( true );
423 :
424 30545 : sal_Int32 nPara = pParaList->GetAbsPos( pPara );
425 :
426 30545 : if (rText.isEmpty())
427 : {
428 26922 : pEditEngine->SetText( nPara, rText );
429 26922 : ImplInitDepth( nPara, pPara->GetDepth(), false );
430 : }
431 : else
432 : {
433 3623 : OUString aText(convertLineEnd(rText, LINEEND_LF));
434 :
435 3623 : if (aText.endsWith("\x0A"))
436 0 : aText = aText.copy(0, aText.getLength()-1); // Delete the last break
437 :
438 3623 : sal_Int32 nCount = comphelper::string::getTokenCount(aText, '\x0A');
439 3623 : sal_Int32 nPos = 0;
440 3623 : sal_Int32 nInsPos = nPara+1;
441 12795 : while( nCount > nPos )
442 : {
443 5549 : OUString aStr = aText.getToken( nPos, '\x0A' );
444 :
445 : sal_Int16 nCurDepth;
446 5549 : if( nPos )
447 : {
448 1926 : pPara = new Paragraph( -1 );
449 1926 : nCurDepth = -1;
450 : }
451 : else
452 3623 : nCurDepth = pPara->GetDepth();
453 :
454 : // In the outliner mode, filter the tabs and set the indentation
455 : // about a LRSpaceItem. In EditEngine mode intend over old tabs
456 8261 : if( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) ||
457 2712 : ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ) )
458 : {
459 : // Extract Tabs
460 2837 : sal_uInt16 nTabs = 0;
461 15252 : while ( ( nTabs < aStr.getLength() ) && ( aStr[nTabs] == '\t' ) )
462 9578 : nTabs++;
463 2837 : if ( nTabs )
464 2837 : aStr = aStr.copy(nTabs);
465 :
466 : // Keep depth? (see Outliner::Insert)
467 2837 : if( !(pPara->nFlags & ParaFlag::HOLDDEPTH) )
468 : {
469 2837 : nCurDepth = nTabs-1;
470 2837 : ImplCheckDepth( nCurDepth );
471 2837 : pPara->SetDepth( nCurDepth );
472 2837 : pPara->nFlags &= (~ParaFlag::HOLDDEPTH);
473 : }
474 : }
475 5549 : if( nPos ) // not with the first paragraph
476 : {
477 1926 : pParaList->Insert( pPara, nInsPos );
478 1926 : pEditEngine->InsertParagraph( nInsPos, aStr );
479 1926 : pHdlParagraph = pPara;
480 1926 : ParagraphInsertedHdl();
481 : }
482 : else
483 : {
484 3623 : nInsPos--;
485 3623 : pEditEngine->SetText( nInsPos, aStr );
486 : }
487 5549 : ImplInitDepth( nInsPos, nCurDepth, false );
488 5549 : nInsPos++;
489 5549 : nPos++;
490 9172 : }
491 : }
492 :
493 : DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"SetText failed!");
494 30545 : bFirstParaIsEmpty = false;
495 30545 : ImplBlockInsertionCallbacks( false );
496 30545 : pEditEngine->SetUpdateMode( bUpdate );
497 30545 : }
498 :
499 : // pView == 0 -> Ignore tabs
500 :
501 0 : bool Outliner::ImpConvertEdtToOut( sal_Int32 nPara,EditView* pView)
502 : {
503 :
504 0 : bool bConverted = false;
505 0 : sal_Int32 nTabs = 0;
506 0 : ESelection aDelSel;
507 :
508 0 : OUString aName;
509 0 : OUString aHeading_US( "heading" );
510 0 : OUString aNumber_US( "Numbering" );
511 :
512 0 : OUString aStr( pEditEngine->GetText( nPara ) );
513 0 : const sal_Unicode* pPtr = aStr.getStr();
514 :
515 0 : sal_Int32 nHeadingNumberStart = 0;
516 0 : sal_Int32 nNumberingNumberStart = 0;
517 0 : SfxStyleSheet* pStyle= pEditEngine->GetStyleSheet( nPara );
518 0 : if( pStyle )
519 : {
520 0 : aName = pStyle->GetName();
521 : sal_Int32 nSearch;
522 0 : if ( ( nSearch = aName.indexOf( aHeading_US ) ) != -1 )
523 0 : nHeadingNumberStart = nSearch + aHeading_US.getLength();
524 0 : else if ( ( nSearch = aName.indexOf( aNumber_US ) ) != -1 )
525 0 : nNumberingNumberStart = nSearch + aNumber_US.getLength();
526 : }
527 :
528 0 : if ( nHeadingNumberStart || nNumberingNumberStart )
529 : {
530 : // PowerPoint import ?
531 0 : if( nHeadingNumberStart && ( aStr.getLength() >= 2 ) &&
532 0 : ( pPtr[0] != '\t' ) && ( pPtr[1] == '\t' ) )
533 : {
534 : // Extract Bullet and Tab
535 0 : aDelSel = ESelection( nPara, 0, nPara, 2 );
536 : }
537 :
538 0 : sal_Int32 nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart;
539 0 : OUString aLevel = comphelper::string::stripStart(aName.copy(nPos), ' ');
540 0 : nTabs = aLevel.toInt32();
541 0 : if( nTabs )
542 0 : nTabs--; // Level 0 = "heading 1"
543 0 : bConverted = true;
544 : }
545 : else
546 : {
547 : // filter leading tabs
548 0 : while( *pPtr == '\t' )
549 : {
550 0 : pPtr++;
551 0 : nTabs++;
552 : }
553 : // Remove tabs from the text
554 0 : if( nTabs )
555 0 : aDelSel = ESelection( nPara, 0, nPara, nTabs );
556 : }
557 :
558 0 : if ( aDelSel.HasRange() )
559 : {
560 0 : if ( pView )
561 : {
562 0 : pView->SetSelection( aDelSel );
563 0 : pView->DeleteSelected();
564 : }
565 : else
566 0 : pEditEngine->QuickDelete( aDelSel );
567 : }
568 :
569 0 : const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
570 0 : sal_Int16 nOutlLevel = rLevel.GetValue();
571 :
572 0 : ImplCheckDepth( nOutlLevel );
573 0 : ImplInitDepth( nPara, nOutlLevel, false );
574 :
575 0 : return bConverted;
576 : }
577 :
578 203138 : void Outliner::SetText( const OutlinerParaObject& rPObj )
579 : {
580 :
581 203138 : bool bUpdate = pEditEngine->GetUpdateMode();
582 203138 : pEditEngine->SetUpdateMode( false );
583 :
584 203138 : bool bUndo = pEditEngine->IsUndoEnabled();
585 203138 : EnableUndo( false );
586 :
587 203138 : Init( rPObj.GetOutlinerMode() );
588 :
589 203138 : ImplBlockInsertionCallbacks( true );
590 203138 : pEditEngine->SetText(rPObj.GetTextObject());
591 :
592 203138 : bFirstParaIsEmpty = false;
593 :
594 203138 : pParaList->Clear( true );
595 418518 : for( sal_Int32 nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ )
596 : {
597 215380 : Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(nCurPara));
598 215380 : ImplCheckDepth( pPara->nDepth );
599 :
600 215380 : pParaList->Append(pPara);
601 215380 : ImplCheckNumBulletItem( nCurPara );
602 : }
603 :
604 203138 : ImplCheckParagraphs( 0, pParaList->GetParagraphCount() );
605 :
606 203138 : EnableUndo( bUndo );
607 203138 : ImplBlockInsertionCallbacks( false );
608 203138 : pEditEngine->SetUpdateMode( bUpdate );
609 :
610 : DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed");
611 : DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed");
612 203138 : }
613 :
614 0 : void Outliner::AddText( const OutlinerParaObject& rPObj )
615 : {
616 :
617 0 : bool bUpdate = pEditEngine->GetUpdateMode();
618 0 : pEditEngine->SetUpdateMode( false );
619 :
620 0 : ImplBlockInsertionCallbacks( true );
621 : sal_Int32 nPara;
622 0 : if( bFirstParaIsEmpty )
623 : {
624 0 : pParaList->Clear( true );
625 0 : pEditEngine->SetText(rPObj.GetTextObject());
626 0 : nPara = 0;
627 : }
628 : else
629 : {
630 0 : nPara = pParaList->GetParagraphCount();
631 0 : pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() );
632 : }
633 0 : bFirstParaIsEmpty = false;
634 :
635 0 : for( sal_Int32 n = 0; n < rPObj.Count(); n++ )
636 : {
637 0 : Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(n) );
638 0 : pParaList->Append(pPara);
639 0 : sal_Int32 nP = nPara+n;
640 : DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync");
641 0 : ImplInitDepth( nP, pPara->GetDepth(), false );
642 : }
643 : DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" );
644 :
645 0 : ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
646 :
647 0 : ImplBlockInsertionCallbacks( false );
648 0 : pEditEngine->SetUpdateMode( bUpdate );
649 0 : }
650 :
651 0 : void Outliner::FieldClicked( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos )
652 : {
653 :
654 0 : if ( aFieldClickedHdl.IsSet() )
655 : {
656 0 : EditFieldInfo aFldInfo( this, rField, nPara, nPos );
657 0 : aFldInfo.SetSimpleClick( true );
658 0 : aFieldClickedHdl.Call( &aFldInfo );
659 : }
660 0 : }
661 :
662 :
663 0 : void Outliner::FieldSelected( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos )
664 : {
665 0 : if ( !aFieldClickedHdl.IsSet() )
666 0 : return;
667 :
668 0 : EditFieldInfo aFldInfo( this, rField, nPara, nPos );
669 0 : aFldInfo.SetSimpleClick( false );
670 0 : aFieldClickedHdl.Call( &aFldInfo );
671 : }
672 :
673 :
674 8647 : OUString Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, Color*& rpTxtColor, Color*& rpFldColor )
675 : {
676 8647 : if ( !aCalcFieldValueHdl.IsSet() )
677 0 : return OUString( ' ' );
678 :
679 8647 : EditFieldInfo aFldInfo( this, rField, nPara, nPos );
680 : // The FldColor is preset with COL_LIGHTGRAY.
681 8647 : if ( rpFldColor )
682 132 : aFldInfo.SetFieldColor( *rpFldColor );
683 :
684 8647 : aCalcFieldValueHdl.Call( &aFldInfo );
685 8647 : if ( aFldInfo.GetTextColor() )
686 : {
687 5 : delete rpTxtColor;
688 5 : rpTxtColor = new Color( *aFldInfo.GetTextColor() );
689 : }
690 :
691 8647 : delete rpFldColor;
692 8647 : rpFldColor = aFldInfo.GetFieldColor() ? new Color( *aFldInfo.GetFieldColor() ) : 0;
693 :
694 8647 : return aFldInfo.GetRepresentation();
695 : }
696 :
697 32239 : void Outliner::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
698 : {
699 32239 : Paragraph* pPara = pParaList->GetParagraph( nPara );
700 32239 : if (pPara)
701 : {
702 32239 : pEditEngine->SetStyleSheet( nPara, pStyle );
703 32239 : pPara->nFlags |= ParaFlag::SETBULLETTEXT;
704 32239 : ImplCheckNumBulletItem( nPara );
705 : }
706 32239 : }
707 :
708 1788053 : void Outliner::ImplCheckNumBulletItem( sal_Int32 nPara )
709 : {
710 1788053 : Paragraph* pPara = pParaList->GetParagraph( nPara );
711 1788053 : if (pPara)
712 1788053 : pPara->aBulSize.Width() = -1;
713 1788053 : }
714 :
715 306 : void Outliner::ImplSetLevelDependendStyleSheet( sal_Int32 nPara, SfxStyleSheet* pLevelStyle )
716 : {
717 :
718 : DBG_ASSERT( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ), "SetLevelDependendStyleSheet: Wrong Mode!" );
719 :
720 306 : SfxStyleSheet* pStyle = pLevelStyle;
721 306 : if ( !pStyle )
722 306 : pStyle = GetStyleSheet( nPara );
723 :
724 306 : if ( pStyle )
725 : {
726 306 : sal_Int16 nDepth = GetDepth( nPara );
727 306 : if( nDepth < 0 )
728 92 : nDepth = 0;
729 :
730 306 : OUString aNewStyleSheetName( pStyle->GetName() );
731 306 : aNewStyleSheetName = aNewStyleSheetName.copy( 0, aNewStyleSheetName.getLength()-1 );
732 306 : aNewStyleSheetName += OUString::number( nDepth+1 );
733 306 : SfxStyleSheet* pNewStyle = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( aNewStyleSheetName, pStyle->GetFamily() ));
734 : DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
735 306 : if ( pNewStyle && ( pNewStyle != GetStyleSheet( nPara ) ) )
736 : {
737 95 : SfxItemSet aOldAttrs( GetParaAttribs( nPara ) );
738 95 : SetStyleSheet( nPara, pNewStyle );
739 95 : if ( aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SfxItemState::SET )
740 : {
741 70 : SfxItemSet aAttrs( GetParaAttribs( nPara ) );
742 70 : aAttrs.Put( aOldAttrs.Get( EE_PARA_NUMBULLET ) );
743 70 : SetParaAttribs( nPara, aAttrs );
744 95 : }
745 306 : }
746 : }
747 306 : }
748 :
749 721479 : void Outliner::ImplInitDepth( sal_Int32 nPara, sal_Int16 nDepth, bool bCreateUndo, bool bUndoAction )
750 : {
751 :
752 : DBG_ASSERT( ( nDepth >= nMinDepth ) && ( nDepth <= nMaxDepth ), "ImplInitDepth - Depth is invalid!" );
753 :
754 721479 : Paragraph* pPara = pParaList->GetParagraph( nPara );
755 721479 : if (!pPara)
756 721479 : return;
757 721479 : sal_Int16 nOldDepth = pPara->GetDepth();
758 721479 : pPara->SetDepth( nDepth );
759 :
760 : // For IsInUndo attributes and style do not have to be set, there
761 : // the old values are restored by the EditEngine.
762 721479 : if( !IsInUndo() )
763 : {
764 721479 : bool bUpdate = pEditEngine->GetUpdateMode();
765 721479 : pEditEngine->SetUpdateMode( false );
766 :
767 721479 : bool bUndo = bCreateUndo && IsUndoEnabled();
768 721479 : if ( bUndo && bUndoAction )
769 0 : UndoActionStart( OLUNDO_DEPTH );
770 :
771 721479 : SfxItemSet aAttrs( pEditEngine->GetParaAttribs( nPara ) );
772 721479 : aAttrs.Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nDepth ) );
773 721479 : pEditEngine->SetParaAttribs( nPara, aAttrs );
774 721479 : ImplCheckNumBulletItem( nPara );
775 721479 : ImplCalcBulletText( nPara, false, false );
776 :
777 721479 : if ( bUndo )
778 : {
779 156 : InsertUndo( new OutlinerUndoChangeDepth( this, nPara, nOldDepth, nDepth ) );
780 156 : if ( bUndoAction )
781 0 : UndoActionEnd( OLUNDO_DEPTH );
782 : }
783 :
784 721479 : pEditEngine->SetUpdateMode( bUpdate );
785 : }
786 : }
787 :
788 97141 : void Outliner::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
789 : {
790 :
791 97141 : pEditEngine->SetParaAttribs( nPara, rSet );
792 97141 : }
793 :
794 0 : bool Outliner::Expand( Paragraph* pPara )
795 : {
796 0 : if ( pParaList->HasHiddenChildren( pPara ) )
797 : {
798 0 : OLUndoExpand* pUndo = 0;
799 0 : bool bUndo = IsUndoEnabled() && !IsInUndo();
800 0 : if( bUndo )
801 : {
802 0 : UndoActionStart( OLUNDO_EXPAND );
803 0 : pUndo = new OLUndoExpand( this, OLUNDO_EXPAND );
804 0 : pUndo->pParas = 0;
805 0 : pUndo->nCount = pParaList->GetAbsPos( pPara );
806 : }
807 0 : pHdlParagraph = pPara;
808 0 : bIsExpanding = true;
809 0 : pParaList->Expand( pPara );
810 0 : ExpandHdl();
811 0 : InvalidateBullet(pParaList->GetAbsPos(pPara));
812 0 : if( bUndo )
813 : {
814 0 : InsertUndo( pUndo );
815 0 : UndoActionEnd( OLUNDO_EXPAND );
816 : }
817 0 : return true;
818 : }
819 0 : return false;
820 : }
821 :
822 0 : bool Outliner::Collapse( Paragraph* pPara )
823 : {
824 0 : if ( pParaList->HasVisibleChildren( pPara ) ) // expanded
825 : {
826 0 : OLUndoExpand* pUndo = 0;
827 0 : bool bUndo = false;
828 :
829 0 : if( !IsInUndo() && IsUndoEnabled() )
830 0 : bUndo = true;
831 0 : if( bUndo )
832 : {
833 0 : UndoActionStart( OLUNDO_COLLAPSE );
834 0 : pUndo = new OLUndoExpand( this, OLUNDO_COLLAPSE );
835 0 : pUndo->pParas = 0;
836 0 : pUndo->nCount = pParaList->GetAbsPos( pPara );
837 : }
838 :
839 0 : pHdlParagraph = pPara;
840 0 : bIsExpanding = false;
841 0 : pParaList->Collapse( pPara );
842 0 : ExpandHdl();
843 0 : InvalidateBullet(pParaList->GetAbsPos(pPara));
844 0 : if( bUndo )
845 : {
846 0 : InsertUndo( pUndo );
847 0 : UndoActionEnd( OLUNDO_COLLAPSE );
848 : }
849 0 : return true;
850 : }
851 0 : return false;
852 : }
853 :
854 :
855 3576 : vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const
856 : {
857 3576 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
858 : DBG_ASSERT( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ), "ImpCalcBulletFont: Missing or BitmapBullet!" );
859 :
860 3576 : vcl::Font aStdFont;
861 3576 : if ( !pEditEngine->IsFlatMode() )
862 : {
863 3576 : ESelection aSel( nPara, 0, nPara, 0 );
864 3576 : aStdFont = EditEngine::CreateFontFromItemSet( pEditEngine->GetAttribs( aSel ), GetScriptType( aSel ) );
865 : }
866 : else
867 : {
868 0 : aStdFont = pEditEngine->GetStandardFont( nPara );
869 : }
870 :
871 3576 : vcl::Font aBulletFont;
872 3576 : const vcl::Font *pSourceFont = 0;
873 3576 : if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
874 : {
875 3523 : pSourceFont = pFmt->GetBulletFont();
876 : }
877 :
878 3576 : if (pSourceFont)
879 : {
880 3463 : aBulletFont = *pSourceFont;
881 : }
882 : else
883 : {
884 113 : aBulletFont = aStdFont;
885 113 : aBulletFont.SetUnderline( UNDERLINE_NONE );
886 113 : aBulletFont.SetOverline( UNDERLINE_NONE );
887 113 : aBulletFont.SetStrikeout( STRIKEOUT_NONE );
888 113 : aBulletFont.SetEmphasisMark( EMPHASISMARK_NONE );
889 113 : aBulletFont.SetRelief( RELIEF_NONE );
890 : }
891 :
892 : // Use original scale...
893 : sal_uInt16 nStretchX, nStretchY;
894 3576 : GetGlobalCharStretching(nStretchX, nStretchY);
895 :
896 3576 : sal_uInt16 nScale = pFmt->GetBulletRelSize() * nStretchY / 100;
897 3576 : sal_uLong nScaledLineHeight = aStdFont.GetSize().Height();
898 3576 : nScaledLineHeight *= nScale*10;
899 3576 : nScaledLineHeight /= 1000;
900 :
901 3576 : aBulletFont.SetAlign( ALIGN_BOTTOM );
902 3576 : aBulletFont.SetSize( Size( 0, nScaledLineHeight ) );
903 3576 : bool bVertical = IsVertical();
904 3576 : aBulletFont.SetVertical( bVertical );
905 3576 : aBulletFont.SetOrientation( bVertical ? 2700 : 0 );
906 :
907 3576 : Color aColor( COL_AUTO );
908 3576 : if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EEControlBits::NOCOLORS ) )
909 : {
910 3576 : aColor = pFmt->GetBulletColor();
911 : }
912 :
913 3576 : if ( ( aColor == COL_AUTO ) || ( IsForceAutoColor() ) )
914 3362 : aColor = pEditEngine->GetAutoColor();
915 :
916 3576 : aBulletFont.SetColor( aColor );
917 3576 : return aBulletFont;
918 : }
919 :
920 20095 : void Outliner::PaintBullet( sal_Int32 nPara, const Point& rStartPos,
921 : const Point& rOrigin, short nOrientation, OutputDevice* pOutDev )
922 : {
923 :
924 20095 : bool bDrawBullet = false;
925 20095 : if (pEditEngine)
926 : {
927 20095 : const SfxBoolItem& rBulletState = static_cast<const SfxBoolItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
928 20095 : bDrawBullet = rBulletState.GetValue();
929 : }
930 :
931 20095 : if (bDrawBullet && ImplHasNumberFormat(nPara))
932 : {
933 942 : bool bVertical = IsVertical();
934 :
935 942 : bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara );
936 :
937 942 : Rectangle aBulletArea( ImpCalcBulletArea( nPara, true, false ) );
938 : sal_uInt16 nStretchX, nStretchY;
939 942 : GetGlobalCharStretching(nStretchX, nStretchY);
940 942 : aBulletArea = Rectangle( Point(aBulletArea.Left()*nStretchX/100,
941 942 : aBulletArea.Top()),
942 942 : Size(aBulletArea.GetWidth()*nStretchX/100,
943 3768 : aBulletArea.GetHeight()) );
944 :
945 942 : Paragraph* pPara = pParaList->GetParagraph( nPara );
946 942 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
947 942 : if ( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) )
948 : {
949 942 : if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
950 : {
951 942 : vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
952 : // Use baseline
953 942 : bool bSymbol = pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
954 942 : aBulletFont.SetAlign( bSymbol ? ALIGN_BOTTOM : ALIGN_BASELINE );
955 1884 : vcl::Font aOldFont = pOutDev->GetFont();
956 942 : pOutDev->SetFont( aBulletFont );
957 :
958 942 : ParagraphInfos aParaInfos = pEditEngine->GetParagraphInfos( nPara );
959 942 : Point aTextPos;
960 942 : if ( !bVertical )
961 : {
962 : // aTextPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
963 942 : aTextPos.Y() = rStartPos.Y() + ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
964 942 : if ( !bRightToLeftPara )
965 942 : aTextPos.X() = rStartPos.X() + aBulletArea.Left();
966 : else
967 0 : aTextPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right();
968 : }
969 : else
970 : {
971 : // aTextPos.X() = rStartPos.X() - aBulletArea.Bottom();
972 0 : aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
973 0 : aTextPos.Y() = rStartPos.Y() + aBulletArea.Left();
974 : }
975 :
976 942 : if ( nOrientation )
977 : {
978 : // Both TopLeft and bottom left is not quite correct,
979 : // since in EditEngine baseline ...
980 0 : double nRealOrientation = nOrientation*F_PI1800;
981 0 : double nCos = cos( nRealOrientation );
982 0 : double nSin = sin( nRealOrientation );
983 0 : Point aRotatedPos;
984 : // Translation...
985 0 : aTextPos -= rOrigin;
986 : // Rotation...
987 0 : aRotatedPos.X()=(long) (nCos*aTextPos.X() + nSin*aTextPos.Y());
988 0 : aRotatedPos.Y()=(long) - (nSin*aTextPos.X() - nCos*aTextPos.Y());
989 0 : aTextPos = aRotatedPos;
990 : // Translation...
991 0 : aTextPos += rOrigin;
992 0 : vcl::Font aRotatedFont( aBulletFont );
993 0 : aRotatedFont.SetOrientation( nOrientation );
994 0 : pOutDev->SetFont( aRotatedFont );
995 : }
996 :
997 : // VCL will take care of brackets and so on...
998 942 : ComplexTextLayoutMode nLayoutMode = pOutDev->GetLayoutMode();
999 942 : nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG);
1000 942 : if ( bRightToLeftPara )
1001 0 : nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT | TEXT_LAYOUT_BIDI_STRONG;
1002 942 : pOutDev->SetLayoutMode( nLayoutMode );
1003 :
1004 942 : if(bStrippingPortions)
1005 : {
1006 941 : const vcl::Font aSvxFont(pOutDev->GetFont());
1007 1882 : boost::scoped_array<long> pBuf(new long[ pPara->GetText().getLength() ]);
1008 941 : pOutDev->GetTextArray( pPara->GetText(), pBuf.get() );
1009 :
1010 941 : if(bSymbol)
1011 : {
1012 : // aTextPos is Bottom, go to Baseline
1013 941 : FontMetric aMetric(pOutDev->GetFontMetric());
1014 941 : aTextPos.Y() -= aMetric.GetDescent();
1015 : }
1016 :
1017 1882 : DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), pBuf.get(),
1018 3764 : aSvxFont, nPara, -1, bRightToLeftPara ? 1 : 0, 0, 0, false, false, true, 0, Color(), Color());
1019 : }
1020 : else
1021 : {
1022 1 : pOutDev->DrawText( aTextPos, pPara->GetText() );
1023 : }
1024 :
1025 1884 : pOutDev->SetFont( aOldFont );
1026 : }
1027 : else
1028 : {
1029 0 : if ( pFmt->GetBrush()->GetGraphicObject() )
1030 : {
1031 0 : Point aBulletPos;
1032 0 : if ( !bVertical )
1033 : {
1034 0 : aBulletPos.Y() = rStartPos.Y() + aBulletArea.Top();
1035 0 : if ( !bRightToLeftPara )
1036 0 : aBulletPos.X() = rStartPos.X() + aBulletArea.Left();
1037 : else
1038 0 : aBulletPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right();
1039 : }
1040 : else
1041 : {
1042 0 : aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom();
1043 0 : aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left();
1044 : }
1045 :
1046 0 : if(bStrippingPortions)
1047 : {
1048 0 : if(aDrawBulletHdl.IsSet())
1049 : {
1050 : // call something analog to aDrawPortionHdl (if set) and feed it something
1051 : // analog to DrawPortionInfo...
1052 : // created aDrawBulletHdl, Set/GetDrawBulletHdl.
1053 : // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx
1054 : DrawBulletInfo aDrawBulletInfo(
1055 0 : *pFmt->GetBrush()->GetGraphicObject(),
1056 : aBulletPos,
1057 0 : pPara->aBulSize);
1058 :
1059 0 : aDrawBulletHdl.Call(&aDrawBulletInfo);
1060 : }
1061 : }
1062 : else
1063 : {
1064 : // Remove CAST when KA made the Draw-Method const
1065 0 : const_cast<GraphicObject*>(pFmt->GetBrush()->GetGraphicObject())->Draw( pOutDev, aBulletPos, pPara->aBulSize );
1066 : }
1067 : }
1068 : }
1069 : }
1070 :
1071 : // In case of collapsed subparagraphs paint a line before the text.
1072 2670 : if( pParaList->HasChildren(pPara) && !pParaList->HasVisibleChildren(pPara) &&
1073 942 : !bStrippingPortions && !nOrientation )
1074 : {
1075 0 : long nWidth = pOutDev->PixelToLogic( Size( 10, 0 ) ).Width();
1076 :
1077 0 : Point aStartPos, aEndPos;
1078 0 : if ( !bVertical )
1079 : {
1080 0 : aStartPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
1081 0 : if ( !bRightToLeftPara )
1082 0 : aStartPos.X() = rStartPos.X() + aBulletArea.Right();
1083 : else
1084 0 : aStartPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left();
1085 0 : aEndPos = aStartPos;
1086 0 : aEndPos.X() += nWidth;
1087 : }
1088 : else
1089 : {
1090 0 : aStartPos.X() = rStartPos.X() - aBulletArea.Bottom();
1091 0 : aStartPos.Y() = rStartPos.Y() + aBulletArea.Right();
1092 0 : aEndPos = aStartPos;
1093 0 : aEndPos.Y() += nWidth;
1094 : }
1095 :
1096 0 : const Color& rOldLineColor = pOutDev->GetLineColor();
1097 0 : pOutDev->SetLineColor( Color( COL_BLACK ) );
1098 0 : pOutDev->DrawLine( aStartPos, aEndPos );
1099 0 : pOutDev->SetLineColor( rOldLineColor );
1100 : }
1101 : }
1102 20095 : }
1103 :
1104 0 : void Outliner::InvalidateBullet(sal_Int32 nPara)
1105 : {
1106 0 : long nLineHeight = (long)pEditEngine->GetLineHeight(nPara );
1107 0 : for ( size_t i = 0, n = aViewList.size(); i < n; ++i )
1108 : {
1109 0 : OutlinerView* pView = aViewList[ i ];
1110 0 : Point aPos( pView->pEditView->GetWindowPosTopLeft(nPara ) );
1111 0 : Rectangle aRect( pView->GetOutputArea() );
1112 0 : aRect.Right() = aPos.X();
1113 0 : aRect.Top() = aPos.Y();
1114 0 : aRect.Bottom() = aPos.Y();
1115 0 : aRect.Bottom() += nLineHeight;
1116 :
1117 0 : pView->GetWindow()->Invalidate( aRect );
1118 : }
1119 0 : }
1120 :
1121 0 : sal_uLong Outliner::Read( SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat, SvKeyValueIterator* pHTTPHeaderAttrs )
1122 : {
1123 :
1124 0 : bool bOldUndo = pEditEngine->IsUndoEnabled();
1125 0 : EnableUndo( false );
1126 :
1127 0 : bool bUpdate = pEditEngine->GetUpdateMode();
1128 0 : pEditEngine->SetUpdateMode( false );
1129 :
1130 0 : Clear();
1131 :
1132 0 : ImplBlockInsertionCallbacks( true );
1133 0 : sal_uLong nRet = pEditEngine->Read( rInput, rBaseURL, (EETextFormat)eFormat, pHTTPHeaderAttrs );
1134 :
1135 0 : bFirstParaIsEmpty = false;
1136 :
1137 0 : sal_Int32 nParas = pEditEngine->GetParagraphCount();
1138 0 : pParaList->Clear( true );
1139 0 : for ( sal_Int32 n = 0; n < nParas; n++ )
1140 : {
1141 0 : Paragraph* pPara = new Paragraph( 0 );
1142 0 : pParaList->Append(pPara);
1143 :
1144 0 : if ( eFormat == EE_FORMAT_BIN )
1145 : {
1146 0 : const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( n );
1147 0 : const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( rAttrs.Get( EE_PARA_OUTLLEVEL ));
1148 0 : sal_Int16 nDepth = rLevel.GetValue();
1149 0 : ImplInitDepth( n, nDepth, false );
1150 : }
1151 : }
1152 :
1153 0 : if ( eFormat != EE_FORMAT_BIN )
1154 : {
1155 0 : ImpFilterIndents( 0, nParas-1 );
1156 : }
1157 :
1158 0 : ImplBlockInsertionCallbacks( false );
1159 0 : pEditEngine->SetUpdateMode( bUpdate );
1160 0 : EnableUndo( bOldUndo );
1161 :
1162 0 : return nRet;
1163 : }
1164 :
1165 :
1166 0 : void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara )
1167 : {
1168 :
1169 0 : bool bUpdate = pEditEngine->GetUpdateMode();
1170 0 : pEditEngine->SetUpdateMode( false );
1171 :
1172 0 : Paragraph* pLastConverted = NULL;
1173 0 : for( sal_Int32 nPara = nFirstPara; nPara <= nLastPara; nPara++ )
1174 : {
1175 0 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1176 0 : if (pPara)
1177 : {
1178 0 : if( ImpConvertEdtToOut( nPara ) )
1179 : {
1180 0 : pLastConverted = pPara;
1181 : }
1182 0 : else if ( pLastConverted )
1183 : {
1184 : // Arrange normal paragraphs below the heading ...
1185 0 : pPara->SetDepth( pLastConverted->GetDepth() );
1186 : }
1187 :
1188 0 : ImplInitDepth( nPara, pPara->GetDepth(), false );
1189 : }
1190 : }
1191 :
1192 0 : pEditEngine->SetUpdateMode( bUpdate );
1193 0 : }
1194 :
1195 686402 : ::svl::IUndoManager& Outliner::GetUndoManager()
1196 : {
1197 686402 : return pEditEngine->GetUndoManager();
1198 : }
1199 :
1200 18 : ::svl::IUndoManager* Outliner::SetUndoManager(::svl::IUndoManager* pNew)
1201 : {
1202 18 : return pEditEngine->SetUndoManager(pNew);
1203 : }
1204 :
1205 0 : void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount )
1206 : {
1207 :
1208 0 : bool bUpdate = pEditEngine->GetUpdateMode();
1209 0 : pEditEngine->SetUpdateMode( false );
1210 :
1211 0 : const sal_Int32 nStart = nStartPara;
1212 :
1213 0 : Paragraph* pPara = pParaList->GetParagraph( nStartPara );
1214 :
1215 0 : while( nCount && pPara )
1216 : {
1217 0 : if( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT )
1218 : {
1219 0 : nDepthChangedHdlPrevDepth = pPara->GetDepth();
1220 0 : mnDepthChangeHdlPrevFlags = pPara->nFlags;
1221 :
1222 0 : ImpConvertEdtToOut( nStartPara );
1223 :
1224 0 : pHdlParagraph = pPara;
1225 :
1226 0 : if( nStartPara == nStart )
1227 : {
1228 : // the existing paragraph has changed depth or flags
1229 0 : if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != mnDepthChangeHdlPrevFlags) )
1230 0 : DepthChangedHdl();
1231 : }
1232 : }
1233 : else // EditEngine mode
1234 : {
1235 0 : sal_Int16 nDepth = -1;
1236 0 : const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( nStartPara );
1237 0 : if ( rAttrs.GetItemState( EE_PARA_OUTLLEVEL ) == SfxItemState::SET )
1238 : {
1239 0 : const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( rAttrs.Get( EE_PARA_OUTLLEVEL ) );
1240 0 : nDepth = rLevel.GetValue();
1241 : }
1242 0 : if ( nDepth != GetDepth( nStartPara ) )
1243 0 : ImplInitDepth( nStartPara, nDepth, false );
1244 : }
1245 :
1246 0 : nCount--;
1247 0 : nStartPara++;
1248 0 : pPara = pParaList->GetParagraph( nStartPara );
1249 : }
1250 :
1251 0 : pEditEngine->SetUpdateMode( bUpdate );
1252 :
1253 : DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed");
1254 0 : }
1255 :
1256 0 : long Outliner::IndentingPagesHdl( OutlinerView* pView )
1257 : {
1258 0 : if( !aIndentingPagesHdl.IsSet() )
1259 0 : return 1;
1260 0 : return aIndentingPagesHdl.Call( pView );
1261 : }
1262 :
1263 0 : bool Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView )
1264 : {
1265 : // The selected pages must already be set in advance through
1266 : // ImpCalcSelectedPages
1267 :
1268 : // If the first paragraph is on level 0 it can not indented in any case,
1269 : // possible there might be indentations in the following on the 0 level.
1270 0 : if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) )
1271 : {
1272 0 : if ( nDepthChangedHdlPrevDepth == 1 ) // is the only page
1273 0 : return false;
1274 : else
1275 0 : (void)pCurView->ImpCalcSelectedPages( false ); // without the first
1276 : }
1277 0 : return IndentingPagesHdl( pCurView );
1278 : }
1279 :
1280 :
1281 0 : bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView )
1282 : {
1283 : // The selected pages must already be set in advance through
1284 : // ImpCalcSelectedPages
1285 0 : return RemovingPagesHdl( pCurView );
1286 : }
1287 :
1288 30948 : Outliner::Outliner( SfxItemPool* pPool, sal_uInt16 nMode )
1289 30948 : : nMinDepth( -1 )
1290 : {
1291 :
1292 30948 : bStrippingPortions = false;
1293 30948 : bPasting = false;
1294 :
1295 30948 : nFirstPage = 1;
1296 30948 : nBlockInsCallback = 0;
1297 :
1298 30948 : nMaxDepth = 9;
1299 :
1300 30948 : pParaList = new ParagraphList;
1301 30948 : pParaList->SetVisibleStateChangedHdl( LINK( this, Outliner, ParaVisibleStateChangedHdl ) );
1302 30948 : Paragraph* pPara = new Paragraph( 0 );
1303 30948 : pParaList->Append(pPara);
1304 30948 : bFirstParaIsEmpty = true;
1305 :
1306 30948 : pEditEngine = new OutlinerEditEng( this, pPool );
1307 30948 : pEditEngine->SetBeginMovingParagraphsHdl( LINK( this, Outliner, BeginMovingParagraphsHdl ) );
1308 30948 : pEditEngine->SetEndMovingParagraphsHdl( LINK( this, Outliner, EndMovingParagraphsHdl ) );
1309 30948 : pEditEngine->SetBeginPasteOrDropHdl( LINK( this, Outliner, BeginPasteOrDropHdl ) );
1310 30948 : pEditEngine->SetEndPasteOrDropHdl( LINK( this, Outliner, EndPasteOrDropHdl ) );
1311 :
1312 30948 : Init( nMode );
1313 30948 : }
1314 :
1315 61573 : Outliner::~Outliner()
1316 : {
1317 :
1318 30686 : pParaList->Clear( true );
1319 30686 : delete pParaList;
1320 30686 : delete pEditEngine;
1321 30887 : }
1322 :
1323 95 : size_t Outliner::InsertView( OutlinerView* pView, size_t nIndex )
1324 : {
1325 : size_t ActualIndex;
1326 :
1327 95 : if ( nIndex >= aViewList.size() )
1328 : {
1329 95 : aViewList.push_back( pView );
1330 95 : ActualIndex = aViewList.size() - 1;
1331 : }
1332 : else
1333 : {
1334 0 : ViewList::iterator it = aViewList.begin();
1335 0 : advance( it, nIndex );
1336 0 : ActualIndex = nIndex;
1337 : }
1338 95 : pEditEngine->InsertView( pView->pEditView, nIndex );
1339 95 : return ActualIndex;
1340 : }
1341 :
1342 2 : OutlinerView* Outliner::RemoveView( OutlinerView* pView )
1343 : {
1344 :
1345 2 : for ( ViewList::iterator it = aViewList.begin(); it != aViewList.end(); ++it )
1346 : {
1347 1 : if ( *it == pView )
1348 : {
1349 1 : pView->pEditView->HideCursor(); // HACK
1350 1 : pEditEngine->RemoveView( pView->pEditView );
1351 1 : aViewList.erase( it );
1352 1 : break;
1353 : }
1354 : }
1355 2 : return NULL; // return superfluous
1356 : }
1357 :
1358 10 : OutlinerView* Outliner::RemoveView( size_t nIndex )
1359 : {
1360 :
1361 10 : EditView* pEditView = pEditEngine->GetView( nIndex );
1362 10 : pEditView->HideCursor(); // HACK
1363 :
1364 10 : pEditEngine->RemoveView( nIndex );
1365 :
1366 : {
1367 10 : ViewList::iterator it = aViewList.begin();
1368 10 : advance( it, nIndex );
1369 10 : aViewList.erase( it );
1370 : }
1371 :
1372 10 : return NULL; // return superfluous
1373 : }
1374 :
1375 :
1376 32 : OutlinerView* Outliner::GetView( size_t nIndex ) const
1377 : {
1378 32 : return ( nIndex >= aViewList.size() ) ? NULL : aViewList[ nIndex ];
1379 : }
1380 :
1381 29 : size_t Outliner::GetViewCount() const
1382 : {
1383 29 : return aViewList.size();
1384 : }
1385 :
1386 5403 : void Outliner::ParagraphInsertedHdl()
1387 : {
1388 5403 : if( !IsInUndo() )
1389 5403 : aParaInsertedHdl.Call( this );
1390 5403 : }
1391 :
1392 :
1393 1536 : void Outliner::ParagraphRemovingHdl()
1394 : {
1395 1536 : if( !IsInUndo() )
1396 1536 : aParaRemovingHdl.Call( this );
1397 1536 : }
1398 :
1399 :
1400 3122 : void Outliner::DepthChangedHdl()
1401 : {
1402 3122 : if( !IsInUndo() )
1403 3122 : aDepthChangedHdl.Call( this );
1404 3122 : }
1405 :
1406 :
1407 2453 : sal_Int32 Outliner::GetAbsPos( Paragraph* pPara )
1408 : {
1409 : DBG_ASSERT(pPara,"GetAbsPos:No Para");
1410 2453 : return pParaList->GetAbsPos( pPara );
1411 : }
1412 :
1413 572158 : sal_Int32 Outliner::GetParagraphCount() const
1414 : {
1415 572158 : return pParaList->GetParagraphCount();
1416 : }
1417 :
1418 184136 : Paragraph* Outliner::GetParagraph( sal_Int32 nAbsPos ) const
1419 : {
1420 184136 : return pParaList->GetParagraph( nAbsPos );
1421 : }
1422 :
1423 0 : bool Outliner::HasChildren( Paragraph* pParagraph ) const
1424 : {
1425 0 : return pParaList->HasChildren( pParagraph );
1426 : }
1427 :
1428 383706 : bool Outliner::ImplHasNumberFormat( sal_Int32 nPara ) const
1429 : {
1430 383706 : return GetNumberFormat(nPara) != 0;
1431 : #if 0 // The below code is obviously unreachable
1432 : if ( GetNumberFormat(nPara) )
1433 : {
1434 : const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE );
1435 : return rBulletState.GetValue();
1436 : }
1437 : else
1438 : return false;
1439 : #endif
1440 : }
1441 :
1442 2632853 : const SvxNumberFormat* Outliner::GetNumberFormat( sal_Int32 nPara ) const
1443 : {
1444 2632853 : const SvxNumberFormat* pFmt = NULL;
1445 :
1446 2632853 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1447 2632853 : if (!pPara)
1448 0 : return NULL;
1449 :
1450 2632853 : sal_Int16 nDepth = pPara->GetDepth();
1451 :
1452 2632853 : if( nDepth >= 0 )
1453 : {
1454 53778 : const SvxNumBulletItem& rNumBullet = static_cast<const SvxNumBulletItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET ) );
1455 53778 : if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth )
1456 53778 : pFmt = rNumBullet.GetNumRule()->Get( nDepth );
1457 : }
1458 :
1459 2632853 : return pFmt;
1460 : }
1461 :
1462 4384 : Size Outliner::ImplGetBulletSize( sal_Int32 nPara )
1463 : {
1464 4384 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1465 4384 : if (!pPara)
1466 0 : return Size();
1467 :
1468 4384 : if( pPara->aBulSize.Width() == -1 )
1469 : {
1470 3819 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1471 : DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" );
1472 :
1473 3819 : if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE )
1474 : {
1475 1190 : pPara->aBulSize = Size( 0, 0 );
1476 : }
1477 2629 : else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1478 : {
1479 2623 : OUString aBulletText = ImplGetBulletText( nPara );
1480 2623 : OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1481 5246 : vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
1482 5246 : vcl::Font aRefFont( pRefDev->GetFont());
1483 2623 : pRefDev->SetFont( aBulletFont );
1484 2623 : pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText );
1485 2623 : pPara->aBulSize.Height() = pRefDev->GetTextHeight();
1486 5246 : pRefDev->SetFont( aRefFont );
1487 : }
1488 : else
1489 : {
1490 6 : pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() );
1491 : }
1492 : }
1493 :
1494 4384 : return pPara->aBulSize;
1495 : }
1496 :
1497 1021916 : void Outliner::ImplCheckParagraphs( sal_Int32 nStart, sal_Int32 nEnd )
1498 : {
1499 :
1500 2064641 : for ( sal_Int32 n = nStart; n < nEnd; n++ )
1501 : {
1502 1042725 : Paragraph* pPara = pParaList->GetParagraph( n );
1503 1042725 : if (pPara)
1504 : {
1505 1042725 : pPara->Invalidate();
1506 1042725 : ImplCalcBulletText( n, false, false );
1507 : }
1508 : }
1509 1021916 : }
1510 :
1511 37246 : void Outliner::SetRefDevice( OutputDevice* pRefDev )
1512 : {
1513 37246 : pEditEngine->SetRefDevice( pRefDev );
1514 111738 : for ( sal_Int32 n = pParaList->GetParagraphCount(); n; )
1515 : {
1516 37246 : Paragraph* pPara = pParaList->GetParagraph( --n );
1517 37246 : pPara->Invalidate();
1518 : }
1519 37246 : }
1520 :
1521 596050 : void Outliner::ParaAttribsChanged( sal_Int32 nPara )
1522 : {
1523 :
1524 : // The Outliner does not have an undo of its own, when paragraphs are
1525 : // separated/merged. When ParagraphInserted the attribute EE_PARA_OUTLLEVEL
1526 : // may not be set, this is however needed when the depth of the paragraph
1527 : // is to be determined.
1528 596050 : if( pEditEngine->IsInUndo() )
1529 : {
1530 0 : if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() )
1531 : {
1532 0 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1533 0 : const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
1534 0 : if ( pPara && pPara->GetDepth() != rLevel.GetValue() )
1535 : {
1536 0 : pPara->SetDepth( rLevel.GetValue() );
1537 0 : ImplCalcBulletText( nPara, true, true );
1538 : }
1539 : }
1540 : }
1541 596050 : }
1542 :
1543 0 : void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle )
1544 : {
1545 :
1546 : // The EditEngine calls StyleSheetChanged also for derived styles.
1547 : // Here all the paragraphs, which had the said template, used to be
1548 : // hunted by a ImpRecalcParaAttribs, why?
1549 : // => only the Bullet-representation can really change...
1550 0 : sal_Int32 nParas = pParaList->GetParagraphCount();
1551 0 : for( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
1552 : {
1553 0 : if ( pEditEngine->GetStyleSheet( nPara ) == pStyle )
1554 : {
1555 0 : ImplCheckNumBulletItem( nPara );
1556 0 : ImplCalcBulletText( nPara, false, false );
1557 : // EditEngine formats changed paragraphs before calling this method,
1558 : // so they are not reformatted now and use wrong bullet indent
1559 0 : pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) );
1560 : }
1561 : }
1562 0 : }
1563 :
1564 4384 : Rectangle Outliner::ImpCalcBulletArea( sal_Int32 nPara, bool bAdjust, bool bReturnPaperPos )
1565 : {
1566 : // Bullet area within the paragraph ...
1567 4384 : Rectangle aBulletArea;
1568 :
1569 4384 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1570 4384 : if ( pFmt )
1571 : {
1572 4384 : Point aTopLeft;
1573 4384 : Size aBulletSize( ImplGetBulletSize( nPara ) );
1574 :
1575 4384 : bool bOutlineMode = bool( pEditEngine->GetControlWord() & EEControlBits::OUTLINER );
1576 :
1577 : // the ODF attribute text:space-before which holds the spacing to add to the left of the label
1578 4384 : const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset();
1579 :
1580 4384 : const SvxLRSpaceItem& rLR = static_cast<const SvxLRSpaceItem&>( pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ) );
1581 4384 : aTopLeft.X() = rLR.GetTextLeft() + rLR.GetTextFirstLineOfst() + nSpaceBefore;
1582 :
1583 4384 : long nBulletWidth = std::max( (long) -rLR.GetTextFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) );
1584 4384 : if ( nBulletWidth < aBulletSize.Width() ) // The Bullet creates its space
1585 29 : nBulletWidth = aBulletSize.Width();
1586 :
1587 4384 : if ( bAdjust && !bOutlineMode )
1588 : {
1589 : // Adjust when centered or align right
1590 942 : const SvxAdjustItem& rItem = static_cast<const SvxAdjustItem&>(pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST ));
1591 1884 : if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) ||
1592 942 : ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) )
1593 : {
1594 0 : aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth;
1595 : }
1596 : }
1597 :
1598 : // Vertical:
1599 4384 : ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara );
1600 4384 : if ( aInfos.bValid )
1601 : {
1602 969 : aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine
1603 969 : aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight
1604 969 : + aInfos.nFirstLineTextHeight / 2
1605 969 : - aBulletSize.Height() / 2;
1606 : // may prefer to print out on the baseline ...
1607 969 : if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) )
1608 : {
1609 11 : vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
1610 11 : if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL )
1611 : {
1612 11 : OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1613 11 : vcl::Font aOldFont = pRefDev->GetFont();
1614 11 : pRefDev->SetFont( aBulletFont );
1615 22 : FontMetric aMetric( pRefDev->GetFontMetric() );
1616 : // Leading on the first line ...
1617 11 : aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent;
1618 11 : aTopLeft.Y() -= aMetric.GetAscent();
1619 22 : pRefDev->SetFont( aOldFont );
1620 11 : }
1621 : }
1622 : }
1623 :
1624 : // Horizontal:
1625 4384 : if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT )
1626 : {
1627 0 : aTopLeft.X() += nBulletWidth - aBulletSize.Width();
1628 : }
1629 4384 : else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER )
1630 : {
1631 0 : aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2;
1632 : }
1633 :
1634 4384 : if ( aTopLeft.X() < 0 ) // then push
1635 9 : aTopLeft.X() = 0;
1636 :
1637 4384 : aBulletArea = Rectangle( aTopLeft, aBulletSize );
1638 : }
1639 4384 : if ( bReturnPaperPos )
1640 : {
1641 0 : Size aBulletSize( aBulletArea.GetSize() );
1642 0 : Point aBulletDocPos( aBulletArea.TopLeft() );
1643 0 : aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y();
1644 0 : Point aBulletPos( aBulletDocPos );
1645 :
1646 0 : if ( IsVertical() )
1647 : {
1648 0 : aBulletPos.Y() = aBulletDocPos.X();
1649 0 : aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y();
1650 : // Rotate:
1651 0 : aBulletPos.X() -= aBulletSize.Height();
1652 0 : Size aSz( aBulletSize );
1653 0 : aBulletSize.Width() = aSz.Height();
1654 0 : aBulletSize.Height() = aSz.Width();
1655 : }
1656 0 : else if ( pEditEngine->IsRightToLeft( nPara ) )
1657 : {
1658 0 : aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width();
1659 : }
1660 :
1661 0 : aBulletArea = Rectangle( aBulletPos, aBulletSize );
1662 : }
1663 4384 : return aBulletArea;
1664 : }
1665 :
1666 0 : void Outliner::ExpandHdl()
1667 : {
1668 0 : aExpandHdl.Call( this );
1669 0 : }
1670 :
1671 0 : EBulletInfo Outliner::GetBulletInfo( sal_Int32 nPara )
1672 : {
1673 0 : EBulletInfo aInfo;
1674 :
1675 0 : aInfo.nParagraph = nPara;
1676 0 : aInfo.bVisible = ImplHasNumberFormat( nPara );
1677 :
1678 0 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1679 0 : aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0;
1680 :
1681 0 : if( pFmt )
1682 : {
1683 0 : if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1684 : {
1685 0 : aInfo.aText = ImplGetBulletText( nPara );
1686 :
1687 0 : if( pFmt->GetBulletFont() )
1688 0 : aInfo.aFont = *pFmt->GetBulletFont();
1689 : }
1690 0 : else if ( pFmt->GetBrush()->GetGraphicObject() )
1691 : {
1692 0 : aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic();
1693 : }
1694 : }
1695 :
1696 0 : if ( aInfo.bVisible )
1697 : {
1698 0 : aInfo.aBounds = ImpCalcBulletArea( nPara, true, true );
1699 : }
1700 :
1701 0 : return aInfo;
1702 : }
1703 :
1704 27451 : OUString Outliner::GetText( Paragraph* pParagraph, sal_Int32 nCount ) const
1705 : {
1706 :
1707 27451 : OUString aText;
1708 27451 : sal_Int32 nStartPara = pParaList->GetAbsPos( pParagraph );
1709 54902 : for ( sal_Int32 n = 0; n < nCount; n++ )
1710 : {
1711 27451 : aText += pEditEngine->GetText( nStartPara + n );
1712 27451 : if ( (n+1) < nCount )
1713 0 : aText += "\n";
1714 : }
1715 27451 : return aText;
1716 : }
1717 :
1718 0 : void Outliner::Remove( Paragraph* pPara, sal_Int32 nParaCount )
1719 : {
1720 :
1721 0 : sal_Int32 nPos = pParaList->GetAbsPos( pPara );
1722 0 : if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) )
1723 : {
1724 0 : Clear();
1725 : }
1726 : else
1727 : {
1728 0 : for( sal_Int32 n = 0; n < nParaCount; n++ )
1729 0 : pEditEngine->RemoveParagraph( nPos );
1730 : }
1731 0 : }
1732 :
1733 17483 : void Outliner::StripPortions()
1734 : {
1735 17483 : bStrippingPortions = true;
1736 17483 : pEditEngine->StripPortions();
1737 17483 : bStrippingPortions = false;
1738 17483 : }
1739 :
1740 23789 : void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart,
1741 : sal_Int32 nTextLen, const long* pDXArray,const SvxFont& rFont,
1742 : sal_Int32 nPara, sal_Int32 nIndex, sal_uInt8 nRightToLeft,
1743 : const EEngineData::WrongSpellVector* pWrongSpellVector,
1744 : const SvxFieldData* pFieldData,
1745 : bool bEndOfLine,
1746 : bool bEndOfParagraph,
1747 : bool bEndOfBullet,
1748 : const ::com::sun::star::lang::Locale* pLocale,
1749 : const Color& rOverlineColor,
1750 : const Color& rTextLineColor)
1751 : {
1752 23789 : if(aDrawPortionHdl.IsSet())
1753 : {
1754 : DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector,
1755 23789 : pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, false, 0, bEndOfLine, bEndOfParagraph, bEndOfBullet);
1756 :
1757 23789 : aDrawPortionHdl.Call( &aInfo );
1758 : }
1759 23789 : }
1760 :
1761 0 : void Outliner::DrawingTab( const Point& rStartPos, long nWidth, const OUString& rChar, const SvxFont& rFont,
1762 : sal_Int32 nPara, sal_Int32 nIndex, sal_uInt8 nRightToLeft, bool bEndOfLine, bool bEndOfParagraph,
1763 : const Color& rOverlineColor, const Color& rTextLineColor)
1764 : {
1765 0 : if(aDrawPortionHdl.IsSet())
1766 : {
1767 : DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, nIndex, NULL, NULL,
1768 0 : NULL, NULL, rOverlineColor, rTextLineColor, nRightToLeft, true, nWidth, bEndOfLine, bEndOfParagraph, false);
1769 :
1770 0 : aDrawPortionHdl.Call( &aInfo );
1771 : }
1772 0 : }
1773 :
1774 0 : bool Outliner::RemovingPagesHdl( OutlinerView* pView )
1775 : {
1776 0 : return !aRemovingPagesHdl.IsSet() || aRemovingPagesHdl.Call( pView );
1777 : }
1778 :
1779 0 : bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, sal_Int32 _nFirstPage, sal_Int32 nPages )
1780 : {
1781 :
1782 0 : nDepthChangedHdlPrevDepth = nPages;
1783 0 : mnFirstSelPage = _nFirstPage;
1784 0 : pHdlParagraph = 0;
1785 0 : return RemovingPagesHdl( pCurView );
1786 : }
1787 :
1788 160194 : SfxItemSet Outliner::GetParaAttribs( sal_Int32 nPara )
1789 : {
1790 160194 : return pEditEngine->GetParaAttribs( nPara );
1791 : }
1792 :
1793 0 : IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara )
1794 : {
1795 :
1796 0 : sal_Int32 nPara = pParaList->GetAbsPos( pPara );
1797 0 : pEditEngine->ShowParagraph( nPara, pPara->IsVisible() );
1798 :
1799 0 : return 0;
1800 : }
1801 :
1802 0 : IMPL_LINK_NOARG(Outliner, BeginMovingParagraphsHdl)
1803 : {
1804 :
1805 0 : if( !IsInUndo() )
1806 0 : GetBeginMovingHdl().Call( this );
1807 :
1808 0 : return 0;
1809 : }
1810 :
1811 0 : IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1812 : {
1813 0 : UndoActionStart( EDITUNDO_DRAGANDDROP );
1814 0 : maBeginPasteOrDropHdl.Call(pInfos);
1815 0 : return 0;
1816 : }
1817 :
1818 0 : IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1819 : {
1820 0 : bPasting = false;
1821 0 : ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1822 0 : maEndPasteOrDropHdl.Call( pInfos );
1823 0 : UndoActionEnd( EDITUNDO_DRAGANDDROP );
1824 0 : return 0;
1825 : }
1826 :
1827 0 : IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos )
1828 : {
1829 :
1830 0 : pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1831 0 : sal_Int32 nChangesStart = std::min( pInfos->nStartPara, pInfos->nDestPara );
1832 0 : sal_Int32 nParas = pParaList->GetParagraphCount();
1833 0 : for ( sal_Int32 n = nChangesStart; n < nParas; n++ )
1834 0 : ImplCalcBulletText( n, false, false );
1835 :
1836 0 : if( !IsInUndo() )
1837 0 : aEndMovingHdl.Call( this );
1838 :
1839 0 : return 0;
1840 : }
1841 :
1842 803 : static bool isSameNumbering( const SvxNumberFormat& rN1, const SvxNumberFormat& rN2 )
1843 : {
1844 803 : if( rN1.GetNumberingType() != rN2.GetNumberingType() )
1845 148 : return false;
1846 :
1847 655 : if( rN1.GetNumStr(1) != rN2.GetNumStr(1) )
1848 0 : return false;
1849 :
1850 655 : if( (rN1.GetPrefix() != rN2.GetPrefix()) || (rN1.GetSuffix() != rN2.GetSuffix()) )
1851 0 : return false;
1852 :
1853 655 : return true;
1854 : }
1855 :
1856 439 : sal_uInt16 Outliner::ImplGetNumbering( sal_Int32 nPara, const SvxNumberFormat* pParaFmt )
1857 : {
1858 439 : sal_uInt16 nNumber = pParaFmt->GetStart() - 1;
1859 :
1860 439 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1861 439 : const sal_Int16 nParaDepth = pPara->GetDepth();
1862 :
1863 1191 : do
1864 : {
1865 1339 : pPara = pParaList->GetParagraph( nPara );
1866 1339 : const sal_Int16 nDepth = pPara->GetDepth();
1867 :
1868 : // ignore paragraphs that are below our paragraph or have no numbering
1869 1339 : if( (nDepth > nParaDepth) || (nDepth == -1) )
1870 536 : continue;
1871 :
1872 : // stop on paragraphs that are above our paragraph
1873 803 : if( nDepth < nParaDepth )
1874 0 : break;
1875 :
1876 803 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1877 :
1878 803 : if( pFmt == 0 )
1879 0 : continue; // ignore paragraphs without bullets
1880 :
1881 : // check if numbering less than or equal to pParaFmt
1882 803 : if( !isSameNumbering( *pFmt, *pParaFmt ) || ( pFmt->GetStart() < pParaFmt->GetStart() ) )
1883 148 : break;
1884 :
1885 655 : if ( pFmt->GetStart() > pParaFmt->GetStart() )
1886 : {
1887 0 : nNumber += pFmt->GetStart() - pParaFmt->GetStart();
1888 0 : pParaFmt = pFmt;
1889 : }
1890 :
1891 655 : const SfxBoolItem& rBulletState = static_cast<const SfxBoolItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
1892 :
1893 655 : if( rBulletState.GetValue() )
1894 655 : nNumber += 1;
1895 :
1896 : // same depth, same number format, check for restart
1897 655 : const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue();
1898 655 : if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() )
1899 : {
1900 0 : if( nNumberingStartValue != -1 )
1901 0 : nNumber += nNumberingStartValue - 1;
1902 0 : break;
1903 : }
1904 : }
1905 : while( nPara-- );
1906 :
1907 439 : return nNumber;
1908 : }
1909 :
1910 1772717 : void Outliner::ImplCalcBulletText( sal_Int32 nPara, bool bRecalcLevel, bool bRecalcChildren )
1911 : {
1912 :
1913 1772717 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1914 :
1915 5318164 : while ( pPara )
1916 : {
1917 1772730 : OUString aBulletText;
1918 1772730 : const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1919 1772730 : if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) )
1920 : {
1921 28634 : aBulletText += pFmt->GetPrefix();
1922 28634 : if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
1923 : {
1924 19633 : aBulletText += OUString(pFmt->GetBulletChar());
1925 : }
1926 9001 : else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE )
1927 : {
1928 439 : aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) );
1929 : }
1930 28634 : aBulletText += pFmt->GetSuffix();
1931 : }
1932 :
1933 1772730 : if (!pPara->GetText().equals(aBulletText))
1934 9901 : pPara->SetText( aBulletText );
1935 :
1936 1772730 : pPara->nFlags &= (~ParaFlag::SETBULLETTEXT);
1937 :
1938 1772730 : if ( bRecalcLevel )
1939 : {
1940 3269 : sal_Int16 nDepth = pPara->GetDepth();
1941 3269 : pPara = pParaList->GetParagraph( ++nPara );
1942 3269 : if ( !bRecalcChildren )
1943 : {
1944 6538 : while ( pPara && ( pPara->GetDepth() > nDepth ) )
1945 0 : pPara = pParaList->GetParagraph( ++nPara );
1946 : }
1947 :
1948 3269 : if ( pPara && ( pPara->GetDepth() < nDepth ) )
1949 0 : pPara = NULL;
1950 : }
1951 : else
1952 : {
1953 1769461 : pPara = NULL;
1954 : }
1955 1772730 : }
1956 1772717 : }
1957 :
1958 925000 : void Outliner::Clear()
1959 : {
1960 :
1961 925000 : if( !bFirstParaIsEmpty )
1962 : {
1963 216629 : ImplBlockInsertionCallbacks( true );
1964 216629 : pEditEngine->Clear();
1965 216629 : pParaList->Clear( true );
1966 216629 : pParaList->Append( new Paragraph( nMinDepth ));
1967 216629 : bFirstParaIsEmpty = true;
1968 216629 : ImplBlockInsertionCallbacks( false );
1969 : }
1970 : else
1971 : {
1972 708371 : Paragraph* pPara = pParaList->GetParagraph( 0 );
1973 708371 : if(pPara)
1974 708371 : pPara->SetDepth( nMinDepth );
1975 : }
1976 925000 : }
1977 :
1978 0 : void Outliner::SetFlatMode( bool bFlat )
1979 : {
1980 :
1981 0 : if( bFlat != pEditEngine->IsFlatMode() )
1982 : {
1983 0 : for ( sal_Int32 nPara = pParaList->GetParagraphCount(); nPara; )
1984 0 : pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1;
1985 :
1986 0 : pEditEngine->SetFlatMode( bFlat );
1987 : }
1988 0 : }
1989 :
1990 2623 : OUString Outliner::ImplGetBulletText( sal_Int32 nPara )
1991 : {
1992 2623 : OUString aRes;
1993 2623 : Paragraph* pPara = pParaList->GetParagraph( nPara );
1994 2623 : if (pPara)
1995 : {
1996 : // Enable optimization again ...
1997 : // if( pPara->nFlags & ParaFlag::SETBULLETTEXT )
1998 2623 : ImplCalcBulletText( nPara, false, false );
1999 2623 : aRes = pPara->GetText();
2000 : }
2001 2623 : return aRes;
2002 : }
2003 :
2004 : // this is needed for StarOffice Api
2005 154 : void Outliner::SetLevelDependendStyleSheet( sal_Int32 nPara )
2006 : {
2007 154 : SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) );
2008 154 : ImplSetLevelDependendStyleSheet( nPara );
2009 154 : pEditEngine->SetParaAttribs( nPara, aOldAttrs );
2010 154 : }
2011 :
2012 901098 : void Outliner::ImplBlockInsertionCallbacks( bool b )
2013 : {
2014 901098 : if ( b )
2015 : {
2016 450549 : nBlockInsCallback++;
2017 : }
2018 : else
2019 : {
2020 : DBG_ASSERT( nBlockInsCallback, "ImplBlockInsertionCallbacks ?!" );
2021 450549 : nBlockInsCallback--;
2022 450549 : if ( !nBlockInsCallback )
2023 : {
2024 : // Call blocked notify events...
2025 900624 : while(!pEditEngine->aNotifyCache.empty())
2026 : {
2027 0 : EENotify aNotify(pEditEngine->aNotifyCache.front());
2028 : // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
2029 0 : pEditEngine->aNotifyCache.erase(pEditEngine->aNotifyCache.begin());
2030 0 : pEditEngine->aOutlinerNotifyHdl.Call( &aNotify );
2031 : }
2032 : }
2033 : }
2034 901098 : }
2035 :
2036 0 : IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify )
2037 : {
2038 0 : if ( !nBlockInsCallback )
2039 0 : pEditEngine->aOutlinerNotifyHdl.Call( pNotify );
2040 : else
2041 0 : pEditEngine->aNotifyCache.push_back(*pNotify);
2042 :
2043 0 : return 0;
2044 : }
2045 :
2046 : /** sets a link that is called at the beginning of a drag operation at an edit view */
2047 0 : void Outliner::SetBeginDropHdl( const Link<>& rLink )
2048 : {
2049 0 : pEditEngine->SetBeginDropHdl( rLink );
2050 0 : }
2051 :
2052 : /** sets a link that is called at the end of a drag operation at an edit view */
2053 0 : void Outliner::SetEndDropHdl( const Link<>& rLink )
2054 : {
2055 0 : pEditEngine->SetEndDropHdl( rLink );
2056 0 : }
2057 :
2058 : /** sets a link that is called before a drop or paste operation. */
2059 18 : void Outliner::SetBeginPasteOrDropHdl( const Link<>& rLink )
2060 : {
2061 18 : maBeginPasteOrDropHdl = rLink;
2062 18 : }
2063 :
2064 : /** sets a link that is called after a drop or paste operation. */
2065 18 : void Outliner::SetEndPasteOrDropHdl( const Link<>& rLink )
2066 : {
2067 18 : maEndPasteOrDropHdl = rLink;
2068 18 : }
2069 :
2070 0 : void Outliner::SetParaFlag( Paragraph* pPara, ParaFlag nFlag )
2071 : {
2072 0 : if( pPara && !pPara->HasFlag( nFlag ) )
2073 : {
2074 0 : if( IsUndoEnabled() && !IsInUndo() )
2075 0 : InsertUndo( new OutlinerUndoChangeParaFlags( this, GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) );
2076 :
2077 0 : pPara->SetFlag( nFlag );
2078 : }
2079 0 : }
2080 :
2081 291 : bool Outliner::HasParaFlag( const Paragraph* pPara, ParaFlag nFlag )
2082 : {
2083 291 : return pPara && pPara->HasFlag( nFlag );
2084 : }
2085 :
2086 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|