xref: /trunk/main/sw/source/core/doc/docdesc.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <cmdid.h>
28 #include <hintids.hxx>
29 #include <vcl/virdev.hxx>
30 #include <svx/svdmodel.hxx>
31 #include <editeng/ulspitem.hxx>
32 #include <editeng/lrspitem.hxx>
33 #include <editeng/paperinf.hxx>
34 #include "editeng/frmdiritem.hxx"
35 #include <tools/urlobj.hxx>
36 #include <sfx2/docfile.hxx>
37 #include <sfx2/printer.hxx>
38 #include <unotools/localedatawrapper.hxx>
39 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
40 #include <fmtfsize.hxx>
41 #include <fmthdft.hxx>
42 #include <fmtcntnt.hxx>
43 #include <fmtpdsc.hxx>
44 #include <ftninfo.hxx>
45 #include <fesh.hxx>
46 #include <ndole.hxx>
47 #include <mdiexp.hxx>
48 #include <doc.hxx>
49 #include <IDocumentUndoRedo.hxx>
50 #include <docary.hxx>
51 #include <pagefrm.hxx>  //Fuer DelPageDesc
52 #include <rootfrm.hxx>  //Fuer DelPageDesc
53 #include <ndtxt.hxx>
54 #include <frmtool.hxx>
55 #include <pagedesc.hxx>
56 #include <poolfmt.hxx>
57 #include <docsh.hxx>
58 #include <ndindex.hxx>
59 #include <ftnidx.hxx>
60 #include <fmtftn.hxx>
61 #include <txtftn.hxx>
62 #include <fntcache.hxx>
63 #include <viewsh.hxx>
64 #include <viewopt.hxx>
65 #include <fldbas.hxx>
66 #include <swwait.hxx>
67 #include <GetMetricVal.hxx>
68 #include <unotools/syslocale.hxx>
69 #include <statstr.hrc>
70 #include <switerator.hxx>
71 #include <hints.hxx>
72 #include <SwUndoPageDesc.hxx>
73 #include <pagedeschint.hxx>
74 #include <tgrditem.hxx>
75 
76 using namespace com::sun::star;
77 
78 static void lcl_DefaultPageFmt( sal_uInt16 nPoolFmtId,
79                                 SwFrmFmt &rFmt1,
80                                 SwFrmFmt &rFmt2 )
81 {
82     // --> FME 2005-01-21 #i41075# Printer on demand
83     // This function does not require a printer anymore.
84     // The default page size is obtained from the application
85     //locale
86     // <--
87 
88     SwFmtFrmSize aFrmSize( ATT_FIX_SIZE );
89     const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize();
90     aFrmSize.SetSize( aPhysSize );
91 
92     //Auf Default-Raender vorbereiten.
93     //Raender haben eine defaultmaessige Mindestgroesse.
94     //wenn der Drucker einen groesseren Rand vorgibt, so
95     //ist mir dass auch recht.
96     // MIB 06/25/2002, #99397#: The HTML page desc had A4 as page size
97     // always. This has been changed to take the page size from the printer.
98     // Unfortunately, the margins of the HTML page desc are smaller than
99     // the margins used here in general, so one extra case is required.
100     // In the long term, this needs to be changed to always keep the
101     // margins from the page desc.
102     sal_Int32 nMinTop, nMinBottom, nMinLeft, nMinRight;
103     if( RES_POOLPAGE_HTML == nPoolFmtId )
104     {
105         nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 );
106         nMinLeft = nMinRight * 2;
107     }
108     else if( MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
109     {
110         nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; //2 Zentimeter
111     }
112     else
113     {
114         nMinTop = nMinBottom = 1440;    //al la WW: 1Inch
115         nMinLeft = nMinRight = 1800;    //          1,25 Inch
116     }
117 
118     //Raender einstellen.
119     SvxLRSpaceItem aLR( RES_LR_SPACE );
120     SvxULSpaceItem aUL( RES_UL_SPACE );
121 
122     aUL.SetUpper( (sal_uInt16)nMinTop );
123     aUL.SetLower( (sal_uInt16)nMinBottom );
124     aLR.SetRight( nMinRight );
125     aLR.SetLeft( nMinLeft );
126 
127     rFmt1.SetFmtAttr( aFrmSize );
128     rFmt1.SetFmtAttr( aLR );
129     rFmt1.SetFmtAttr( aUL );
130 
131     rFmt2.SetFmtAttr( aFrmSize );
132     rFmt2.SetFmtAttr( aLR );
133     rFmt2.SetFmtAttr( aUL );
134 }
135 
136 /*************************************************************************
137 |*
138 |*  SwDoc::ChgPageDesc()
139 |*
140 |*  Ersterstellung      MA 25. Jan. 93
141 |*  Letzte Aenderung    MA 01. Mar. 95
142 |*
143 |*************************************************************************/
144 
145 void lcl_DescSetAttr( const SwFrmFmt &rSource, SwFrmFmt &rDest,
146                          const sal_Bool bPage = sal_True )
147 {
148 /////////////// !!!!!!!!!!!!!!!!
149 //JP 03.03.99:
150 // eigentlich sollte hier das Intersect von ItemSet benutzt werden, aber das
151 // funktioniert nicht richtig, wenn man unterschiedliche WhichRanges hat.
152 /////////////// !!!!!!!!!!!!!!!!
153     //Die interressanten Attribute uebernehmen.
154     sal_uInt16 __READONLY_DATA aIdArr[] = { RES_FRM_SIZE, RES_UL_SPACE,
155                                         RES_BACKGROUND, RES_SHADOW,
156                                         RES_COL, RES_COL,
157                                         RES_FRAMEDIR, RES_FRAMEDIR,
158                                         RES_TEXTGRID, RES_TEXTGRID,
159                                         // --> FME 2005-04-18 #i45539#
160                                         RES_HEADER_FOOTER_EAT_SPACING,
161                                         RES_HEADER_FOOTER_EAT_SPACING,
162                                         // <--
163                                         RES_UNKNOWNATR_CONTAINER,
164                                         RES_UNKNOWNATR_CONTAINER,
165                                         0 };
166 
167     const SfxPoolItem* pItem;
168     for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 )
169     {
170         for( sal_uInt16 nId = aIdArr[ n ]; nId <= aIdArr[ n+1]; ++nId )
171         {
172             // --> FME 2005-04-18 #i45539#
173             // bPage == true:
174             // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
175             // bPage == false:
176             // All in aIdArr except from RES_COL and RES_PAPER_BIN:
177             // <--
178             if( (  bPage && RES_HEADER_FOOTER_EAT_SPACING != nId ) ||
179                 ( !bPage && RES_COL != nId && RES_PAPER_BIN != nId ))
180             {
181                 if( SFX_ITEM_SET == rSource.GetItemState( nId, sal_False, &pItem ))
182                     rDest.SetFmtAttr( *pItem );
183                 else
184                     rDest.ResetFmtAttr( nId );
185             }
186         }
187     }
188 
189     // auch Pool-, Hilfe-Id's uebertragen
190     rDest.SetPoolFmtId( rSource.GetPoolFmtId() );
191     rDest.SetPoolHelpId( rSource.GetPoolHelpId() );
192     rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() );
193 }
194 
195 
196 void SwDoc::ChgPageDesc( sal_uInt16 i, const SwPageDesc &rChged )
197 {
198     ASSERT( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
199 
200     SwPageDesc *pDesc = aPageDescs[i];
201     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
202 
203     if (GetIDocumentUndoRedo().DoesUndo())
204     {
205         SwUndo *const pUndo(new SwUndoPageDesc(*pDesc, rChged, this));
206         GetIDocumentUndoRedo().AppendUndo(pUndo);
207     }
208     ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
209 
210     //Als erstes wird ggf. gespiegelt.
211     if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR )
212         ((SwPageDesc&)rChged).Mirror();
213     else
214         //sonst Werte aus Master nach Left uebertragen.
215         ::lcl_DescSetAttr( ((SwPageDesc&)rChged).GetMaster(),
216                        ((SwPageDesc&)rChged).GetLeft() );
217 
218     //NumType uebernehmen.
219     if( rChged.GetNumType().GetNumberingType() != pDesc->GetNumType().GetNumberingType() )
220     {
221         pDesc->SetNumType( rChged.GetNumType() );
222         // JP 30.03.99: Bug 64121 - den Seitennummernfeldern bescheid sagen,
223         //      das sich das Num-Format geaendert hat
224         GetSysFldType( RES_PAGENUMBERFLD )->UpdateFlds();
225         GetSysFldType( RES_REFPAGEGETFLD )->UpdateFlds();
226 
227         // Wenn sich die Numerierungsart geaendert hat, koennte es QuoVadis/
228         // ErgoSum-Texte geben, die sich auf eine geaenderte Seite beziehen,
229         // deshalb werden die Fussnoten invalidiert
230         SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
231         for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
232         {
233             SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
234             const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
235             pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
236         }
237     }
238 
239     //Orientierung uebernehmen
240     pDesc->SetLandscape( rChged.GetLandscape() );
241 
242     // #i46909# no undo if header or footer changed
243     bool bHeaderFooterChanged = false;
244 
245     //Header abgleichen.
246     const SwFmtHeader &rHead = rChged.GetMaster().GetHeader();
247     if (undoGuard.UndoWasEnabled())
248     {
249         // #i46909# no undo if header or footer changed
250         // hat sich an den Nodes etwas veraendert ?
251         const SwFmtHeader &rOldHead = pDesc->GetMaster().GetHeader();
252         bHeaderFooterChanged |=
253             ( rHead.IsActive() != rOldHead.IsActive() ||
254               rChged.IsHeaderShared() != pDesc->IsHeaderShared() );
255     }
256     pDesc->GetMaster().SetFmtAttr( rHead );
257     if ( rChged.IsHeaderShared() || !rHead.IsActive() )
258     {
259         //Left teilt sich den Header mit dem Master.
260         pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetHeader() );
261     }
262     else if ( rHead.IsActive() )
263     {   //Left bekommt einen eigenen Header verpasst wenn das Format nicht
264         //bereits einen hat.
265         //Wenn er bereits einen hat und dieser auf die gleiche Section
266         //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
267         //Inhalt wird sinnigerweise kopiert.
268         const SwFmtHeader &rLeftHead = pDesc->GetLeft().GetHeader();
269         if ( !rLeftHead.IsActive() )
270         {
271             SwFmtHeader aHead( MakeLayoutFmt( RND_STD_HEADERL, 0 ) );
272             pDesc->GetLeft().SetFmtAttr( aHead );
273             //Weitere Attribute (Raender, Umrandung...) uebernehmen.
274             ::lcl_DescSetAttr( *rHead.GetHeaderFmt(), *aHead.GetHeaderFmt(), sal_False);
275         }
276         else
277         {
278             const SwFrmFmt *pRight = rHead.GetHeaderFmt();
279             const SwFmtCntnt &aRCnt = pRight->GetCntnt();
280             const SwFmtCntnt &aLCnt = rLeftHead.GetHeaderFmt()->GetCntnt();
281             if( !aLCnt.GetCntntIdx() )
282                 pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetHeader() );
283             else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
284             {
285                 SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Header",
286                                                 GetDfltFrmFmt() );
287                 ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
288                 //Der Bereich auf den das rechte Kopfattribut zeigt wird
289                 //kopiert und der Index auf den StartNode in das linke
290                 //Kopfattribut gehaengt.
291                 SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
292                 SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwHeaderStartNode );
293                 SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
294                             *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
295                 aTmp = *pSttNd->EndOfSectionNode();
296                 GetNodes()._Copy( aRange, aTmp, sal_False );
297 
298                 pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
299                 pDesc->GetLeft().SetFmtAttr( SwFmtHeader( pFmt ) );
300             }
301             else
302                 ::lcl_DescSetAttr( *pRight,
303                                *(SwFrmFmt*)rLeftHead.GetHeaderFmt(), sal_False );
304 
305         }
306     }
307     pDesc->ChgHeaderShare( rChged.IsHeaderShared() );
308 
309     //Footer abgleichen.
310     const SwFmtFooter &rFoot = rChged.GetMaster().GetFooter();
311     if (undoGuard.UndoWasEnabled())
312     {
313         // #i46909# no undo if header or footer changed
314         // hat sich an den Nodes etwas veraendert ?
315         const SwFmtFooter &rOldFoot = pDesc->GetMaster().GetFooter();
316         bHeaderFooterChanged |=
317             ( rFoot.IsActive() != rOldFoot.IsActive() ||
318               rChged.IsFooterShared() != pDesc->IsFooterShared() );
319     }
320     pDesc->GetMaster().SetFmtAttr( rFoot );
321     if ( rChged.IsFooterShared() || !rFoot.IsActive() )
322         //Left teilt sich den Header mit dem Master.
323         pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetFooter() );
324     else if ( rFoot.IsActive() )
325     {   //Left bekommt einen eigenen Footer verpasst wenn das Format nicht
326         //bereits einen hat.
327         //Wenn er bereits einen hat und dieser auf die gleiche Section
328         //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
329         //Inhalt wird sinnigerweise kopiert.
330         const SwFmtFooter &rLeftFoot = pDesc->GetLeft().GetFooter();
331         if ( !rLeftFoot.IsActive() )
332         {
333             SwFmtFooter aFoot( MakeLayoutFmt( RND_STD_FOOTER, 0 ) );
334             pDesc->GetLeft().SetFmtAttr( aFoot );
335             //Weitere Attribute (Raender, Umrandung...) uebernehmen.
336             ::lcl_DescSetAttr( *rFoot.GetFooterFmt(), *aFoot.GetFooterFmt(), sal_False);
337         }
338         else
339         {
340             const SwFrmFmt *pRight = rFoot.GetFooterFmt();
341             const SwFmtCntnt &aRCnt = pRight->GetCntnt();
342             const SwFmtCntnt &aLCnt = rLeftFoot.GetFooterFmt()->GetCntnt();
343             if( !aLCnt.GetCntntIdx() )
344                 pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetFooter() );
345             else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
346             {
347                 SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Footer",
348                                                 GetDfltFrmFmt() );
349                 ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
350                 //Der Bereich auf den das rechte Kopfattribut zeigt wird
351                 //kopiert und der Index auf den StartNode in das linke
352                 //Kopfattribut gehaengt.
353                 SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
354                 SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwFooterStartNode );
355                 SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
356                             *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
357                 aTmp = *pSttNd->EndOfSectionNode();
358                 GetNodes()._Copy( aRange, aTmp, sal_False );
359 
360                 pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
361                 pDesc->GetLeft().SetFmtAttr( SwFmtFooter( pFmt ) );
362             }
363             else
364                 ::lcl_DescSetAttr( *pRight,
365                                *(SwFrmFmt*)rLeftFoot.GetFooterFmt(), sal_False );
366         }
367     }
368     pDesc->ChgFooterShare( rChged.IsFooterShared() );
369 
370     if ( pDesc->GetName() != rChged.GetName() )
371         pDesc->SetName( rChged.GetName() );
372 
373     // Dadurch wird ein RegisterChange ausgeloest, wenn notwendig
374     pDesc->SetRegisterFmtColl( rChged.GetRegisterFmtColl() );
375 
376     //Wenn sich das UseOn oder der Follow aendern muessen die
377     //Absaetze das erfahren.
378     sal_Bool bUseOn  = sal_False;
379     sal_Bool bFollow = sal_False;
380     if ( pDesc->GetUseOn() != rChged.GetUseOn() )
381     {   pDesc->SetUseOn( rChged.GetUseOn() );
382         bUseOn = sal_True;
383     }
384     if ( pDesc->GetFollow() != rChged.GetFollow() )
385     {   if ( rChged.GetFollow() == &rChged )
386         {   if ( pDesc->GetFollow() != pDesc )
387             {   pDesc->SetFollow( pDesc );
388                 bFollow = sal_True;
389             }
390         }
391         else
392         {   pDesc->SetFollow( rChged.pFollow );
393             bFollow = sal_True;
394         }
395     }
396 
397     if ( (bUseOn || bFollow) && pTmpRoot)
398         //Layot benachrichtigen!
399     {
400         std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
401         std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));//swmod 080304
402     }
403 
404     //Jetzt noch die Seiten-Attribute uebernehmen.
405     ::lcl_DescSetAttr( rChged.GetMaster(), pDesc->GetMaster() );
406     ::lcl_DescSetAttr( rChged.GetLeft(), pDesc->GetLeft() );
407 
408     //Wenn sich FussnotenInfo veraendert, so werden die Seiten
409     //angetriggert.
410     if( !(pDesc->GetFtnInfo() == rChged.GetFtnInfo()) )
411     {
412         pDesc->SetFtnInfo( rChged.GetFtnInfo() );
413         SwMsgPoolItem  aInfo( RES_PAGEDESC_FTNINFO );
414         {
415             pDesc->GetMaster().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
416         }
417         {
418             pDesc->GetLeft().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
419         }
420     }
421     SetModified();
422 
423     // #i46909# no undo if header or footer changed
424     if( bHeaderFooterChanged )
425     {
426         GetIDocumentUndoRedo().DelAllUndoObj();
427     }
428 
429     SfxBindings* pBindings = GetDocShell() ? GetDocShell()->GetDispatcher()->GetBindings() : 0;
430     if ( pBindings )
431     {
432         pBindings->Invalidate( SID_ATTR_SWPAGE_COLUMN );
433         pBindings->Invalidate( SID_ATTR_PAGE );
434         pBindings->Invalidate( SID_ATTR_PAGE_SIZE );
435         pBindings->Invalidate( SID_ATTR_LONG_ULSPACE );
436         pBindings->Invalidate( SID_ATTR_LONG_LRSPACE );
437     }
438 
439 }
440 
441 /*************************************************************************
442 |*
443 |*  SwDoc::DelPageDesc()
444 |*
445 |*  Beschreibung        Alle Descriptoren, deren Follow auf den zu loeschenden
446 |*      zeigen muessen angepasst werden.
447 |*  Ersterstellung      MA 25. Jan. 93
448 |*  Letzte Aenderung    JP 04.09.95
449 |*
450 |*************************************************************************/
451 
452 // #i7983#
453 void SwDoc::PreDelPageDesc(SwPageDesc * pDel)
454 {
455     if (0 == pDel)
456         return;
457 
458     // mba: test iteration as clients are removed while iteration
459     SwPageDescHint aHint( aPageDescs[0] );
460     pDel->CallSwClientNotify( aHint );
461 
462     bool bHasLayout = HasLayout();
463     if ( pFtnInfo->DependsOn( pDel ) )
464     {
465         pFtnInfo->ChgPageDesc( aPageDescs[0] );
466         if ( bHasLayout )
467         {
468             std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
469             std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), false));
470         }
471     }
472     else if ( pEndNoteInfo->DependsOn( pDel ) )
473     {
474         pEndNoteInfo->ChgPageDesc( aPageDescs[0] );
475         if ( bHasLayout )
476         {
477             std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
478             std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), true));
479         }
480     }
481 
482     for ( sal_uInt16 j = 0; j < aPageDescs.Count(); ++j )
483     {
484         if ( aPageDescs[j]->GetFollow() == pDel )
485         {
486             aPageDescs[j]->SetFollow( 0 );
487             if( bHasLayout )
488             {
489                 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
490                 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));//swmod 080228
491             }
492         }
493     }
494 }
495 
496 // #116530#
497 void SwDoc::BroadcastStyleOperation(String rName, SfxStyleFamily eFamily,
498                                     sal_uInt16 nOp)
499 {
500     if (pDocShell)
501     {
502         SfxStyleSheetBasePool * pPool = pDocShell->GetStyleSheetPool();
503 
504         if (pPool)
505         {
506             pPool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
507             SfxStyleSheetBase * pBase = pPool->Find(rName);
508 
509             if (pBase != NULL)
510                 pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase ));
511         }
512     }
513 }
514 
515 void SwDoc::DelPageDesc( sal_uInt16 i, sal_Bool bBroadcast )
516 {
517     ASSERT( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
518     ASSERT( i != 0, "Default Pagedesc loeschen is nicht." );
519     if ( i == 0 )
520         return;
521 
522     SwPageDesc *pDel = aPageDescs[i];
523 
524     // -> #116530#
525     if (bBroadcast)
526         BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PAGE,
527                                 SFX_STYLESHEET_ERASED);
528     // <- #116530#
529 
530     if (GetIDocumentUndoRedo().DoesUndo())
531     {
532         SwUndo *const pUndo(new SwUndoPageDescDelete(*pDel, this));
533         GetIDocumentUndoRedo().AppendUndo(pUndo);
534     }
535 
536     PreDelPageDesc(pDel); // #i7983#
537 
538     aPageDescs.Remove( i );
539     delete pDel;
540     SetModified();
541 }
542 
543 
544 
545 /*************************************************************************
546 |*
547 |*  SwDoc::MakePageDesc()
548 |*
549 |*  Ersterstellung      MA 25. Jan. 93
550 |*  Letzte Aenderung    MA 20. Aug. 93
551 |*
552 |*************************************************************************/
553 
554 sal_uInt16 SwDoc::MakePageDesc( const String &rName, const SwPageDesc *pCpy,
555                             sal_Bool bRegardLanguage, sal_Bool bBroadcast) // #116530#
556 {
557     SwPageDesc *pNew;
558     if( pCpy )
559     {
560         pNew = new SwPageDesc( *pCpy );
561         pNew->SetName( rName );
562         if( rName != pCpy->GetName() )
563         {
564             pNew->SetPoolFmtId( USHRT_MAX );
565             pNew->SetPoolHelpId( USHRT_MAX );
566             pNew->SetPoolHlpFileId( UCHAR_MAX );
567         }
568     }
569     else
570     {
571         pNew = new SwPageDesc( rName, GetDfltFrmFmt(), this );
572         //Default-Seitenformat einstellen.
573         lcl_DefaultPageFmt( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft() );
574 
575         SvxFrameDirection aFrameDirection = bRegardLanguage ?
576             GetDefaultFrameDirection(GetAppLanguage())
577             : FRMDIR_HORI_LEFT_TOP;
578 
579         pNew->GetMaster().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
580         pNew->GetLeft().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
581     }
582     aPageDescs.Insert( pNew, aPageDescs.Count() );
583 
584     // -> #116530#
585     if (bBroadcast)
586         BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PAGE,
587                                 SFX_STYLESHEET_CREATED);
588     // <- #116530#
589 
590     if (GetIDocumentUndoRedo().DoesUndo())
591     {
592         // #116530#
593         GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this));
594     }
595 
596     SetModified();
597     return (aPageDescs.Count()-1);
598 }
599 
600 SwPageDesc* SwDoc::FindPageDescByName( const String& rName, sal_uInt16* pPos ) const
601 {
602     SwPageDesc* pRet = 0;
603     if( pPos ) *pPos = USHRT_MAX;
604 
605     for( sal_uInt16 n = 0, nEnd = aPageDescs.Count(); n < nEnd; ++n )
606         if( aPageDescs[ n ]->GetName() == rName )
607         {
608             pRet = aPageDescs[ n ];
609             if( pPos )
610                 *pPos = n;
611             break;
612         }
613     return pRet;
614 }
615 
616 /******************************************************************************
617  *  Methode     :   void SwDoc::PrtDataChanged()
618  *  Beschreibung:
619  *  Erstellt    :   OK 27.10.94 10:20
620  *  Aenderung   :   MA 26. Mar. 98
621  ******************************************************************************/
622 
623 void SwDoc::PrtDataChanged()
624 {
625 //!!!!!!!! Bei Aenderungen hier bitte ggf. InJobSetup im Sw3io mitpflegen
626 
627     // --> FME 2005-01-21 #i41075#
628     ASSERT( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) ||
629             0 != getPrinter( sal_False ), "PrtDataChanged will be called recursive!" )
630     // <--
631     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
632     SwWait *pWait = 0;
633     sal_Bool bEndAction = sal_False;
634 
635     if( GetDocShell() )
636         GetDocShell()->UpdateFontList();
637 
638     sal_Bool bDraw = sal_True;
639     if ( pTmpRoot )
640     {
641         ViewShell *pSh = GetCurrentViewShell();
642         if( !pSh->GetViewOptions()->getBrowseMode() ||
643             pSh->GetViewOptions()->IsPrtFormat() )
644         {
645             if ( GetDocShell() )
646                 pWait = new SwWait( *GetDocShell(), sal_True );
647 
648             pTmpRoot->StartAllAction();
649             bEndAction = sal_True;
650 
651             bDraw = sal_False;
652             if( pDrawModel )
653             {
654                 pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
655                 pDrawModel->SetRefDevice( getReferenceDevice( false ) );
656             }
657 
658             pFntCache->Flush();
659 
660             std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
661             std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));//swmod 080304
662 
663             if ( pSh )
664             {
665                 do
666                 {
667                     pSh->InitPrt( pPrt );
668                     pSh = (ViewShell*)pSh->GetNext();
669                 }
670                 while ( pSh != GetCurrentViewShell() );
671             }
672 
673         }
674     }   //swmod 080218
675     if ( bDraw && pDrawModel )
676     {
677         const sal_Bool bTmpAddExtLeading = get(IDocumentSettingAccess::ADD_EXT_LEADING);
678         if ( bTmpAddExtLeading != pDrawModel->IsAddExtLeading() )
679             pDrawModel->SetAddExtLeading( bTmpAddExtLeading );
680 
681         OutputDevice* pOutDev = getReferenceDevice( false );
682         if ( pOutDev != pDrawModel->GetRefDevice() )
683             pDrawModel->SetRefDevice( pOutDev );
684     }
685 
686     PrtOLENotify( sal_True );
687 
688     if ( bEndAction )
689         pTmpRoot->EndAllAction();   //swmod 080218
690     delete pWait;
691 }
692 
693 //Zur Laufzeit sammeln wir die GlobalNames der Server, die keine
694 //Benachrichtigung zu Druckerwechseln wuenschen. Dadurch sparen wir
695 //das Laden vieler Objekte (gluecklicherweise werden obendrein alle
696 //Fremdobjekte unter einer ID abgebuildet). Init und DeInit vom Array
697 //ist in init.cxx zu finden.
698 extern SvPtrarr *pGlobalOLEExcludeList;
699 
700 void SwDoc::PrtOLENotify( sal_Bool bAll )
701 {
702     SwFEShell *pShell = 0;
703     if ( GetCurrentViewShell() )
704     {
705         ViewShell *pSh = GetCurrentViewShell();
706         if ( !pSh->ISA(SwFEShell) )
707             do
708             {   pSh = (ViewShell*)pSh->GetNext();
709             } while ( !pSh->ISA(SwFEShell) &&
710                       pSh != GetCurrentViewShell() );
711 
712         if ( pSh->ISA(SwFEShell) )
713             pShell = (SwFEShell*)pSh;
714     }   //swmod 071107//swmod 071225
715     if ( !pShell )
716     {
717         //Das hat ohne Shell und damit ohne Client keinen Sinn, weil nur darueber
718         //die Kommunikation bezueglich der Groessenaenderung implementiert ist.
719         //Da wir keine Shell haben, merken wir uns diesen unguenstigen
720         //Zustand am Dokument, dies wird dann beim Erzeugen der ersten Shell
721         //nachgeholt.
722         mbOLEPrtNotifyPending = sal_True;
723         if ( bAll )
724             mbAllOLENotify = sal_True;
725     }
726     else
727     {
728         if ( mbAllOLENotify )
729             bAll = sal_True;
730 
731         mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
732 
733         SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), !bAll );
734         if ( pNodes )
735         {
736             ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
737                              0, pNodes->Count(), GetDocShell());
738             GetCurrentLayout()->StartAllAction();   //swmod 080218
739 
740             for( sal_uInt16 i = 0; i < pNodes->Count(); ++i )
741             {
742                 ::SetProgressState( i, GetDocShell() );
743 
744                 SwOLENode* pOLENd = (*pNodes)[i];
745                 pOLENd->SetOLESizeInvalid( sal_False );
746 
747                 //Ersteinmal die Infos laden und festellen ob das Teil nicht
748                 //schon in der Exclude-Liste steht
749                 SvGlobalName aName;
750 
751                 svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject();
752                 if ( xObj.is() )
753                     aName = SvGlobalName( xObj->getClassID() );
754                 else  //Noch nicht geladen
755                 {
756                         // TODO/LATER: retrieve ClassID of an unloaded object
757                         // aName = ????
758                 }
759 
760                 sal_Bool bFound = sal_False;
761                 for ( sal_uInt16 j = 0;
762                       j < pGlobalOLEExcludeList->Count() && !bFound;
763                       ++j )
764                 {
765                     bFound = *(SvGlobalName*)(*pGlobalOLEExcludeList)[j] ==
766                                     aName;
767                 }
768                 if ( bFound )
769                     continue;
770 
771                 //Kennen wir nicht, also muss das Objekt geladen werden.
772                 //Wenn es keine Benachrichtigung wuenscht
773                 if ( xObj.is() )
774                 {
775                     //TODO/LATER: needs MiscStatus for ResizeOnPrinterChange
776                     /*
777                     if ( SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE & xRef->GetMiscStatus())
778                     {
779                         if ( pOLENd->GetFrm() )
780                         {
781                             xObj->OnDocumentPrinterChanged( pPrt );
782                             pShell->CalcAndSetScale( xObj );//Client erzeugen lassen.
783                         }
784                         else
785                             pOLENd->SetOLESizeInvalid( sal_True );
786                     }
787                     else */
788                         pGlobalOLEExcludeList->Insert(
789                                 new SvGlobalName( aName ),
790                                 pGlobalOLEExcludeList->Count() );
791                 }
792             }
793             delete pNodes;
794             GetCurrentLayout()->EndAllAction(); //swmod 080218
795             ::EndProgress( GetDocShell() );
796         }
797     }
798 }
799 
800 IMPL_LINK( SwDoc, DoUpdateModifiedOLE, Timer *, )
801 {
802     SwFEShell* pSh = (SwFEShell*)GetEditShell();
803     if( pSh )
804     {
805         mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
806 
807         SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), true );
808         if( pNodes )
809         {
810             ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
811                              0, pNodes->Count(), GetDocShell());
812             GetCurrentLayout()->StartAllAction();   //swmod 080218
813             SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
814 
815             for( sal_uInt16 i = 0; i < pNodes->Count(); ++i )
816             {
817                 ::SetProgressState( i, GetDocShell() );
818 
819                 SwOLENode* pOLENd = (*pNodes)[i];
820                 pOLENd->SetOLESizeInvalid( sal_False );
821 
822                 //Kennen wir nicht, also muss das Objekt geladen werden.
823                 //Wenn es keine Benachrichtigung wuenscht
824                 if( pOLENd->GetOLEObj().GetOleRef().is() ) //Kaputt?
825                 {
826                     //TODO/LATER: needs MiscStatus for ResizeOnPrinterChange
827                     /*
828                     if( SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE &
829                             xRef->GetMiscStatus() )
830                     {
831                         if( pOLENd->GetFrm() )
832                         {
833                             xRef->OnDocumentPrinterChanged( pPrt );
834                             pSh->CalcAndSetScale( xRef );//Client erzeugen lassen.
835                         }
836                         else
837                             pOLENd->SetOLESizeInvalid( sal_True );
838                     }*/
839                     // repaint it
840                     pOLENd->ModifyNotification( &aMsgHint, &aMsgHint );
841                 }
842             }
843             GetCurrentLayout()->EndAllAction(); //swmod 080218
844             ::EndProgress( GetDocShell() );
845             delete pNodes;
846         }
847     }
848     return 0;
849 }
850 
851 sal_Bool SwDoc::FindPageDesc( const String & rName, sal_uInt16 * pFound)
852 {
853     sal_Bool bResult = sal_False;
854     sal_uInt16 nI;
855     for (nI = 0; nI < aPageDescs.Count(); nI++)
856     {
857         if (aPageDescs[nI]->GetName() == rName)
858         {
859             *pFound = nI;
860             bResult = sal_True;
861             break;
862         }
863     }
864 
865     return bResult;
866 }
867 
868 SwPageDesc * SwDoc::GetPageDesc( const String & rName )
869 {
870     SwPageDesc * aResult = NULL;
871 
872     sal_uInt16 nI;
873 
874     if (FindPageDesc(rName, &nI))
875         aResult = aPageDescs[nI];
876 
877     return aResult;
878 }
879 
880 void SwDoc::DelPageDesc( const String & rName, sal_Bool bBroadcast ) // #116530#
881 {
882     sal_uInt16 nI;
883 
884     if (FindPageDesc(rName, &nI))
885         DelPageDesc(nI, bBroadcast); // #116530#
886 }
887 
888 void SwDoc::ChgPageDesc( const String & rName, const SwPageDesc & rDesc)
889 {
890     sal_uInt16 nI;
891 
892     if (FindPageDesc(rName, &nI))
893         ChgPageDesc(nI, rDesc);
894 }
895 
896 /*
897  * The HTML import cannot resist changing the page descriptions, I don't
898  * know why. This function is meant to check the page descriptors for invalid
899  * values.
900  */
901 void SwDoc::CheckDefaultPageFmt()
902 {
903     for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
904     {
905         SwPageDesc& rDesc = _GetPageDesc( i );
906 
907         SwFrmFmt& rMaster = rDesc.GetMaster();
908         SwFrmFmt& rLeft   = rDesc.GetLeft();
909 
910         const SwFmtFrmSize& rMasterSize  = rMaster.GetFrmSize();
911         const SwFmtFrmSize& rLeftSize    = rLeft.GetFrmSize();
912 
913         const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() ||
914                               LONG_MAX == rMasterSize.GetHeight() ||
915                               LONG_MAX == rLeftSize.GetWidth() ||
916                               LONG_MAX == rLeftSize.GetHeight();
917 
918         if ( bSetSize )
919             lcl_DefaultPageFmt( rDesc.GetPoolFmtId(), rDesc.GetMaster(), rDesc.GetLeft() );
920     }
921 }
922 
923 void SwDoc::SetDefaultPageMode(bool bSquaredPageMode)
924 {
925     if( !bSquaredPageMode == !IsSquaredPageMode() )
926         return;
927 
928     const SwTextGridItem& rGrid =
929                     (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
930     SwTextGridItem aNewGrid = rGrid;
931     aNewGrid.SetSquaredMode(bSquaredPageMode);
932     aNewGrid.Init();
933     SetDefault(aNewGrid);
934 
935     for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
936     {
937         SwPageDesc& rDesc = _GetPageDesc( i );
938 
939         SwFrmFmt& rMaster = rDesc.GetMaster();
940         SwFrmFmt& rLeft = rDesc.GetLeft();
941 
942         SwTextGridItem aGrid((SwTextGridItem&)rMaster.GetFmtAttr(RES_TEXTGRID));
943         aGrid.SwitchPaperMode( bSquaredPageMode );
944         rMaster.SetFmtAttr(aGrid);
945         rLeft.SetFmtAttr(aGrid);
946     }
947 }
948 
949 sal_Bool SwDoc::IsSquaredPageMode() const
950 {
951     const SwTextGridItem& rGrid =
952                         (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
953     return rGrid.IsSquaredMode();
954 }
955