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