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