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