xref: /trunk/main/sd/source/ui/view/outlview.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 #include "OutlineView.hxx"
32 #include <memory>
33 #include <editeng/forbiddencharacterstable.hxx>
34 #include <sfx2/progress.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <svx/svxids.hrc>
37 #include "eetext.hxx"
38 #include <editeng/eeitem.hxx>
39 #include <editeng/editstat.hxx>
40 #include <editeng/lrspitem.hxx>
41 #include <svx/svdotext.hxx>
42 #include <sfx2/printer.hxx>
43 #include <sfx2/imagemgr.hxx>
44 #include <sfx2/app.hxx>
45 #include <sfx2/bindings.hxx>
46 #include <svl/itempool.hxx>
47 #include <svl/style.hxx>
48 #include <svx/svdorect.hxx>
49 #include <svx/svdundo.hxx>
50 #include <svl/brdcst.hxx>
51 #include <vcl/msgbox.hxx>
52 #include <editeng/adjitem.hxx>
53 #include <editeng/tstpitem.hxx>
54 #include <editeng/lspcitem.hxx>
55 #include <editeng/numitem.hxx>
56 #include <editeng/outlobj.hxx>
57 #include <editeng/numitem.hxx>
58 #include <editeng/editeng.hxx>
59 
60 // #97766#
61 #include <editeng/editobj.hxx>
62 #include <editeng/editund2.hxx>
63 
64 #include <editeng/editview.hxx>
65 #include <editeng/svxfont.hxx>
66 #include <editeng/fhgtitem.hxx>
67 
68 #include "DrawDocShell.hxx"
69 #include "drawdoc.hxx"
70 #include "Window.hxx"
71 #include "sdpage.hxx"
72 #include "pres.hxx"
73 #include "OutlineViewShell.hxx"
74 #include "app.hrc"
75 #include "glob.hrc"
76 #include "sdresid.hxx"
77 #include "Outliner.hxx"
78 #include "strings.hrc"
79 #include "EventMultiplexer.hxx"
80 #include "ViewShellBase.hxx"
81 #include "undo/undoobjects.hxx"
82 #include "undo/undomanager.hxx"
83 #include "stlsheet.hxx"
84 
85 using ::rtl::OUString;
86 using namespace ::com::sun::star::uno;
87 using namespace ::com::sun::star::frame;
88 
89 namespace sd {
90 
91 // Breite: DIN A 4,  zwei Raender zu je 1 cm
92 #define OUTLINE_PAPERWIDTH 19000
93 
94 // beim Seitenmanipulation Fortschrittsanzeige, wenn mehr Seiten betroffen
95 // sind als:
96 #define PROCESS_WITH_PROGRESS_THRESHOLD  5
97 
98 struct SdParaAndPos
99 {
100     Paragraph* pPara;
101     sal_uInt16     nPos;
102 };
103 
104 TYPEINIT1( OutlineView, ::sd::View );
105 
106 /*************************************************************************
107 |*
108 |* Konstruktor
109 |*
110 \************************************************************************/
111 
112 OutlineView::OutlineView( DrawDocShell* pDocSh, ::Window* pWindow, OutlineViewShell* pOutlineViewSh)
113 : ::sd::View(pDocSh->GetDoc(), pWindow, pOutlineViewSh)
114 , mpOutlineViewShell(pOutlineViewSh)
115 , mpOutliner( mpDoc->GetOutliner(sal_True) )
116 , mpOldParaOrder(NULL)
117 , mpSelectedParas(NULL)
118 , mnPagesToProcess(0)
119 , mnPagesProcessed(0)
120 , mbFirstPaint(sal_True)
121 , mpProgress(NULL)
122 , mbHighContrastMode( false )
123 , maDocColor( COL_WHITE )
124 , mnPageNumberWidthPixel( 0 )
125 , maLRSpaceItem( 0, 0, 2000, 0, EE_PARA_OUTLLRSPACE )
126 {
127     sal_Bool bInitOutliner = sal_False;
128 
129     if (mpOutliner->GetViewCount() == 0)
130     {
131         // Outliner initialisieren: Referenz-Device setzen
132         bInitOutliner = sal_True;
133         mpOutliner->Init( OUTLINERMODE_OUTLINEVIEW );
134 /*
135         SfxStyleSheet* pTitleSheet = mpDoc->GetSdPage( 0, PK_STANDARD )->GetStyleSheetForPresObj( PRESOBJ_TITLE );
136 
137         if ( pTitleSheet )
138         {
139             // set title symbol (level 0)
140             SvxNumBulletItem aNumBulletItem( (const SvxNumBulletItem&) pTitleSheet->GetItemSet().Get(EE_PARA_NUMBULLET) );
141             SvxNumRule aNumRule(* aNumBulletItem.GetNumRule());
142             SvxNumberFormat aFormat( aNumRule.GetLevel(0));
143             Font    aBulletFont;
144             const Font* pFont = aFormat.GetBulletFont();
145             if ( pFont )                                        // if available take font size and color from style
146                 aBulletFont = *pFont;
147             else
148             {
149                 aBulletFont.SetColor( COL_AUTO );
150                 aBulletFont.SetHeight( 1552 );
151             }
152             aBulletFont.SetCharSet(RTL_TEXTENCODING_MS_1252);   // and replacing other values by standard
153             aBulletFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" )) );
154             aBulletFont.SetWeight(WEIGHT_NORMAL);
155             aBulletFont.SetUnderline(UNDERLINE_NONE);
156             aBulletFont.SetStrikeout(STRIKEOUT_NONE);
157             aBulletFont.SetItalic(ITALIC_NONE);
158             aBulletFont.SetOutline(sal_False);
159             aBulletFont.SetShadow(sal_False);
160             aFormat.SetBulletFont( &aBulletFont );
161             aFormat.SetBulletChar( 0xE011 );  // StarBats: 0xF000 + 114
162             mpOutliner->OverwriteLevel0Bullet( aFormat );
163         }
164 */
165         mpOutliner->SetRefDevice( SD_MOD()->GetRefDevice( *pDocSh ) );
166         sal_uLong nWidth = OUTLINE_PAPERWIDTH;
167         mpOutliner->SetPaperSize(Size(nWidth, 400000000));
168     }
169 
170     // View in Outliner einfuegen
171     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
172     {
173         mpOutlinerView[nView] = NULL;
174     }
175 
176     mpOutlinerView[0] = new OutlinerView(mpOutliner, pWindow);
177     Rectangle aNullRect;
178     mpOutlinerView[0]->SetOutputArea(aNullRect);
179     mpOutliner->SetUpdateMode(sal_False);
180     mpOutliner->InsertView(mpOutlinerView[0], LIST_APPEND);
181 
182     onUpdateStyleSettings( true );
183 
184     if (bInitOutliner)
185     {
186         // Outliner mit Inhalt fuellen
187         FillOutliner();
188     }
189 
190     Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
191     mpOutlineViewShell->GetViewShellBase().GetEventMultiplexer()->AddEventListener(
192         aLink,
193         tools::EventMultiplexerEvent::EID_CURRENT_PAGE
194         | tools::EventMultiplexerEvent::EID_PAGE_ORDER);
195 
196     LanguageType eLang = mpOutliner->GetDefaultLanguage();
197     maPageNumberFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 );
198     maPageNumberFont.SetHeight( 500 );
199 
200     maBulletFont.SetColor( COL_AUTO );
201     maBulletFont.SetHeight( 1000 );
202     maBulletFont.SetCharSet(RTL_TEXTENCODING_MS_1252);   // and replacing other values by standard
203     maBulletFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" )) );
204     maBulletFont.SetWeight(WEIGHT_NORMAL);
205     maBulletFont.SetUnderline(UNDERLINE_NONE);
206     maBulletFont.SetStrikeout(STRIKEOUT_NONE);
207     maBulletFont.SetItalic(ITALIC_NONE);
208     maBulletFont.SetOutline(sal_False);
209     maBulletFont.SetShadow(sal_False);
210 
211 
212     Reference<XFrame> xFrame (mpOutlineViewShell->GetViewShellBase().GetFrame()->GetTopFrame().GetFrameInterface(), UNO_QUERY);
213 
214     const OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( ".uno:ShowSlide" ));
215     maSlideImage = GetImage( xFrame, aSlotURL, true, false /* todo, hc mode */ );
216 
217     // Tell undo manager of the document about the undo manager of the
218     // outliner, so that the former can synchronize with the later.
219     sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
220     if (pDocUndoMgr != NULL)
221         pDocUndoMgr->SetLinkedUndoManager(&mpOutliner->GetUndoManager());
222 }
223 
224 /*************************************************************************
225 |*
226 |* Destruktor, Links restaurieren, Outliner leeren
227 |*
228 \************************************************************************/
229 
230 OutlineView::~OutlineView()
231 {
232     DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::~OutlineView(), prior drag operation not finished correctly!" );
233 
234     Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
235     mpOutlineViewShell->GetViewShellBase().GetEventMultiplexer()->RemoveEventListener( aLink );
236     DisconnectFromApplication();
237 
238     if( mpProgress )
239         delete mpProgress;
240 
241     // OutlinerViews abmelden und zerstoeren
242     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
243     {
244         if (mpOutlinerView[nView] != NULL)
245         {
246             mpOutliner->RemoveView( mpOutlinerView[nView] );
247             delete mpOutlinerView[nView];
248             mpOutlinerView[nView] = NULL;
249         }
250     }
251 
252     if (mpOutliner->GetViewCount() == 0)
253     {
254         // Outliner deinitialisieren: Farbdarstellung einschalten
255         ResetLinks();
256         sal_uLong nCntrl = mpOutliner->GetControlWord();
257         mpOutliner->SetUpdateMode(sal_False); // sonst wird bei SetControlWord gezeichnet
258         mpOutliner->SetControlWord(nCntrl & ~EE_CNTRL_NOCOLORS);
259         SvtAccessibilityOptions aOptions;
260         mpOutliner->ForceAutoColor( aOptions.GetIsAutomaticFontColor() );
261         mpOutliner->Clear();
262     }
263 
264     DBG_ASSERT(!mpSelectedParas, "Absatzliste nicht geloescht");
265     DBG_ASSERT(!mpOldParaOrder, "Absatzliste nicht geloescht");
266 }
267 
268 
269 
270 
271 void OutlineView::ConnectToApplication (void)
272 {
273     mpOutlineViewShell->GetActiveWindow()->GrabFocus();
274     Application::AddEventListener(LINK(this, OutlineView, AppEventListenerHdl));
275 }
276 
277 
278 
279 
280 void OutlineView::DisconnectFromApplication (void)
281 {
282     Application::RemoveEventListener(LINK(this, OutlineView, AppEventListenerHdl));
283 }
284 
285 
286 
287 
288 /*************************************************************************
289 |*
290 |* Paint-Methode
291 |*
292 \************************************************************************/
293 
294 void OutlineView::Paint(const Rectangle& rRect, ::sd::Window* pWin)
295 {
296     OutlinerView* pOlView = GetViewByWindow(pWin);
297 
298     if (pOlView)
299     {
300         pOlView->HideCursor();
301         pOlView->Paint(rRect);
302 
303         pOlView->ShowCursor(mbFirstPaint);
304 
305 /*
306         if( mnPageNumberWidthPixel == 0 )
307             GetPageNumberWidthPixel();
308 
309         const sal_uLong nParaCount = pOlView->GetOutliner()->GetParagraphCount();
310         EditView& rEditView = pOlView->GetEditView();
311 
312         Font aOldFont( pWin->GetFont() );
313 
314         const String aBulletStr( sal_Unicode( 0xE011 ) );
315         pWin->SetFont( maBulletFont);
316         sal_Int32 nBulletWidth = pWin->GetTextWidth(aBulletStr);
317 
318         sal_Int32 nPage = 1;
319         for( sal_uLong nPara = 0; nPara < nParaCount; nPara++ )
320         {
321             Paragraph* pPara = pOlView->GetOutliner()->GetParagraph( nPara );
322             if( pPara->HasFlag( PARAFLAG_ISPAGE ) )
323             {
324                 pWin->SetFont( maPageNumberFont );
325                 const String aStr( String::CreateFromInt32( nPage++ ) );
326                 Point aPos( rEditView.GetWindowPosTopLeft( (sal_uInt16)nPara ) );
327 
328                 sal_Int32 nNumberOffset = pWin->PixelToLogic( Point(mnPageNumberWidthPixel, 0) ).X() - nBulletWidth;
329                 sal_Int32 nLineHeight = pOlView->GetOutliner()->GetLineHeight( nPara, 0 );
330 
331                 aPos.X() = nNumberOffset;
332 
333                 Point aPoint( aPos.X() - pWin->GetTextWidth( aStr ), aPos.Y() + ( nLineHeight - maPageNumberFont.GetHeight()) / 2 );
334                 pWin->DrawText( aPoint, aStr );
335 
336                 aPoint.X() = aPos.X();
337                 aPoint.Y() = aPos.Y() +( nLineHeight - maBulletFont.GetHeight()) / 2;
338                 pWin->SetFont( maBulletFont );
339                 pWin->DrawText( aPoint, aBulletStr );
340             }
341         }
342 
343         pWin->SetFont( aOldFont );
344 */
345         mbFirstPaint = sal_False;
346     }
347 }
348 
349 void OutlineView::InvalidateSlideNumberArea()
350 {
351 /*
352     for( sal_Int16 nView = 0; nView < MAX_OUTLINERVIEWS; ++nView )
353     {
354         if (mpOutlinerView[nView] != NULL)
355         {
356             ::Window* pWindow = mpOutlinerView[nView]->GetWindow();
357             if( pWindow )
358             {
359                 Rectangle aRect( Point(0,0), pWindow->GetOutputSize() );
360                 aRect.nRight = aRect.nLeft + pWindow->PixelToLogic( Point( mnPageNumberWidthPixel, 0 ) ).X() * 2;
361 
362                 pWindow->Invalidate(aRect);
363             }
364         }
365     }
366 */
367 }
368 
369 /*************************************************************************
370 |*
371 |* Fenster-Groesse hat sich geaendert
372 |*
373 \************************************************************************/
374 
375 void OutlineView::AdjustPosSizePixel(const Point &,const Size &,::sd::Window*)
376 {
377 }
378 
379 /*************************************************************************
380 |*
381 |* ein Fenster hinzufuegen
382 |*
383 \************************************************************************/
384 
385 void OutlineView::AddWindowToPaintView(OutputDevice* pWin)
386 {
387     sal_Bool bAdded = sal_False;
388     sal_Bool bValidArea = sal_False;
389     Rectangle aOutputArea;
390     const Color aWhiteColor( COL_WHITE );
391     sal_uInt16 nView = 0;
392 
393     while (nView < MAX_OUTLINERVIEWS && !bAdded)
394     {
395         if (mpOutlinerView[nView] == NULL)
396         {
397             mpOutlinerView[nView] = new OutlinerView(mpOutliner, dynamic_cast< ::sd::Window* >(pWin));
398             mpOutlinerView[nView]->SetBackgroundColor( aWhiteColor );
399             mpOutliner->InsertView(mpOutlinerView[nView], LIST_APPEND);
400             bAdded = sal_True;
401 
402             if (bValidArea)
403             {
404                 mpOutlinerView[nView]->SetOutputArea(aOutputArea);
405             }
406         }
407         else if (!bValidArea)
408         {
409             aOutputArea = mpOutlinerView[nView]->GetOutputArea();
410             bValidArea = sal_True;
411         }
412 
413         nView++;
414     }
415 
416     // weisser Hintergrund im Outliner
417     pWin->SetBackground( Wallpaper( aWhiteColor ) );
418 
419     ::sd::View::AddWindowToPaintView(pWin);
420 }
421 
422 /*************************************************************************
423 |*
424 |* ein Fenster entfernen
425 |*
426 \************************************************************************/
427 
428 void OutlineView::DeleteWindowFromPaintView(OutputDevice* pWin)
429 {
430     sal_Bool bRemoved = sal_False;
431     sal_uInt16 nView = 0;
432     ::Window* pWindow;
433 
434     while (nView < MAX_OUTLINERVIEWS && !bRemoved)
435     {
436         if (mpOutlinerView[nView] != NULL)
437         {
438             pWindow = mpOutlinerView[nView]->GetWindow();
439 
440             if (pWindow == pWin)
441             {
442                 mpOutliner->RemoveView( mpOutlinerView[nView] );
443                 delete mpOutlinerView[nView];
444                 mpOutlinerView[nView] = NULL;
445                 bRemoved = sal_True;
446             }
447         }
448 
449         nView++;
450     }
451 
452     ::sd::View::DeleteWindowFromPaintView(pWin);
453 }
454 
455 /*************************************************************************
456 |*
457 |* Zeiger der dem Fenster entsprechenden OutlinerView zurueckgeben.
458 |*
459 \************************************************************************/
460 
461 OutlinerView* OutlineView::GetViewByWindow (::Window* pWin) const
462 {
463     OutlinerView* pOlView = NULL;
464     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
465     {
466         if (mpOutlinerView[nView] != NULL)
467         {
468             if ( pWin == mpOutlinerView[nView]->GetWindow() )
469             {
470                 pOlView = mpOutlinerView[nView];
471             }
472         }
473     }
474     return (pOlView);
475 }
476 
477 
478 /*************************************************************************
479 |*
480 |* Ermittelt den Titel vor einem beliebigen Absatz.
481 |*
482 \************************************************************************/
483 
484 Paragraph* OutlineView::GetPrevTitle(const Paragraph* pPara)
485 {
486     sal_Int32 nPos = mpOutliner->GetAbsPos(const_cast<Paragraph*>(pPara));
487 
488     if (nPos > 0)
489     {
490         while(nPos)
491         {
492             pPara = mpOutliner->GetParagraph(--nPos);
493             if( mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
494             {
495                 return const_cast< Paragraph* >( pPara );
496             }
497         }
498 
499     }
500     return NULL;
501 }
502 
503 /*************************************************************************
504 |*
505 |* Ermittelt den Titel nach einem beliebigen Absatz.
506 |*
507 \************************************************************************/
508 
509 Paragraph* OutlineView::GetNextTitle(const Paragraph* pPara)
510 {
511     Paragraph* pResult = const_cast< Paragraph* >( pPara );
512 
513     sal_Int32 nPos = mpOutliner->GetAbsPos(pResult);
514 
515     do
516     {
517         pResult = mpOutliner->GetParagraph(++nPos);
518         if( pResult && mpOutliner->HasParaFlag(pResult, PARAFLAG_ISPAGE) )
519             return pResult;
520     }
521     while( pResult );
522 
523     return NULL;
524 }
525 
526 /*************************************************************************
527 |*
528 |* Handler fuer das Einfuegen von Seiten (Absaetzen)
529 |*
530 \************************************************************************/
531 
532 IMPL_LINK( OutlineView, ParagraphInsertedHdl, ::Outliner *, pOutliner )
533 {
534 //  DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::ParagraphInsertedHdl(), model change without undo?!" );
535 
536     // we get calls to this handler during binary insert of drag and drop contents but
537     // we ignore it here and handle it later in OnEndPasteOrDrop()
538     if( maDragAndDropModelGuard.get() == 0 )
539     {
540         OutlineViewPageChangesGuard aGuard(this);
541 
542         Paragraph* pPara = pOutliner->GetHdlParagraph();
543 
544         sal_uInt16 nAbsPos = (sal_uInt16)mpOutliner->GetAbsPos( pPara );
545 
546         UpdateParagraph( nAbsPos );
547 
548         if( (nAbsPos == 0) || mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) || mpOutliner->HasParaFlag(mpOutliner->GetParagraph( nAbsPos-1 ), PARAFLAG_ISPAGE) )
549         {
550             InsertSlideForParagraph( pPara );
551             InvalidateSlideNumberArea();
552         }
553     }
554 
555     return 0;
556 }
557 
558 /** creates and inserts an empty slide for the given paragraph */
559 SdPage* OutlineView::InsertSlideForParagraph( Paragraph* pPara )
560 {
561     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::InsertSlideForParagraph(), model change without undo?!" );
562 
563     OutlineViewPageChangesGuard aGuard(this);
564 
565     mpOutliner->SetParaFlag( pPara, PARAFLAG_ISPAGE );
566     // wieviele Titel sind vor dem neuen Titelabsatz?
567     sal_uLong nExample = 0L;            // Position der "Vorbild"seite
568     sal_uLong nTarget  = 0L;            // Einfuegeposition
569     while(pPara)
570     {
571         pPara = GetPrevTitle(pPara);
572         if (pPara)
573             nTarget++;
574     }
575 
576 
577     // was der Outliner nicht kann, muss hier wieder wettgemacht werden:
578     // wenn VOR dem ersten Absatz ein neuer Absatz mit RETURN erzeugt wird,
579     // meldet der Outliner den bereits bestehenden (jetzt nach unten
580     // gerutschten) Absatz als neuen Absatz; nicht darauf reinfallen!
581     if (nTarget == 1)
582     {
583         String aTest(mpOutliner->GetText( mpOutliner->GetParagraph( 0 ) ));
584         if (aTest.Len() == 0)
585         {
586             nTarget = 0;
587         }
588     }
589 
590 
591     // "Vorbild"seite ist - wenn vorhanden - die Vorgaengerseite
592     if (nTarget > 0)
593     {
594         nExample = nTarget - 1;
595 
596         sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PK_STANDARD );
597         if( nExample >= nPageCount )
598             nExample = nPageCount - 1;
599     }
600 
601     /**********************************************************************
602     * Es wird stets zuerst eine Standardseite und dann eine
603     * Notizseite erzeugt. Es ist sichergestellt, dass auf eine
604     * Standardseite stets die zugehoerige Notizseite folgt.
605     * Vorangestellt ist genau eine Handzettelseite
606     **********************************************************************/
607 
608     // diese Seite hat Vorbildfunktion
609     SdPage* pExample = (SdPage*)mpDoc->GetSdPage((sal_uInt16)nExample, PK_STANDARD);
610     SdPage* pPage = (SdPage*)mpDoc->AllocPage(sal_False);
611 
612     pPage->SetLayoutName(pExample->GetLayoutName());
613 
614     // einfuegen (Seite)
615     mpDoc->InsertPage(pPage, (sal_uInt16)(nTarget) * 2 + 1);
616     if( isRecordingUndo() )
617         AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pPage));
618 
619     // der Standardseite eine Masterpage zuweisen
620     pPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
621 
622     // Seitengroesse setzen
623     pPage->SetSize(pExample->GetSize());
624     pPage->SetBorder( pExample->GetLftBorder(),
625                       pExample->GetUppBorder(),
626                       pExample->GetRgtBorder(),
627                       pExample->GetLwrBorder() );
628 
629     // neue Praesentationsobjekte anlegen (auf <Titel> oder
630     // <Titel mit Untertitel> folgt <Titel mit Gliederung>, ansonsten
631     // wird das Layout von der Vorgaengerseite uebernommen)
632     AutoLayout eAutoLayout = pExample->GetAutoLayout();
633     if (eAutoLayout == AUTOLAYOUT_TITLE ||
634         eAutoLayout == AUTOLAYOUT_ONLY_TITLE)
635     {
636         pPage->SetAutoLayout(AUTOLAYOUT_ENUM, sal_True);
637     }
638     else
639     {
640         pPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
641     }
642 
643     /**********************************************************************
644     |* jetzt die Notizseite
645     \*********************************************************************/
646     pExample = (SdPage*)mpDoc->GetSdPage((sal_uInt16)nExample, PK_NOTES);
647     SdPage* pNotesPage = (SdPage*)mpDoc->AllocPage(sal_False);
648 
649     pNotesPage->SetLayoutName(pExample->GetLayoutName());
650 
651     pNotesPage->SetPageKind(PK_NOTES);
652 
653     // einfuegen (Notizseite)
654     mpDoc->InsertPage(pNotesPage, (sal_uInt16)(nTarget) * 2 + 2);
655     if( isRecordingUndo() )
656         AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pNotesPage));
657 
658     // der Notizseite eine Masterpage zuweisen
659     pNotesPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
660 
661     // Seitengroesse setzen, es muss bereits eine Seite vorhanden sein
662     pNotesPage->SetSize(pExample->GetSize());
663     pNotesPage->SetBorder( pExample->GetLftBorder(),
664                            pExample->GetUppBorder(),
665                            pExample->GetRgtBorder(),
666                            pExample->GetLwrBorder() );
667 
668     // neue Praesentationsobjekte anlegen
669     pNotesPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
670 
671     mpOutliner->UpdateFields();
672 
673     return pPage;
674 }
675 
676 /*************************************************************************
677 |*
678 |* Handler fuer das Loeschen von Seiten (Absaetzen)
679 |*
680 \************************************************************************/
681 
682 IMPL_LINK( OutlineView, ParagraphRemovingHdl, ::Outliner *, pOutliner )
683 {
684     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::ParagraphRemovingHdl(), model change without undo?!" );
685 
686     OutlineViewPageChangesGuard aGuard(this);
687 
688     Paragraph* pPara = pOutliner->GetHdlParagraph();
689     if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) )
690     {
691         // wieviele Titel sind vor dem fraglichen Titelabsatz?
692         sal_uLong nPos = 0L;
693         while(pPara)
694         {
695             pPara = GetPrevTitle(pPara);
696             if (pPara) nPos++;
697         }
698 
699         // Seite und Notizseite loeschen
700         sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
701         SdrPage* pPage = mpDoc->GetPage(nAbsPos);
702         if( isRecordingUndo() )
703             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
704         mpDoc->RemovePage(nAbsPos);
705 
706         nAbsPos = (sal_uInt16)nPos * 2 + 1;
707         pPage = mpDoc->GetPage(nAbsPos);
708         if( isRecordingUndo() )
709             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
710         mpDoc->RemovePage(nAbsPos);
711 
712         // ggfs. Fortschrittsanzeige
713         if (mnPagesToProcess)
714         {
715             mnPagesProcessed++;
716 
717             if(mpProgress)
718                 mpProgress->SetState(mnPagesProcessed);
719 
720             if (mnPagesProcessed == mnPagesToProcess)
721             {
722                 if(mpProgress)
723                 {
724                     delete mpProgress;
725                     mpProgress = NULL;
726                 }
727                 mnPagesToProcess = 0;
728                 mnPagesProcessed = 0;
729             }
730         }
731         pOutliner->UpdateFields();
732     }
733 
734     InvalidateSlideNumberArea();
735 
736     return 0;
737 }
738 
739 /*************************************************************************
740 |*
741 |* Handler fuer das Aendern der Einruecktiefe von Absaetzen (macht ggfs.
742 |* das Einfuegen oder Loeschen von Seiten notwendig)
743 |*
744 \************************************************************************/
745 
746 IMPL_LINK( OutlineView, DepthChangedHdl, ::Outliner *, pOutliner )
747 {
748     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::DepthChangedHdl(), no undo for model change?!" );
749 
750     OutlineViewPageChangesGuard aGuard(this);
751 
752     Paragraph* pPara = pOutliner->GetHdlParagraph();
753     if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) == 0) )
754     {
755         // the current paragraph is transformed into a slide
756 
757         mpOutliner->SetDepth( pPara, -1 );
758 
759         // werden da etwa mehrere Level-1-Absaetze auf Level 0 gebracht und
760         // wir sollten eine Fortschrittsanzeige oder Eieruhr aufsetzen und
761         // haben es noch nicht getan?
762         if (mnPagesToProcess == 0)
763         {
764             Window*       pActWin = mpOutlineViewShell->GetActiveWindow();
765             OutlinerView* pOlView = GetViewByWindow(pActWin);
766             List*         pList   = pOlView->CreateSelectionList();
767 
768             Paragraph*    pParagraph   = (Paragraph*)pList->First();
769             while (pParagraph)
770             {
771                 if( !pOutliner->HasParaFlag( pParagraph, PARAFLAG_ISPAGE ) && (pOutliner->GetDepth( (sal_uInt16) pOutliner->GetAbsPos( pParagraph ) ) <= 0) )
772                     mnPagesToProcess++;
773                 pParagraph = (Paragraph*)pList->Next();
774             }
775 
776             mnPagesToProcess++; // der Absatz, der jetzt schon auf Level 0
777                                 // steht, gehoert auch dazu
778             mnPagesProcessed = 0;
779 
780             if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
781             {
782                 if( mpProgress )
783                     delete mpProgress;
784 
785                 const String aStr(SdResId(STR_CREATE_PAGES));
786                 mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
787             }
788             else
789             {
790                 mpDocSh->SetWaitCursor( sal_True );
791             }
792             delete pList;
793         }
794 
795         ParagraphInsertedHdl(pOutliner);
796 
797         mnPagesProcessed++;
798 
799         // muss eine Fortschrittsanzeige gepflegt werden?
800         if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
801         {
802             if (mpProgress)
803                 mpProgress->SetState(mnPagesProcessed);
804         }
805 
806         // war das die letzte Seite?
807         if (mnPagesProcessed == mnPagesToProcess)
808         {
809             if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD && mpProgress)
810             {
811                 delete mpProgress;
812                 mpProgress = NULL;
813             }
814             else
815                 mpDocSh->SetWaitCursor( sal_False );
816 
817             mnPagesToProcess = 0;
818             mnPagesProcessed = 0;
819         }
820         pOutliner->UpdateFields();
821     }
822     else if( !pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) != 0) )
823     {
824         // the paragraph was a page but now becomes a normal paragraph
825 
826         // how many titles are before the title paragraph in question?
827         sal_uLong nPos = 0L;
828         Paragraph* pParagraph = pPara;
829         while(pParagraph)
830         {
831             pParagraph = GetPrevTitle(pParagraph);
832             if (pParagraph)
833                 nPos++;
834         }
835         // Seite und Notizseite loeschen
836 
837         sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
838         SdrPage* pPage = mpDoc->GetPage(nAbsPos);
839         if( isRecordingUndo() )
840             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
841         mpDoc->RemovePage(nAbsPos);
842 
843         nAbsPos = (sal_uInt16)nPos * 2 + 1;
844         pPage = mpDoc->GetPage(nAbsPos);
845         if( isRecordingUndo() )
846             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
847         mpDoc->RemovePage(nAbsPos);
848 
849         pPage = GetPageForParagraph( pPara );
850 
851         mpOutliner->SetDepth( pPara, (pPage && (static_cast<SdPage*>(pPage)->GetAutoLayout() == AUTOLAYOUT_TITLE)) ?  -1 : 0 );
852 
853         // ggfs. Fortschrittsanzeige
854         if (mnPagesToProcess)
855         {
856             mnPagesProcessed++;
857             if (mpProgress)
858                 mpProgress->SetState(mnPagesProcessed);
859 
860             if (mnPagesProcessed == mnPagesToProcess)
861             {
862                 if(mpProgress)
863                 {
864                     delete mpProgress;
865                     mpProgress = NULL;
866                 }
867                 mnPagesToProcess = 0;
868                 mnPagesProcessed = 0;
869             }
870         }
871         pOutliner->UpdateFields();
872     }
873     else if ( (pOutliner->GetPrevDepth() == 1) && ( pOutliner->GetDepth( (sal_uInt16) pOutliner->GetAbsPos( pPara ) ) == 2 ) )
874     {
875         // wieviele Titel sind vor dem fraglichen Titelabsatz?
876         sal_Int32 nPos = -1L;
877 
878         Paragraph* pParagraph = pPara;
879         while(pParagraph)
880         {
881             pParagraph = GetPrevTitle(pParagraph);
882             if (pParagraph)
883                 nPos++;
884         }
885 
886         if(nPos >= 0)
887         {
888             SdPage*pPage = (SdPage*)mpDoc->GetSdPage( (sal_uInt16) nPos, PK_STANDARD);
889 
890             if(pPage && pPage->GetPresObj(PRESOBJ_TEXT))
891                 pOutliner->SetDepth( pPara, 0 );
892         }
893 
894     }
895     // wieviele Titel sind vor dem fraglichen Titelabsatz?
896     sal_Int32 nPos = -1L;
897 
898     Paragraph* pTempPara = pPara;
899     while(pTempPara)
900     {
901         pTempPara = GetPrevTitle(pTempPara);
902         if (pTempPara)
903             nPos++;
904     }
905 
906     if( nPos >= 0 )
907     {
908         SdPage* pPage = (SdPage*) mpDoc->GetSdPage( (sal_uInt16) nPos, PK_STANDARD );
909 
910         if( pPage )
911         {
912             SfxStyleSheet* pStyleSheet = NULL;
913             sal_uLong nPara = pOutliner->GetAbsPos( pPara );
914             sal_Int16 nDepth = pOutliner->GetDepth( (sal_uInt16) nPara );
915             bool bSubTitle = pPage->GetPresObj(PRESOBJ_TEXT) != NULL;
916 
917             if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
918             {
919                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE );
920             }
921             else if( bSubTitle )
922             {
923                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TEXT );
924             }
925             else
926             {
927                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_OUTLINE );
928 
929                 if( nDepth > 0 )
930                 {
931                     String aNewStyleSheetName( pStyleSheet->GetName() );
932                     aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 );
933                     aNewStyleSheetName += String::CreateFromInt32( nDepth+1 );
934                     SfxStyleSheetBasePool* pStylePool = mpDoc->GetStyleSheetPool();
935                     pStyleSheet = (SfxStyleSheet*) pStylePool->Find( aNewStyleSheetName, pStyleSheet->GetFamily() );
936                 }
937             }
938 
939             // before we set the style sheet we need to preserve the bullet item
940             // since all items will be deleted while setting a new style sheet
941             SfxItemSet aOldAttrs( pOutliner->GetParaAttribs( (sal_uInt16)nPara ) );
942 
943             pOutliner->SetStyleSheet( nPara, pStyleSheet );
944 
945             // restore the old bullet item but not if the style changed
946             if ( pOutliner->GetPrevDepth() != -1 && nDepth != -1 &&
947                  aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON )
948             {
949                 SfxItemSet aAttrs( pOutliner->GetParaAttribs( (sal_uInt16)nPara ) );
950                 aAttrs.Put( *aOldAttrs.GetItem( EE_PARA_NUMBULLET ) );
951                 pOutliner->SetParaAttribs( (sal_uInt16)nPara, aAttrs );
952             }
953         }
954     }
955 
956     InvalidateSlideNumberArea();
957 
958     return 0;
959 }
960 
961 /*************************************************************************
962 |*
963 |* Handler fuer StatusEvents
964 |*
965 \************************************************************************/
966 
967 IMPL_LINK( OutlineView, StatusEventHdl, EditStatus *, EMPTYARG )
968 {
969     ::sd::Window*   pWin = mpOutlineViewShell->GetActiveWindow();
970     OutlinerView*   pOutlinerView = GetViewByWindow(pWin);
971     Rectangle     aVis          = pOutlinerView->GetVisArea();
972 
973 //    sal_uLong nWidth = ((SdPage*)mpDoc->GetSdPage(0, PK_STANDARD))->GetSize().Width();
974     sal_uLong nWidth = OUTLINE_PAPERWIDTH;
975     Rectangle aText = Rectangle(Point(0,0),
976                                    Size(nWidth,
977                                         mpOutliner->GetTextHeight()));
978     Rectangle aWin(Point(0,0), pWin->GetOutputSizePixel());
979     aWin = pWin->PixelToLogic(aWin);
980 
981     if (!aVis.IsEmpty())        // nicht beim Oeffnen
982     {
983         aText.Bottom() += aWin.GetHeight();
984 
985         mpOutlineViewShell->InitWindows(Point(0,0), aText.GetSize(),
986                                        Point(aVis.TopLeft()));
987         mpOutlineViewShell->UpdateScrollBars();
988     }
989 
990     InvalidateSlideNumberArea();
991     return 0;
992 }
993 
994 IMPL_LINK( OutlineView, BeginDropHdl, void *, EMPTYARG )
995 {
996     DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::BeginDropHdl(), prior drag operation not finished correctly!" );
997 
998     maDragAndDropModelGuard.reset( new OutlineViewModelChangeGuard( *this ) );
999     return 0;
1000 }
1001 
1002 IMPL_LINK( OutlineView, EndDropHdl, void *, EMPTYARG )
1003 {
1004     maDragAndDropModelGuard.reset(0);
1005     InvalidateSlideNumberArea();
1006     return 0;
1007 }
1008 
1009 /*************************************************************************
1010 |*
1011 |* Handler fuer den Beginn einer Absatzverschiebung
1012 |*
1013 \************************************************************************/
1014 
1015 IMPL_LINK( OutlineView, BeginMovingHdl, ::Outliner *, pOutliner )
1016 {
1017     DBG_ASSERT(!mpSelectedParas, "Absatzliste nicht geloescht");
1018     DBG_ASSERT(!mpOldParaOrder, "Absatzliste nicht geloescht");
1019 
1020     OutlineViewPageChangesGuard aGuard(this);
1021 
1022     mpOldParaOrder = new List;
1023 
1024     // Liste der selektierten Titelabsaetze
1025     mpSelectedParas = mpOutlinerView[0]->CreateSelectionList();
1026     Paragraph* pPara = static_cast<Paragraph*>(mpSelectedParas->First());
1027     while (pPara)
1028     {
1029         if( !pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1030         {
1031             mpSelectedParas->Remove();
1032             pPara = static_cast<Paragraph*>(mpSelectedParas->GetCurObject());
1033         }
1034         else
1035         {
1036             pPara = static_cast<Paragraph*>(mpSelectedParas->Next());
1037         }
1038     }
1039 
1040     // Die zu den selektierten Absaetzen auf Ebene 0 gehoerenden Seiten
1041     // selektieren
1042     sal_uInt16 nPos = 0;
1043     sal_uLong nParaPos = 0;
1044     pPara = pOutliner->GetParagraph( 0 );
1045 
1046     while(pPara)
1047     {
1048         if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )                     // eine Seite?
1049         {
1050             mpOldParaOrder->Insert(pPara, LIST_APPEND);
1051             SdPage* pPage = mpDoc->GetSdPage(nPos, PK_STANDARD);
1052             pPage->SetSelected(sal_False);
1053             if (mpSelectedParas->Seek(pPara))            // selektiert?
1054             {
1055                 pPage->SetSelected(sal_True);
1056             }
1057             nPos++;
1058         }
1059         pPara = pOutliner->GetParagraph( ++nParaPos );
1060     }
1061 
1062     return 0;
1063 }
1064 
1065 /*************************************************************************
1066 |*
1067 |* Handler fuer das Ende einer Absatzverschiebung
1068 |*
1069 \************************************************************************/
1070 
1071 IMPL_LINK( OutlineView, EndMovingHdl, ::Outliner *, pOutliner )
1072 {
1073     OutlineViewPageChangesGuard aGuard(this);
1074 
1075     DBG_ASSERT(mpSelectedParas, "keine Absatzliste");
1076     DBG_ASSERT(mpOldParaOrder, "keine Absatzliste");
1077     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::EndMovingHdl(), model change without undo?!" );
1078 
1079     // Einfuegeposition anhand des ersten Absatzes suchen
1080     Paragraph* pSearchIt = (Paragraph*)mpSelectedParas->First();
1081 
1082     // den ersten der selektierten Paragraphen in der neuen Ordnung suchen
1083     sal_uInt16 nPosNewOrder = 0;
1084     sal_uLong nParaPos = 0;
1085     Paragraph*  pPara = pOutliner->GetParagraph( 0 );
1086     Paragraph*  pPrev = NULL;
1087     while (pPara && pPara != pSearchIt)
1088     {
1089         if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1090         {
1091             nPosNewOrder++;
1092             pPrev = pPara;
1093         }
1094         pPara = pOutliner->GetParagraph( ++nParaPos );
1095     }
1096 
1097     sal_uInt16 nPos = nPosNewOrder;     // nPosNewOrder nicht veraendern
1098     if (nPos == 0)
1099     {
1100         nPos = (sal_uInt16)-1;          // vor der ersten Seite einfuegen
1101     }
1102     else
1103     {
1104         // den Vorgaenger in der alten Ordnung suchen
1105         nPos = (sal_uInt16)mpOldParaOrder->GetPos(pPrev);
1106         DBG_ASSERT(nPos != 0xffff, "Absatz nicht gefunden");
1107     }
1108 
1109     mpDoc->MovePages(nPos);
1110 
1111     // die Seiten wieder deselektieren
1112     sal_uInt16 nPageCount = (sal_uInt16)mpSelectedParas->Count();
1113     while (nPageCount)
1114     {
1115         SdPage* pPage = mpDoc->GetSdPage(nPosNewOrder, PK_STANDARD);
1116         pPage->SetSelected(sal_False);
1117         nPosNewOrder++;
1118         nPageCount--;
1119     }
1120 
1121     pOutliner->UpdateFields();
1122 
1123     delete mpSelectedParas;
1124     mpSelectedParas = NULL;
1125     delete mpOldParaOrder;
1126     mpOldParaOrder = NULL;
1127 
1128     InvalidateSlideNumberArea();
1129 
1130     return 0;
1131 }
1132 
1133 /*************************************************************************
1134 |*
1135 |* Eine Seite des Models nach dem Titeltextobjekt durchsuchen
1136 |*
1137 \************************************************************************/
1138 
1139 SdrTextObj* OutlineView::GetTitleTextObject(SdrPage* pPage)
1140 {
1141     sal_uLong           nObjectCount = pPage->GetObjCount();
1142     SdrObject*      pObject      = NULL;
1143     SdrTextObj*     pResult      = NULL;
1144 
1145     for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
1146     {
1147         pObject = pPage->GetObj(nObject);
1148         if (pObject->GetObjInventor() == SdrInventor &&
1149             pObject->GetObjIdentifier() == OBJ_TITLETEXT)
1150         {
1151             pResult = (SdrTextObj*)pObject;
1152             break;
1153         }
1154     }
1155     return pResult;
1156 }
1157 
1158 
1159 /*************************************************************************
1160 |*
1161 |* Eine Seite des Models nach dem Gliederungstextobjekt durchsuchen
1162 |*
1163 \************************************************************************/
1164 
1165 SdrTextObj* OutlineView::GetOutlineTextObject(SdrPage* pPage)
1166 {
1167     sal_uLong           nObjectCount = pPage->GetObjCount();
1168     SdrObject*      pObject      = NULL;
1169     SdrTextObj*     pResult      = NULL;
1170 
1171     for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
1172     {
1173         pObject = pPage->GetObj(nObject);
1174         if (pObject->GetObjInventor() == SdrInventor &&
1175             pObject->GetObjIdentifier() == OBJ_OUTLINETEXT)
1176         {
1177             pResult = (SdrTextObj*)pObject;
1178             break;
1179         }
1180     }
1181     return pResult;
1182 }
1183 
1184 SdrTextObj* OutlineView::CreateTitleTextObject(SdPage* pPage)
1185 {
1186     DBG_ASSERT( GetTitleTextObject(pPage) == 0, "sd::OutlineView::CreateTitleTextObject(), there is already a title text object!" );
1187 
1188     if( pPage->GetAutoLayout() == AUTOLAYOUT_NONE )
1189     {
1190         // simple case
1191         pPage->SetAutoLayout( AUTOLAYOUT_ONLY_TITLE, true );
1192     }
1193     else
1194     {
1195         // we already have a layout with a title but the title
1196         // object was deleted, create a new one
1197         pPage->InsertAutoLayoutShape( 0, PRESOBJ_TITLE, false, pPage->GetTitleRect(), true );
1198     }
1199 
1200     return GetTitleTextObject(pPage);
1201 }
1202 
1203 SdrTextObj* OutlineView::CreateOutlineTextObject(SdPage* pPage)
1204 {
1205     DBG_ASSERT( GetOutlineTextObject(pPage) == 0, "sd::OutlineView::CreateOutlineTextObject(), there is already a layout text object!" );
1206 
1207     AutoLayout eNewLayout = pPage->GetAutoLayout();
1208     switch( eNewLayout )
1209     {
1210     case AUTOLAYOUT_NONE:
1211     case AUTOLAYOUT_ONLY_TITLE:
1212     case AUTOLAYOUT_TITLE:  eNewLayout = AUTOLAYOUT_ENUM; break;
1213 
1214     case AUTOLAYOUT_CHART:  eNewLayout = AUTOLAYOUT_CHARTTEXT; break;
1215 
1216     case AUTOLAYOUT_ORG:
1217     case AUTOLAYOUT_TAB:
1218     case AUTOLAYOUT_OBJ:    eNewLayout = AUTOLAYOUT_OBJTEXT; break;
1219     default:
1220         break;
1221     }
1222 
1223     if( eNewLayout != pPage->GetAutoLayout() )
1224     {
1225         pPage->SetAutoLayout( eNewLayout, true );
1226     }
1227     else
1228     {
1229         // we already have a layout with a text but the text
1230         // object was deleted, create a new one
1231         pPage->InsertAutoLayoutShape( 0,
1232                                       (eNewLayout == AUTOLAYOUT_TITLE) ? PRESOBJ_TEXT : PRESOBJ_OUTLINE,
1233                                       false, pPage->GetLayoutRect(), true );
1234     }
1235 
1236     return GetOutlineTextObject(pPage);
1237 }
1238 
1239 /** updates draw model with all changes from outliner model */
1240 sal_Bool OutlineView::PrepareClose(sal_Bool)
1241 {
1242     ::sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
1243     if (pDocUndoMgr != NULL)
1244         pDocUndoMgr->SetLinkedUndoManager(NULL);
1245 
1246     mpOutliner->GetUndoManager().Clear();
1247 
1248     const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1249     BegUndo(aUndoStr);
1250     UpdateDocument();
1251     EndUndo();
1252     mpDoc->SetSelected(GetActualPage(), sal_True);
1253     return sal_True;
1254 }
1255 
1256 
1257 /*************************************************************************
1258 |*
1259 |* Attribute des selektierten Textes setzen
1260 |*
1261 \************************************************************************/
1262 
1263 sal_Bool OutlineView::SetAttributes(const SfxItemSet& rSet, sal_Bool )
1264 {
1265     sal_Bool bOk = sal_False;
1266 
1267     OutlinerView* pOlView = GetViewByWindow(mpOutlineViewShell->GetActiveWindow());
1268 
1269     if (pOlView)
1270     {
1271         pOlView->SetAttribs(rSet);
1272         bOk = sal_True;
1273     }
1274 
1275     mpOutlineViewShell->Invalidate (SID_PREVIEW_STATE);
1276 
1277     return (bOk);
1278 }
1279 
1280 /*************************************************************************
1281 |*
1282 |* Attribute des selektierten Textes erfragen
1283 |*
1284 \************************************************************************/
1285 
1286 sal_Bool OutlineView::GetAttributes( SfxItemSet& rTargetSet, sal_Bool ) const
1287 {
1288     OutlinerView* pOlView = GetViewByWindow(
1289                                 mpOutlineViewShell->GetActiveWindow());
1290     DBG_ASSERT(pOlView, "keine OutlinerView gefunden");
1291 
1292     rTargetSet.Put( pOlView->GetAttribs(), sal_False );
1293     return sal_True;
1294 }
1295 
1296 /** creates outliner model from draw model */
1297 void OutlineView::FillOutliner()
1298 {
1299     mpOutliner->GetUndoManager().Clear();
1300     mpOutliner->EnableUndo(sal_False);
1301     ResetLinks();
1302     mpOutliner->SetUpdateMode(false);
1303 
1304     Paragraph* pTitleToSelect = NULL;
1305     sal_uLong nPageCount = mpDoc->GetSdPageCount(PK_STANDARD);
1306 
1307     // fill outliner with paragraphs from slides title & (outlines|subtitles)
1308     for (sal_uInt16 nPage = 0; nPage < nPageCount; nPage++)
1309     {
1310         SdPage*     pPage = (SdPage*)mpDoc->GetSdPage(nPage, PK_STANDARD);
1311         Paragraph * pPara = NULL;
1312 
1313         // take text from title shape
1314         SdrTextObj* pTO = GetTitleTextObject(pPage);
1315         if(pTO && !(pTO->IsEmptyPresObj()))
1316         {
1317             OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1318             if (pOPO)
1319             {
1320                 sal_Bool bVertical = pOPO->IsVertical();
1321                 pOPO->SetVertical( sal_False );
1322                 mpOutliner->AddText(*pOPO);
1323                 pOPO->SetVertical( bVertical );
1324                 pPara = mpOutliner->GetParagraph( mpOutliner->GetParagraphCount()-1 );
1325             }
1326         }
1327 
1328         if( pPara == 0 ) // no title, insert an empty paragraph
1329         {
1330             pPara = mpOutliner->Insert(String());
1331             mpOutliner->SetDepth(pPara, -1);
1332 
1333             // Keine harten Attribute vom vorherigen Absatz uebernehmen
1334             mpOutliner->SetParaAttribs( (sal_uInt16)mpOutliner->GetAbsPos(pPara),
1335                                        mpOutliner->GetEmptyItemSet() );
1336 
1337             mpOutliner->SetStyleSheet( mpOutliner->GetAbsPos( pPara ), pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE ) );
1338         }
1339 
1340         mpOutliner->SetParaFlag( pPara, PARAFLAG_ISPAGE );
1341 
1342         sal_uLong nPara = mpOutliner->GetAbsPos( pPara );
1343 
1344         UpdateParagraph( (sal_uInt16)nPara );
1345 
1346         // remember paragraph of currently selected page
1347         if (pPage->IsSelected())
1348             pTitleToSelect = pPara;
1349 
1350         // take text from subtitle or outline
1351         pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TEXT));
1352         const bool bSubTitle = pTO != 0;
1353 
1354         if (!pTO) // if no subtile found, try outline
1355             pTO = GetOutlineTextObject(pPage);
1356 
1357         if(pTO && !(pTO->IsEmptyPresObj())) // found some text
1358         {
1359             OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1360             if (pOPO)
1361             {
1362                 sal_uInt16 nParaCount1 = (sal_uInt16)mpOutliner->GetParagraphCount();
1363                 sal_Bool bVertical = pOPO->IsVertical();
1364                 pOPO->SetVertical( sal_False );
1365                 mpOutliner->AddText(*pOPO);
1366                 pOPO->SetVertical( bVertical );
1367 
1368                 sal_uInt16 nParaCount2 = (sal_uInt16)mpOutliner->GetParagraphCount();
1369                 for (sal_uInt16 n = nParaCount1; n < nParaCount2; n++)
1370                 {
1371                     if( bSubTitle )
1372                     {
1373                         Paragraph* p = mpOutliner->GetParagraph(n);
1374                         if(p && mpOutliner->GetDepth( n ) > 0 )
1375                             mpOutliner->SetDepth(p, 0);
1376                     }
1377 
1378                     UpdateParagraph( n );
1379                 }
1380             }
1381         }
1382     }
1383 
1384     // place cursor at the start
1385     Paragraph* pFirstPara = mpOutliner->GetParagraph( 0 );
1386     mpOutlinerView[0]->Select( pFirstPara, sal_True, sal_False );
1387     mpOutlinerView[0]->Select( pFirstPara, sal_False, sal_False );
1388 
1389     // select title of slide that was selected
1390     if (pTitleToSelect)
1391         mpOutlinerView[0]->Select(pTitleToSelect, sal_True, sal_False);
1392 
1393     SetLinks();
1394 
1395     mpOutliner->EnableUndo(sal_True);
1396 
1397     mpOutliner->SetUpdateMode(true);
1398 }
1399 
1400 /*************************************************************************
1401 |*
1402 |* Handler fuer das Loeschen von Level-0-Absaetzen (Seiten): Warnung
1403 |*
1404 \************************************************************************/
1405 
1406 IMPL_LINK( OutlineView, RemovingPagesHdl, OutlinerView *, EMPTYARG )
1407 {
1408     sal_uInt16 nNumOfPages = mpOutliner->GetSelPageCount();
1409 
1410     if (nNumOfPages > PROCESS_WITH_PROGRESS_THRESHOLD)
1411     {
1412         mnPagesToProcess = nNumOfPages;
1413         mnPagesProcessed  = 0;
1414     }
1415 
1416     if (mnPagesToProcess)
1417     {
1418         if( mpProgress )
1419             delete mpProgress;
1420 
1421         String aStr(SdResId(STR_DELETE_PAGES));
1422         mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
1423     }
1424     mpOutliner->UpdateFields();
1425 
1426     InvalidateSlideNumberArea();
1427 
1428     return 1;
1429 }
1430 
1431 /*************************************************************************
1432 |*
1433 |* Handler fuer das Einruecken von Level-0-Absaetzen (Seiten): Warnung
1434 |*
1435 \************************************************************************/
1436 
1437 IMPL_LINK_INLINE_START( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1438 {
1439     return RemovingPagesHdl(pOutlinerView);
1440 }
1441 IMPL_LINK_INLINE_END( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1442 
1443 
1444 /** returns the first slide that is selected in the outliner or where
1445     the cursor is located */
1446 SdPage* OutlineView::GetActualPage()
1447 {
1448     ::sd::Window* pWin = mpOutlineViewShell->GetActiveWindow();
1449     OutlinerView* pActiveView = GetViewByWindow(pWin);
1450     std::auto_ptr<List> pSelList( static_cast< List* >(pActiveView->CreateSelectionList()) );
1451 
1452     SdPage* pCurrent = GetPageForParagraph(static_cast<Paragraph*>(pSelList->First()) );
1453     DBG_ASSERT( pCurrent ||
1454                 (mpDocSh->GetUndoManager() && static_cast< sd::UndoManager *>(mpDocSh->GetUndoManager())->IsDoing()) ||
1455                 maDragAndDropModelGuard.get(),
1456                 "sd::OutlineView::GetActualPage(), no current page?" );
1457     if( pCurrent )
1458         return pCurrent;
1459     else
1460         return mpDoc->GetSdPage( 0, PK_STANDARD );
1461 }
1462 
1463 SdPage* OutlineView::GetPageForParagraph( Paragraph* pPara )
1464 {
1465     if( !mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1466         pPara = GetPrevTitle(pPara);
1467 
1468     sal_uInt32 nPageToSelect = 0;
1469     while(pPara)
1470     {
1471         pPara = GetPrevTitle(pPara);
1472         if(pPara)
1473             nPageToSelect++;
1474     }
1475 
1476     if( nPageToSelect < (sal_uInt32)mpDoc->GetSdPageCount( PK_STANDARD ) )
1477         return static_cast< SdPage* >( mpDoc->GetSdPage( (sal_uInt16)nPageToSelect, PK_STANDARD) );
1478     else
1479         return 0;
1480 }
1481 
1482 Paragraph* OutlineView::GetParagraphForPage( ::Outliner* pOutl, SdPage* pPage )
1483 {
1484     // get the number of paragraphs with ident 0 we need to skip before
1485     // we finde the actual page
1486     sal_uInt32 nPagesToSkip = (pPage->GetPageNum() - 1) >> 1;
1487 
1488     sal_uInt32 nParaPos = 0;
1489     Paragraph* pPara = pOutl->GetParagraph( 0 );
1490     while( pPara )
1491     {
1492         // if this paragraph is a page ...
1493         if( mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1494         {
1495             // see if we already skiped enough pages
1496             if( 0 == nPagesToSkip )
1497                 break;  // and if so, end the loop
1498 
1499             // we skiped another page
1500             nPagesToSkip--;
1501         }
1502 
1503         // get next paragraph
1504         pPara = mpOutliner->GetParagraph( ++nParaPos );
1505     }
1506 
1507     return pPara;
1508 }
1509 
1510 /** selects the paragraph for the given page at the outliner view*/
1511 void OutlineView::SetActualPage( SdPage* pActual )
1512 {
1513     if( pActual && mpOutliner && dynamic_cast<Outliner*> ( mpOutliner )->GetIgnoreCurrentPageChangesLevel()==0 && !mbFirstPaint)
1514     {
1515         // if we found a paragraph, select its text at the outliner view
1516         Paragraph* pPara = GetParagraphForPage( mpOutliner, pActual );
1517         if( pPara )
1518             mpOutlinerView[0]->Select( pPara, sal_True, sal_False );
1519     }
1520 }
1521 
1522 /*************************************************************************
1523 |*
1524 |* StyleSheet aus der Selektion besorgen
1525 |*
1526 \************************************************************************/
1527 
1528 SfxStyleSheet* OutlineView::GetStyleSheet() const
1529 {
1530     ::sd::Window* pActWin = mpOutlineViewShell->GetActiveWindow();
1531     OutlinerView* pOlView = GetViewByWindow(pActWin);
1532     SfxStyleSheet* pResult = pOlView->GetStyleSheet();
1533     return pResult;
1534 }
1535 
1536 
1537 
1538 /*************************************************************************
1539 |*
1540 |* Seiten als selektiert / nicht selektiert setzen
1541 |*
1542 \************************************************************************/
1543 
1544 void OutlineView::SetSelectedPages()
1545 {
1546     // Liste der selektierten Titelabsaetze
1547     List* pSelParas = mpOutlinerView[0]->CreateSelectionList();
1548     Paragraph* pPara = (Paragraph*) pSelParas->First();
1549 
1550     while(pPara)
1551     {
1552         if( !mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1553         {
1554             pSelParas->Remove();
1555             pPara = (Paragraph*) pSelParas->GetCurObject();
1556         }
1557         else
1558         {
1559             pPara = (Paragraph*) pSelParas->Next();
1560         }
1561     }
1562 
1563     // Die zu den selektierten Absaetzen auf Ebene 0 gehoerenden Seiten
1564     // selektieren
1565     sal_uInt16 nPos = 0;
1566     sal_uLong nParaPos = 0;
1567     pPara = mpOutliner->GetParagraph( 0 );
1568 
1569     while(pPara)
1570     {
1571         if( mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )                     // eine Seite?
1572         {
1573             SdPage* pPage = mpDoc->GetSdPage(nPos, PK_STANDARD);
1574             DBG_ASSERT(pPage!=NULL,
1575                 "Trying to select non-existing page OutlineView::SetSelectedPages()");
1576             if (pPage != NULL)
1577             {
1578                 pPage->SetSelected(sal_False);
1579 
1580                 if (pSelParas->Seek(pPara))            // selektiert?
1581                     pPage->SetSelected(sal_True);
1582             }
1583 
1584             nPos++;
1585         }
1586 
1587         pPara = mpOutliner->GetParagraph( ++nParaPos );
1588     }
1589 }
1590 
1591 
1592 /*************************************************************************
1593 |*
1594 |* Neue Links setzen
1595 |*
1596 \************************************************************************/
1597 
1598 void OutlineView::SetLinks()
1599 {
1600     // Benachrichtigungs-Links setzen
1601     mpOutliner->SetParaInsertedHdl(LINK(this, OutlineView, ParagraphInsertedHdl));
1602     mpOutliner->SetParaRemovingHdl(LINK(this, OutlineView, ParagraphRemovingHdl));
1603     mpOutliner->SetDepthChangedHdl(LINK(this, OutlineView, DepthChangedHdl));
1604     mpOutliner->SetBeginMovingHdl(LINK(this, OutlineView, BeginMovingHdl));
1605     mpOutliner->SetEndMovingHdl(LINK(this, OutlineView, EndMovingHdl));
1606     mpOutliner->SetRemovingPagesHdl(LINK(this, OutlineView, RemovingPagesHdl));
1607     mpOutliner->SetIndentingPagesHdl(LINK(this, OutlineView, IndentingPagesHdl));
1608     mpOutliner->SetStatusEventHdl(LINK(this, OutlineView, StatusEventHdl));
1609     mpOutliner->SetBeginDropHdl(LINK(this,OutlineView, BeginDropHdl));
1610     mpOutliner->SetEndDropHdl(LINK(this,OutlineView, EndDropHdl));
1611     mpOutliner->SetPaintFirstLineHdl(LINK(this,OutlineView,PaintingFirstLineHdl));
1612     mpOutliner->SetBeginPasteOrDropHdl(LINK(this,OutlineView, BeginPasteOrDropHdl));
1613     mpOutliner->SetEndPasteOrDropHdl(LINK(this,OutlineView, EndPasteOrDropHdl));
1614 }
1615 
1616 
1617 
1618 /*************************************************************************
1619 |*
1620 |* Alte Links restaurieren
1621 |*
1622 \************************************************************************/
1623 
1624 void OutlineView::ResetLinks() const
1625 {
1626     // alte Links restaurieren
1627     Link aEmptyLink;
1628     mpOutliner->SetParaInsertedHdl(aEmptyLink);
1629     mpOutliner->SetParaRemovingHdl(aEmptyLink);
1630     mpOutliner->SetDepthChangedHdl(aEmptyLink);
1631     mpOutliner->SetBeginMovingHdl(aEmptyLink);
1632     mpOutliner->SetEndMovingHdl(aEmptyLink);
1633     mpOutliner->SetStatusEventHdl(aEmptyLink);
1634     mpOutliner->SetRemovingPagesHdl(aEmptyLink);
1635     mpOutliner->SetIndentingPagesHdl(aEmptyLink);
1636     mpOutliner->SetDrawPortionHdl(aEmptyLink);
1637     mpOutliner->SetBeginPasteOrDropHdl(aEmptyLink);
1638     mpOutliner->SetEndPasteOrDropHdl(aEmptyLink);
1639 }
1640 
1641 /*************************************************************************
1642 |*
1643 |* AcceptDrop
1644 |*
1645 \************************************************************************/
1646 
1647 sal_Int8 OutlineView::AcceptDrop( const AcceptDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1648 {
1649     return DND_ACTION_NONE;
1650 }
1651 
1652 /*************************************************************************
1653 |*
1654 |* ExecuteDrop
1655 |*
1656 \************************************************************************/
1657 
1658 sal_Int8 OutlineView::ExecuteDrop( const ExecuteDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1659 {
1660     return DND_ACTION_NONE;
1661 }
1662 
1663 // #97766# Re-implement GetScriptType for this view to get correct results
1664 sal_uInt16 OutlineView::GetScriptType() const
1665 {
1666     sal_uInt16 nScriptType = ::sd::View::GetScriptType();
1667 
1668     if(mpOutliner)
1669     {
1670         OutlinerParaObject* pTempOPObj = mpOutliner->CreateParaObject();
1671 
1672         if(pTempOPObj)
1673         {
1674             nScriptType = pTempOPObj->GetTextObject().GetScriptType();
1675             delete pTempOPObj;
1676         }
1677     }
1678 
1679     return nScriptType;
1680 }
1681 
1682 void OutlineView::onUpdateStyleSettings( bool bForceUpdate /* = false */ )
1683 {
1684     const bool bHighContrastMode = Application::GetSettings().GetStyleSettings().GetHighContrastMode() != 0;
1685     if( bForceUpdate || (mbHighContrastMode != bHighContrastMode) )
1686     {
1687         if( mpOutliner )
1688         {
1689             mpOutliner->ForceAutoColor( bHighContrastMode );
1690         }
1691         mbHighContrastMode = bHighContrastMode;
1692 
1693     }
1694 
1695     svtools::ColorConfig aColorConfig;
1696     const Color aDocColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
1697     if( bForceUpdate || (maDocColor != aDocColor) )
1698     {
1699         sal_uInt16 nView;
1700         for( nView = 0; nView < MAX_OUTLINERVIEWS; nView++ )
1701         {
1702             if (mpOutlinerView[nView] != NULL)
1703             {
1704                 mpOutlinerView[nView]->SetBackgroundColor( aDocColor );
1705 
1706                 ::Window* pWindow = mpOutlinerView[nView]->GetWindow();
1707 
1708                 if( pWindow )
1709                     pWindow->SetBackground( Wallpaper( aDocColor ) );
1710 
1711             }
1712         }
1713 
1714         if( mpOutliner )
1715             mpOutliner->SetBackgroundColor( aDocColor );
1716 
1717         maDocColor = aDocColor;
1718     }
1719 }
1720 
1721 IMPL_LINK( OutlineView, AppEventListenerHdl, void *, EMPTYARG )
1722 {
1723     onUpdateStyleSettings();
1724     return 0;
1725 }
1726 
1727 
1728 
1729 
1730 IMPL_LINK(OutlineView, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent*, pEvent)
1731 {
1732     if (pEvent != NULL)
1733     {
1734         switch (pEvent->meEventId)
1735         {
1736             case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
1737                 SetActualPage(mpOutlineViewShell->GetActualPage());
1738                 InvalidateSlideNumberArea();
1739                 break;
1740 
1741             case tools::EventMultiplexerEvent::EID_PAGE_ORDER:
1742                 if (mpOutliner != NULL && mpDoc!=NULL && mpOutliner != NULL && dynamic_cast<Outliner*> ( mpOutliner )->GetIgnoreCurrentPageChangesLevel()==0)
1743                 {
1744                     if (((mpDoc->GetPageCount()-1)%2) == 0)
1745                     {
1746                         mpOutliner->Clear();
1747                         FillOutliner();
1748                         ::sd::Window* pWindow = mpOutlineViewShell->GetActiveWindow();
1749                         if (pWindow != NULL)
1750                             pWindow->Invalidate();
1751                     }
1752                 }
1753                 break;
1754         }
1755     }
1756     return 0;
1757 }
1758 
1759 void OutlineView::IgnoreCurrentPageChanges (bool bIgnoreChanges)
1760 {
1761     if ( mpOutliner )
1762     {
1763         if (bIgnoreChanges)
1764             dynamic_cast<Outliner*> ( mpOutliner )->IncreIgnoreCurrentPageChangesLevel();
1765         else
1766             dynamic_cast<Outliner*> ( mpOutliner )->DecreIgnoreCurrentPageChangesLevel();
1767     }
1768 }
1769 
1770 /** call this method before you do anything that can modify the outliner
1771     and or the drawing document model. It will create needed undo actions */
1772 void OutlineView::BeginModelChange()
1773 {
1774     const String aEmpty;
1775     mpOutliner->GetUndoManager().EnterListAction(aEmpty,aEmpty);
1776     const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1777     BegUndo(aUndoStr);
1778 }
1779 
1780 /** call this method after BeginModelChange(), when all possible model
1781     changes are done. */
1782 void OutlineView::EndModelChange()
1783 {
1784     UpdateDocument();
1785 
1786     ::svl::IUndoManager* pDocUndoMgr = mpDocSh->GetUndoManager();
1787 
1788     bool bHasUndoActions = pDocUndoMgr->GetUndoActionCount() != 0;
1789 
1790     EndUndo();
1791 
1792     DBG_ASSERT( bHasUndoActions == (mpOutliner->GetUndoManager().GetUndoActionCount() != 0), "sd::OutlineView::EndModelChange(), undo actions not in sync!" );
1793 
1794     if( bHasUndoActions )
1795     {
1796         SfxLinkUndoAction* pLink = new SfxLinkUndoAction(pDocUndoMgr);
1797         mpOutliner->GetUndoManager().AddUndoAction(pLink);
1798     }
1799 
1800     mpOutliner->GetUndoManager().LeaveListAction();
1801 
1802     if( bHasUndoActions && mpOutliner->GetEditEngine().HasTriedMergeOnLastAddUndo() )
1803         TryToMergeUndoActions();
1804 
1805     mpOutlineViewShell->Invalidate( SID_UNDO );
1806     mpOutlineViewShell->Invalidate( SID_REDO );
1807 }
1808 
1809 /** updates all changes in the outliner model to the draw model */
1810 void OutlineView::UpdateDocument()
1811 {
1812     const sal_uInt32 nPageCount = mpDoc->GetSdPageCount(PK_STANDARD);
1813     Paragraph* pPara = mpOutliner->GetParagraph( 0 );
1814     sal_uInt32 nPage;
1815     for (nPage = 0; nPage < nPageCount; nPage++)
1816     {
1817         SdPage* pPage = mpDoc->GetSdPage( (sal_uInt16)nPage, PK_STANDARD);
1818         mpDoc->SetSelected(pPage, sal_False);
1819 
1820         mpOutlineViewShell->UpdateTitleObject( pPage, pPara );
1821         mpOutlineViewShell->UpdateOutlineObject( pPage, pPara );
1822 
1823         if( pPara )
1824             pPara = GetNextTitle(pPara);
1825     }
1826 
1827     DBG_ASSERT( pPara == 0, "sd::OutlineView::UpdateDocument(), slides are out of sync, creating missing ones" );
1828     while( pPara )
1829     {
1830         SdPage* pPage = InsertSlideForParagraph( pPara );
1831         mpDoc->SetSelected(pPage, sal_False);
1832 
1833         mpOutlineViewShell->UpdateTitleObject( pPage, pPara );
1834         mpOutlineViewShell->UpdateOutlineObject( pPage, pPara );
1835 
1836         if( pPara )
1837             pPara = GetNextTitle(pPara);
1838     }
1839 }
1840 
1841 /** merge edit engine undo actions if possible */
1842 void OutlineView::TryToMergeUndoActions()
1843 {
1844     ::svl::IUndoManager& rOutlineUndo = mpOutliner->GetUndoManager();
1845     if( rOutlineUndo.GetUndoActionCount() > 1 )
1846     {
1847         SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(0) );
1848         SfxListUndoAction* pPrevListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(1) );
1849         if( pListAction && pPrevListAction )
1850         {
1851             // find the top EditUndo action in the top undo action list
1852             size_t nAction = pListAction->aUndoActions.size();
1853             EditUndo* pEditUndo = 0;
1854             while( !pEditUndo && nAction )
1855             {
1856                 pEditUndo = dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction);
1857             }
1858 
1859             sal_uInt16 nEditPos = nAction; // we need this later to remove the merged undo actions
1860 
1861             // make sure it is the only EditUndo action in the top undo list
1862             while( pEditUndo && nAction )
1863             {
1864                 if( dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction) )
1865                     pEditUndo = 0;
1866             }
1867 
1868             // do we have one and only one EditUndo action in the top undo list?
1869             if( pEditUndo )
1870             {
1871                 // yes, see if we can merge it with the prev undo list
1872 
1873                 nAction = pPrevListAction->aUndoActions.size();
1874                 EditUndo* pPrevEditUndo = 0;
1875                 while( !pPrevEditUndo && nAction )
1876                     pPrevEditUndo = dynamic_cast< EditUndo* >(pPrevListAction->aUndoActions[--nAction].pAction);
1877 
1878                 if( pPrevEditUndo && pPrevEditUndo->Merge( pEditUndo ) )
1879                 {
1880                     // ok we merged the only EditUndo of the top undo list with
1881                     // the top EditUndo of the previous undo list
1882 
1883                     // first remove the merged undo action
1884                     DBG_ASSERT( pListAction->aUndoActions[nEditPos].pAction == pEditUndo,
1885                         "sd::OutlineView::TryToMergeUndoActions(), wrong edit pos!" );
1886                     pListAction->aUndoActions.Remove(nEditPos);
1887                     delete pEditUndo;
1888 
1889                     // now check if we also can merge the draw undo actions
1890                     ::svl::IUndoManager* pDocUndoManager = mpDocSh->GetUndoManager();
1891                     if( pDocUndoManager && ( pListAction->aUndoActions.size() == 1 ))
1892                     {
1893                         SfxLinkUndoAction* pLinkAction = dynamic_cast< SfxLinkUndoAction* >( pListAction->aUndoActions[0].pAction );
1894                         SfxLinkUndoAction* pPrevLinkAction = 0;
1895 
1896                         if( pLinkAction )
1897                         {
1898                             nAction = pPrevListAction->aUndoActions.size();
1899                             while( !pPrevLinkAction && nAction )
1900                                 pPrevLinkAction = dynamic_cast< SfxLinkUndoAction* >(pPrevListAction->aUndoActions[--nAction].pAction);
1901                         }
1902 
1903                         if( pLinkAction && pPrevLinkAction &&
1904                             ( pLinkAction->GetAction() == pDocUndoManager->GetUndoAction(0) ) &&
1905                             ( pPrevLinkAction->GetAction() == pDocUndoManager->GetUndoAction(1) ) )
1906                         {
1907                             SfxListUndoAction* pSourceList = dynamic_cast< SfxListUndoAction* >(pLinkAction->GetAction());
1908                             SfxListUndoAction* pDestinationList = dynamic_cast< SfxListUndoAction* >(pPrevLinkAction->GetAction());
1909 
1910                             if( pSourceList && pDestinationList )
1911                             {
1912                                 sal_uInt16 nCount = pSourceList->aUndoActions.size();
1913                                 sal_uInt16 nDestAction = pDestinationList->aUndoActions.size();
1914                                 while( nCount-- )
1915                                 {
1916                                     SfxUndoAction* pTemp = pSourceList->aUndoActions[0].pAction;
1917                                     pSourceList->aUndoActions.Remove(0);
1918                                     pDestinationList->aUndoActions.Insert( pTemp, nDestAction++ );
1919                                 }
1920                                 pDestinationList->nCurUndoAction = pDestinationList->aUndoActions.size();
1921 
1922                                 pListAction->aUndoActions.Remove(0);
1923                                 delete pLinkAction;
1924 
1925                                 pDocUndoManager->RemoveLastUndoAction();
1926                             }
1927                         }
1928                     }
1929 
1930                     if ( !pListAction->aUndoActions.empty() )
1931                     {
1932                         // now we have to move all remaining doc undo actions from the top undo
1933                         // list to the previous undo list and remove the top undo list
1934 
1935                         size_t nCount = pListAction->aUndoActions.size();
1936                         size_t nDestAction = pPrevListAction->aUndoActions.size();
1937                         while( nCount-- )
1938                         {
1939                             SfxUndoAction* pTemp = pListAction->aUndoActions[0].pAction;
1940                             pListAction->aUndoActions.Remove(0);
1941                             if( pTemp )
1942                                 pPrevListAction->aUndoActions.Insert( pTemp, nDestAction++ );
1943                         }
1944                         pPrevListAction->nCurUndoAction = pPrevListAction->aUndoActions.size();
1945                     }
1946 
1947                     rOutlineUndo.RemoveLastUndoAction();
1948                 }
1949             }
1950         }
1951     }
1952 }
1953 
1954 IMPL_LINK(OutlineView, PaintingFirstLineHdl, PaintFirstLineInfo*, pInfo)
1955 {
1956     if( pInfo && mpOutliner )
1957     {
1958         Paragraph* pPara = mpOutliner->GetParagraph( pInfo->mnPara );
1959         EditEngine& rEditEngine = const_cast< EditEngine& >( mpOutliner->GetEditEngine() );
1960 
1961         Size aImageSize( pInfo->mpOutDev->PixelToLogic( maSlideImage.GetSizePixel()  ) );
1962         Size aOffset( 100, 100 );
1963 
1964         // paint slide number
1965         if( pPara && mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1966         {
1967             long nPage = 0; // todo, printing??
1968             for ( sal_uInt16 n = 0; n <= pInfo->mnPara; n++ )
1969             {
1970                 Paragraph* p = mpOutliner->GetParagraph( n );
1971                 if ( mpOutliner->HasParaFlag(p,PARAFLAG_ISPAGE) )
1972                     nPage++;
1973             }
1974 
1975             long nBulletHeight = (long)mpOutliner->GetLineHeight( pInfo->mnPara );
1976             long nFontHeight = 0;
1977             if ( !rEditEngine.IsFlatMode() )
1978             {
1979 //              const SvxFontHeightItem& rFH = (const SvxFontHeightItem&)rEditEngine.GetParaAttrib( pInfo->mnPara, EE_CHAR_FONTHEIGHT );
1980 //              nBulletHeight = rFH.GetHeight();
1981                 nFontHeight = nBulletHeight / 5;
1982             }
1983             else
1984             {
1985 //              const SvxFontHeightItem& rFH = (const SvxFontHeightItem&)rEditEngine.GetEmptyItemSet().Get( EE_CHAR_FONTHEIGHT );
1986  //               nBulletHeight = rFH.GetHeight();
1987                 nFontHeight = (nBulletHeight * 10) / 25;
1988             }
1989 
1990             Size aFontSz( 0, nFontHeight );
1991 
1992             Size aOutSize( 2000, nBulletHeight );
1993 
1994             const float fImageHeight = ((float)aOutSize.Height() * (float)4) / (float)7;
1995             const float fImageRatio  = (float)aImageSize.Height() / (float)aImageSize.Width();
1996             aImageSize.Width() = (long)( fImageRatio * fImageHeight );
1997             aImageSize.Height() = (long)( fImageHeight );
1998 
1999             Point aImagePos( pInfo->mrStartPos );
2000             aImagePos.X() += aOutSize.Width() - aImageSize.Width() - aOffset.Width() ;
2001             aImagePos.Y() += (aOutSize.Height() - aImageSize.Height()) / 2;
2002 
2003             pInfo->mpOutDev->DrawImage( aImagePos, aImageSize, maSlideImage );
2004 
2005             const bool bVertical = mpOutliner->IsVertical();
2006             const bool bRightToLeftPara = rEditEngine.IsRightToLeft( pInfo->mnPara );
2007 
2008             LanguageType eLang = rEditEngine.GetDefaultLanguage();
2009 
2010             Point aTextPos( aImagePos.X() - aOffset.Width(), pInfo->mrStartPos.Y() );
2011             Font aNewFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 ) );
2012             aNewFont.SetSize( aFontSz );
2013 //          aNewFont.SetAlign( aBulletFont.GetAlign() );
2014             aNewFont.SetVertical( bVertical );
2015             aNewFont.SetOrientation( bVertical ? 2700 : 0 );
2016             aNewFont.SetColor( COL_AUTO );
2017             pInfo->mpOutDev->SetFont( aNewFont );
2018             String aPageText = String::CreateFromInt32( nPage );
2019             Size aTextSz;
2020             aTextSz.Width() = pInfo->mpOutDev->GetTextWidth( aPageText );
2021             aTextSz.Height() = pInfo->mpOutDev->GetTextHeight();
2022 //            long nBulletHeight = !bVertical ? aBulletArea.GetHeight() : aBulletArea.GetWidth();
2023             if ( !bVertical )
2024             {
2025                 aTextPos.Y() += (aOutSize.Height() - aTextSz.Height()) / 2;
2026                 if ( !bRightToLeftPara )
2027                 {
2028                     aTextPos.X() -= aTextSz.Width();
2029                 }
2030                 else
2031                 {
2032                     aTextPos.X() += aTextSz.Width();
2033                 }
2034             }
2035             else
2036             {
2037                 aTextPos.Y() -= aTextSz.Width();
2038                 aTextPos.X() += nBulletHeight / 2;
2039             }
2040             pInfo->mpOutDev->DrawText( aTextPos, aPageText );
2041         }
2042     }
2043 
2044     return 0;
2045 }
2046 
2047 #if 0
2048 sal_Int32 OutlineView::GetPageNumberWidthPixel()
2049 {
2050     Window* pActWin = mpOutlineViewShell->GetActiveWindow();
2051     if( pActWin )
2052     {
2053         Font aOldFont( pActWin->GetFont() );
2054         pActWin->SetFont( maPageNumberFont );
2055         Size aSize( pActWin->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM("X" ) ) ), 0 );
2056         sal_Int32 nWidth = pActWin->LogicToPixel( aSize ).Width() * 5;
2057 
2058         const String aBulletStr( sal_Unicode( 0xE011 ) );
2059         pActWin->SetFont( maBulletFont);
2060 
2061         aSize.Width() = pActWin->GetTextWidth(aBulletStr);
2062         nWidth += pActWin->LogicToPixel( aSize ).Width();
2063 
2064         pActWin->SetFont( aOldFont );
2065 
2066         mnPageNumberWidthPixel = nWidth;
2067     }
2068     return mnPageNumberWidthPixel;
2069 }
2070 #endif
2071 
2072 // --------------------------------------------------------------------
2073 
2074 void OutlineView::UpdateParagraph( sal_uInt16 nPara )
2075 {
2076     if( mpOutliner )
2077     {
2078         SfxItemSet aNewAttrs2( mpOutliner->GetParaAttribs( nPara ) );
2079         aNewAttrs2.Put( maLRSpaceItem );
2080         mpOutliner->SetParaAttribs( nPara, aNewAttrs2 );
2081     }
2082 }
2083 
2084 // --------------------------------------------------------------------
2085 
2086 void OutlineView::OnBeginPasteOrDrop( PasteOrDropInfos* /*pInfos*/ )
2087 {
2088 }
2089 
2090 /** this is called after a paste or drop operation, make sure that the newly inserted paragraphs
2091     get the correct style sheet and new slides are inserted. */
2092 void OutlineView::OnEndPasteOrDrop( PasteOrDropInfos* pInfos )
2093 {
2094     SdPage* pPage = 0;
2095     SfxStyleSheetBasePool* pStylePool = GetDoc()->GetStyleSheetPool();
2096 
2097     for( sal_uInt16 nPara = pInfos->nStartPara; nPara <= pInfos->nEndPara; nPara++ )
2098     {
2099         Paragraph* pPara = mpOutliner->GetParagraph( nPara );
2100 
2101         bool bPage = mpOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE  );
2102 
2103         if( !bPage )
2104         {
2105             SdStyleSheet* pStyleSheet = dynamic_cast< SdStyleSheet* >( mpOutliner->GetStyleSheet( nPara ) );
2106             if( pStyleSheet )
2107             {
2108                 const OUString aName( pStyleSheet->GetApiName() );
2109                 if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("title" ) ) )
2110                     bPage = true;
2111             }
2112         }
2113 
2114         if( !pPara )
2115             continue; // fatality!?
2116 
2117         if( bPage && (nPara != pInfos->nStartPara) )
2118         {
2119             // insert new slide for this paragraph
2120             pPage = InsertSlideForParagraph( pPara );
2121         }
2122         else
2123         {
2124             // newly inserted non page paragraphs get the outline style
2125             if( !pPage )
2126                 pPage = GetPageForParagraph( pPara );
2127 
2128             if( pPage )
2129             {
2130                 SfxStyleSheet* pStyle = pPage->GetStyleSheetForPresObj( bPage ? PRESOBJ_TITLE : PRESOBJ_OUTLINE );
2131 
2132                 if( !bPage )
2133                 {
2134                     const sal_Int16 nDepth = mpOutliner->GetDepth( nPara );
2135                     if( nDepth > 0 )
2136                     {
2137                         String aStyleSheetName( pStyle->GetName() );
2138                         aStyleSheetName.Erase( aStyleSheetName.Len() - 1, 1 );
2139                         aStyleSheetName += String::CreateFromInt32( nDepth );
2140                         pStyle = static_cast<SfxStyleSheet*>( pStylePool->Find( aStyleSheetName, pStyle->GetFamily() ) );
2141                         DBG_ASSERT( pStyle, "sd::OutlineView::OnEndPasteOrDrop(), Style not found!" );
2142                     }
2143                 }
2144 
2145                 mpOutliner->SetStyleSheet( nPara, pStyle );
2146             }
2147 
2148             UpdateParagraph( nPara );
2149         }
2150     }
2151 }
2152 
2153 // ====================================================================
2154 
2155 
2156 OutlineViewModelChangeGuard::OutlineViewModelChangeGuard( OutlineView& rView )
2157 : mrView( rView )
2158 {
2159     mrView.BeginModelChange();
2160 }
2161 
2162 OutlineViewModelChangeGuard::~OutlineViewModelChangeGuard()
2163 {
2164     mrView.EndModelChange();
2165 }
2166 
2167 OutlineViewPageChangesGuard::OutlineViewPageChangesGuard( OutlineView* pView )
2168 : mpView( pView )
2169 {
2170     if( mpView )
2171         mpView->IgnoreCurrentPageChanges( true );
2172 }
2173 
2174 OutlineViewPageChangesGuard::~OutlineViewPageChangesGuard()
2175 {
2176     if( mpView )
2177         mpView->IgnoreCurrentPageChanges( false );
2178 }
2179 
2180 
2181 } // end of namespace sd
2182