Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <cmdid.h>
21 : #include <svx/svdmodel.hxx>
22 : #include <editeng/ulspitem.hxx>
23 : #include <editeng/paperinf.hxx>
24 : #include <editeng/frmdiritem.hxx>
25 : #include <sfx2/bindings.hxx>
26 : #include <sfx2/dispatch.hxx>
27 : #include <sfx2/printer.hxx>
28 : #include <fmtfsize.hxx>
29 : #include <fmthdft.hxx>
30 : #include <fmtcntnt.hxx>
31 : #include <ftninfo.hxx>
32 : #include <fesh.hxx>
33 : #include <ndole.hxx>
34 : #include <mdiexp.hxx>
35 : #include <doc.hxx>
36 : #include <IDocumentUndoRedo.hxx>
37 : #include <IDocumentFieldsAccess.hxx>
38 : #include <DocumentContentOperationsManager.hxx>
39 : #include <IDocumentState.hxx>
40 : #include <IDocumentLayoutAccess.hxx>
41 : #include <docary.hxx>
42 : #include <rootfrm.hxx>
43 : #include <frmtool.hxx>
44 : #include <poolfmt.hxx>
45 : #include <docsh.hxx>
46 : #include <ftnidx.hxx>
47 : #include <fmtftn.hxx>
48 : #include <txtftn.hxx>
49 : #include <fntcache.hxx>
50 : #include <viewopt.hxx>
51 : #include <fldbas.hxx>
52 : #include <swwait.hxx>
53 : #include <GetMetricVal.hxx>
54 : #include <statstr.hrc>
55 : #include <hints.hxx>
56 : #include <SwUndoPageDesc.hxx>
57 : #include <pagedeschint.hxx>
58 : #include <tgrditem.hxx>
59 : #include <unotools/syslocale.hxx>
60 :
61 : #include <boost/scoped_ptr.hpp>
62 :
63 : using namespace com::sun::star;
64 :
65 6612 : static void lcl_DefaultPageFmt( sal_uInt16 nPoolFmtId,
66 : SwFrmFmt &rFmt1,
67 : SwFrmFmt &rFmt2,
68 : SwFrmFmt &rFmt3,
69 : SwFrmFmt &rFmt4)
70 : {
71 : // --> #i41075# Printer on demand
72 : // This function does not require a printer anymore.
73 : // The default page size is obtained from the application
74 : //locale
75 :
76 6612 : SwFmtFrmSize aFrmSize( ATT_FIX_SIZE );
77 6612 : const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize();
78 6612 : aFrmSize.SetSize( aPhysSize );
79 :
80 : // Prepare for default margins.
81 : // Margins have a default minimum size.
82 : // If the printer forces a larger margins, that's ok too.
83 : // The HTML page desc had A4 as page size always.
84 : // This has been changed to take the page size from the printer.
85 : // Unfortunately, the margins of the HTML page desc are smaller than
86 : // the margins used here in general, so one extra case is required.
87 : // In the long term, this needs to be changed to always keep the
88 : // margins from the page desc.
89 : sal_Int32 nMinTop, nMinBottom, nMinLeft, nMinRight;
90 6612 : if( RES_POOLPAGE_HTML == nPoolFmtId )
91 : {
92 0 : nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 );
93 0 : nMinLeft = nMinRight * 2;
94 : }
95 6612 : else if( MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
96 : {
97 0 : nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; // 2 centimetres
98 : }
99 : else
100 : {
101 6612 : nMinTop = nMinBottom = 1440; // as in MS Word: 1 Inch
102 6612 : nMinLeft = nMinRight = 1800; // 1,25 Inch
103 : }
104 :
105 : // set margins
106 13224 : SvxLRSpaceItem aLR( RES_LR_SPACE );
107 13224 : SvxULSpaceItem aUL( RES_UL_SPACE );
108 :
109 6612 : aUL.SetUpper( (sal_uInt16)nMinTop );
110 6612 : aUL.SetLower( (sal_uInt16)nMinBottom );
111 6612 : aLR.SetRight( nMinRight );
112 6612 : aLR.SetLeft( nMinLeft );
113 :
114 6612 : rFmt1.SetFmtAttr( aFrmSize );
115 6612 : rFmt1.SetFmtAttr( aLR );
116 6612 : rFmt1.SetFmtAttr( aUL );
117 :
118 6612 : rFmt2.SetFmtAttr( aFrmSize );
119 6612 : rFmt2.SetFmtAttr( aLR );
120 6612 : rFmt2.SetFmtAttr( aUL );
121 :
122 6612 : rFmt3.SetFmtAttr( aFrmSize );
123 6612 : rFmt3.SetFmtAttr( aLR );
124 6612 : rFmt3.SetFmtAttr( aUL );
125 :
126 6612 : rFmt4.SetFmtAttr( aFrmSize );
127 6612 : rFmt4.SetFmtAttr( aLR );
128 13224 : rFmt4.SetFmtAttr( aUL );
129 6612 : }
130 :
131 81630 : static void lcl_DescSetAttr( const SwFrmFmt &rSource, SwFrmFmt &rDest,
132 : const bool bPage = true )
133 : {
134 : // We should actually use ItemSet's Intersect here, but that doesn't work
135 : // correctly if we have different WhichRanges.
136 :
137 : // Take over the attributes which are of interest.
138 : sal_uInt16 const aIdArr[] = {
139 : RES_FRM_SIZE, RES_UL_SPACE, // [83..86
140 : RES_BACKGROUND, RES_SHADOW, // [99..101
141 : RES_COL, RES_COL, // [103
142 : RES_TEXTGRID, RES_TEXTGRID, // [109
143 : RES_FRAMEDIR, RES_FRAMEDIR, // [114
144 : RES_HEADER_FOOTER_EAT_SPACING, RES_HEADER_FOOTER_EAT_SPACING, // [115
145 : RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER, // [143
146 :
147 : //UUUU take over DrawingLayer FillStyles
148 : XATTR_FILL_FIRST, XATTR_FILL_LAST, // [1014
149 :
150 81630 : 0};
151 :
152 : const SfxPoolItem* pItem;
153 734670 : for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 )
154 : {
155 3265200 : for( sal_uInt16 nId = aIdArr[ n ]; nId <= aIdArr[ n+1]; ++nId )
156 : {
157 : // #i45539#
158 : // bPage == true:
159 : // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
160 : // bPage == false:
161 : // All in aIdArr except from RES_COL and RES_PAPER_BIN:
162 2612160 : bool bExecuteId(true);
163 :
164 2612160 : if(bPage)
165 : {
166 : // When Page
167 2574080 : switch(nId)
168 : {
169 : // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
170 : case RES_HEADER_FOOTER_EAT_SPACING:
171 : //UUUU take out SvxBrushItem; it's the result of the fallback
172 : // at SwFmt::GetItemState and not really in state SfxItemState::SET
173 : case RES_BACKGROUND:
174 160880 : bExecuteId = false;
175 160880 : break;
176 : default:
177 2413200 : break;
178 : }
179 : }
180 : else
181 : {
182 : // When not Page
183 38080 : switch(nId)
184 : {
185 : // When not Page: All in aIdArr except from RES_COL and RES_PAPER_BIN:
186 : case RES_COL:
187 : case RES_PAPER_BIN:
188 2380 : bExecuteId = false;
189 2380 : break;
190 : default:
191 35700 : break;
192 : }
193 : }
194 :
195 2612160 : if(bExecuteId)
196 : {
197 2448900 : if (SfxItemState::SET == rSource.GetItemState(nId, false, &pItem))
198 : {
199 411276 : rDest.SetFmtAttr(*pItem);
200 : }
201 : else
202 : {
203 2037624 : rDest.ResetFmtAttr(nId);
204 : }
205 : }
206 : }
207 : }
208 :
209 : // Transmit pool and help IDs too
210 81630 : rDest.SetPoolFmtId( rSource.GetPoolFmtId() );
211 81630 : rDest.SetPoolHelpId( rSource.GetPoolHelpId() );
212 81630 : rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() );
213 81630 : }
214 :
215 34530 : void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFmtHeader &rHead, SwPageDesc *pDesc, bool bLeft, bool bFirst)
216 : {
217 : assert(bLeft || bFirst);
218 : SwFrmFmt& rDescFrmFmt = (bFirst)
219 : ? (bLeft) ? pDesc->GetFirstLeft() : pDesc->GetFirstMaster()
220 34530 : : pDesc->GetLeft();
221 34530 : if (bFirst && bLeft)
222 : {
223 : // special case: always shared with something
224 11510 : rDescFrmFmt.SetFmtAttr( rChged.IsFirstShared()
225 11390 : ? pDesc->GetLeft().GetHeader()
226 34410 : : pDesc->GetFirstMaster().GetHeader());
227 : }
228 46040 : else if ((bFirst ? rChged.IsFirstShared() : rChged.IsHeaderShared())
229 46040 : || !rHead.IsActive())
230 : {
231 : // Left or first shares the header with the Master.
232 22248 : rDescFrmFmt.SetFmtAttr( pDesc->GetMaster().GetHeader() );
233 : }
234 772 : else if ( rHead.IsActive() )
235 : { // Left or first gets its own header if the Format doesn't alrady have one.
236 : // If it already has one and it points to the same Section as the
237 : // Right one, it needs to get an own Header.
238 : // The content is evidently copied.
239 772 : const SwFmtHeader &rFmtHead = rDescFrmFmt.GetHeader();
240 772 : if ( !rFmtHead.IsActive() )
241 : {
242 6 : SwFmtHeader aHead( getIDocumentLayoutAccess().MakeLayoutFmt( RND_STD_HEADERL, 0 ) );
243 6 : rDescFrmFmt.SetFmtAttr( aHead );
244 : // take over additional attributes (margins, borders ...)
245 6 : ::lcl_DescSetAttr( *rHead.GetHeaderFmt(), *aHead.GetHeaderFmt(), false);
246 : }
247 : else
248 : {
249 766 : const SwFrmFmt *pRight = rHead.GetHeaderFmt();
250 766 : const SwFmtCntnt &aRCnt = pRight->GetCntnt();
251 766 : const SwFmtCntnt &aCnt = rFmtHead.GetHeaderFmt()->GetCntnt();
252 :
253 766 : if (!aCnt.GetCntntIdx())
254 : {
255 : const SwFrmFmt& rChgedFrmFmt = (bFirst)
256 : ? (bLeft) ? rChged.GetFirstLeft() : rChged.GetFirstMaster()
257 0 : : rChged.GetLeft();
258 0 : rDescFrmFmt.SetFmtAttr( rChgedFrmFmt.GetHeader() );
259 : }
260 1420 : else if ((*aRCnt.GetCntntIdx() == *aCnt.GetCntntIdx()) ||
261 : // The CntntIdx is _always_ different when called from
262 : // SwDocStyleSheet::SetItemSet, because it deep-copies the
263 : // PageDesc. So check if it was previously shared.
264 654 : ((bFirst) ? pDesc->IsFirstShared() : pDesc->IsHeaderShared()))
265 : {
266 : SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(),
267 : (bFirst) ? "First header" : "Left header",
268 112 : GetDfltFrmFmt() );
269 112 : ::lcl_DescSetAttr( *pRight, *pFmt, false );
270 : // The section which the right header attribute is pointing
271 : // is copied, and the Index to the StartNode is set to
272 : // the left or first header attribute.
273 112 : SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
274 112 : SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwHeaderStartNode );
275 112 : SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
276 336 : *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
277 112 : aTmp = *pSttNd->EndOfSectionNode();
278 112 : GetNodes()._Copy( aRange, aTmp, false );
279 112 : aTmp = *pSttNd;
280 112 : GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp);
281 :
282 112 : pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
283 224 : rDescFrmFmt.SetFmtAttr( SwFmtHeader( pFmt ) );
284 : }
285 : else
286 : ::lcl_DescSetAttr( *pRight,
287 654 : *(SwFrmFmt*)rFmtHead.GetHeaderFmt(), false );
288 : }
289 : }
290 34530 : }
291 :
292 34530 : void SwDoc::CopyMasterFooter(const SwPageDesc &rChged, const SwFmtFooter &rFoot, SwPageDesc *pDesc, bool bLeft, bool bFirst)
293 : {
294 : assert(bLeft || bFirst);
295 : SwFrmFmt& rDescFrmFmt = (bFirst)
296 : ? (bLeft) ? pDesc->GetFirstLeft() : pDesc->GetFirstMaster()
297 34530 : : pDesc->GetLeft();
298 34530 : if (bFirst && bLeft)
299 : {
300 : // special case: always shared with something
301 11510 : rDescFrmFmt.SetFmtAttr( rChged.IsFirstShared()
302 11390 : ? pDesc->GetLeft().GetFooter()
303 34410 : : pDesc->GetFirstMaster().GetFooter());
304 : }
305 46040 : else if ((bFirst ? rChged.IsFirstShared() : rChged.IsFooterShared())
306 46040 : || !rFoot.IsActive())
307 : {
308 : // Left or first shares the Header with the Master.
309 22602 : rDescFrmFmt.SetFmtAttr( pDesc->GetMaster().GetFooter() );
310 : }
311 418 : else if ( rFoot.IsActive() )
312 : { // Left or first gets its own Footer if the Format does not already have one.
313 : // If the Format already has a Footer and it points to the same section as the Right one,
314 : // it needs to get an own one.
315 : // The content is evidently copied.
316 418 : const SwFmtFooter &rFmtFoot = rDescFrmFmt.GetFooter();
317 418 : if ( !rFmtFoot.IsActive() )
318 : {
319 12 : SwFmtFooter aFoot( getIDocumentLayoutAccess().MakeLayoutFmt( RND_STD_FOOTER, 0 ) );
320 12 : rDescFrmFmt.SetFmtAttr( aFoot );
321 : // Take over additional attributes (margins, borders ...).
322 12 : ::lcl_DescSetAttr( *rFoot.GetFooterFmt(), *aFoot.GetFooterFmt(), false);
323 : }
324 : else
325 : {
326 406 : const SwFrmFmt *pRight = rFoot.GetFooterFmt();
327 406 : const SwFmtCntnt &aRCnt = pRight->GetCntnt();
328 406 : const SwFmtCntnt &aLCnt = rFmtFoot.GetFooterFmt()->GetCntnt();
329 406 : if( !aLCnt.GetCntntIdx() )
330 : {
331 : const SwFrmFmt& rChgedFrmFmt = (bFirst)
332 : ? (bLeft) ? rChged.GetFirstLeft() : rChged.GetFirstMaster()
333 0 : : rChged.GetLeft();
334 0 : rDescFrmFmt.SetFmtAttr( rChgedFrmFmt.GetFooter() );
335 : }
336 726 : else if ((*aRCnt.GetCntntIdx() == *aLCnt.GetCntntIdx()) ||
337 : // The CntntIdx is _always_ different when called from
338 : // SwDocStyleSheet::SetItemSet, because it deep-copies the
339 : // PageDesc. So check if it was previously shared.
340 320 : ((bFirst) ? pDesc->IsFirstShared() : pDesc->IsFooterShared()))
341 : {
342 : SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(),
343 : (bFirst) ? "First footer" : "Left footer",
344 86 : GetDfltFrmFmt() );
345 86 : ::lcl_DescSetAttr( *pRight, *pFmt, false );
346 : // The section to which the right footer attribute is pointing
347 : // is copied, and the Index to the StartNode is set to
348 : // the left footer attribute.
349 86 : SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
350 86 : SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwFooterStartNode );
351 86 : SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
352 258 : *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
353 86 : aTmp = *pSttNd->EndOfSectionNode();
354 86 : GetNodes()._Copy( aRange, aTmp, false );
355 86 : aTmp = *pSttNd;
356 86 : GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp);
357 :
358 86 : pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
359 172 : rDescFrmFmt.SetFmtAttr( SwFmtFooter( pFmt ) );
360 : }
361 : else
362 : ::lcl_DescSetAttr( *pRight,
363 320 : *(SwFrmFmt*)rFmtFoot.GetFooterFmt(), false );
364 : }
365 : }
366 34530 : }
367 :
368 11510 : void SwDoc::ChgPageDesc( sal_uInt16 i, const SwPageDesc &rChged )
369 : {
370 : OSL_ENSURE( i < maPageDescs.size(), "PageDescs is out of range." );
371 :
372 11510 : SwPageDesc *pDesc = maPageDescs[i];
373 11510 : SwRootFrm* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
374 :
375 11510 : if (GetIDocumentUndoRedo().DoesUndo())
376 : {
377 240 : SwUndo *const pUndo(new SwUndoPageDesc(*pDesc, rChged, this));
378 240 : GetIDocumentUndoRedo().AppendUndo(pUndo);
379 : }
380 11510 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
381 :
382 : // Mirror at first if needed.
383 11510 : if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR )
384 130 : ((SwPageDesc&)rChged).Mirror();
385 : else
386 : {
387 : // Or else transfer values from Master to Left
388 11380 : ::lcl_DescSetAttr(rChged.GetMaster(),
389 22760 : const_cast<SwPageDesc&>(rChged).GetLeft());
390 : }
391 11510 : ::lcl_DescSetAttr(rChged.GetMaster(),
392 23020 : const_cast<SwPageDesc&>(rChged).GetFirstMaster());
393 11510 : ::lcl_DescSetAttr(rChged.GetLeft(),
394 23020 : const_cast<SwPageDesc&>(rChged).GetFirstLeft());
395 :
396 : // Take over NumType.
397 11510 : if( rChged.GetNumType().GetNumberingType() != pDesc->GetNumType().GetNumberingType() )
398 : {
399 0 : pDesc->SetNumType( rChged.GetNumType() );
400 : // Notify page number fields that NumFormat has changed
401 0 : getIDocumentFieldsAccess().GetSysFldType( RES_PAGENUMBERFLD )->UpdateFlds();
402 0 : getIDocumentFieldsAccess().GetSysFldType( RES_REFPAGEGETFLD )->UpdateFlds();
403 :
404 : // If the numbering scheme has changed we could have QuoVadis/ErgoSum texts
405 : // that refer to a changed page, so we invalidate foot notes.
406 0 : SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
407 0 : for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.size(); ++nPos )
408 : {
409 0 : SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
410 0 : const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
411 0 : pTxtFtn->SetNumber(rFtn.GetNumber(), rFtn.GetNumStr());
412 : }
413 : }
414 :
415 : // Take over orientation
416 11510 : pDesc->SetLandscape( rChged.GetLandscape() );
417 :
418 : // #i46909# no undo if header or footer changed
419 11510 : bool bHeaderFooterChanged = false;
420 :
421 : // Synch header.
422 11510 : const SwFmtHeader &rHead = rChged.GetMaster().GetHeader();
423 11510 : if (undoGuard.UndoWasEnabled())
424 : {
425 : // #i46909# no undo if header or footer changed
426 : // Did something change in the nodes?
427 240 : const SwFmtHeader &rOldHead = pDesc->GetMaster().GetHeader();
428 : bHeaderFooterChanged |=
429 480 : ( rHead.IsActive() != rOldHead.IsActive() ||
430 480 : rChged.IsHeaderShared() != pDesc->IsHeaderShared() ||
431 480 : rChged.IsFirstShared() != pDesc->IsFirstShared() );
432 : }
433 11510 : pDesc->GetMaster().SetFmtAttr( rHead );
434 11510 : CopyMasterHeader(rChged, rHead, pDesc, true, false); // Copy left header
435 11510 : CopyMasterHeader(rChged, rHead, pDesc, false, true); // Copy first master
436 11510 : CopyMasterHeader(rChged, rHead, pDesc, true, true); // Copy first left
437 11510 : pDesc->ChgHeaderShare( rChged.IsHeaderShared() );
438 :
439 : // Synch Footer.
440 11510 : const SwFmtFooter &rFoot = rChged.GetMaster().GetFooter();
441 11510 : if (undoGuard.UndoWasEnabled())
442 : {
443 : // #i46909# no undo if header or footer changed
444 : // Did something change in the Nodes?
445 240 : const SwFmtFooter &rOldFoot = pDesc->GetMaster().GetFooter();
446 : bHeaderFooterChanged |=
447 480 : ( rFoot.IsActive() != rOldFoot.IsActive() ||
448 480 : rChged.IsFooterShared() != pDesc->IsFooterShared() );
449 : }
450 11510 : pDesc->GetMaster().SetFmtAttr( rFoot );
451 11510 : CopyMasterFooter(rChged, rFoot, pDesc, true, false); // Copy left footer
452 11510 : CopyMasterFooter(rChged, rFoot, pDesc, false, true); // Copy first master
453 11510 : CopyMasterFooter(rChged, rFoot, pDesc, true, true); // Copy first left
454 11510 : pDesc->ChgFooterShare( rChged.IsFooterShared() );
455 : // there is just one first shared flag for both header and footer?
456 11510 : pDesc->ChgFirstShare( rChged.IsFirstShared() );
457 :
458 11510 : if ( pDesc->GetName() != rChged.GetName() )
459 4 : pDesc->SetName( rChged.GetName() );
460 :
461 : // A RegisterChange is triggered, if necessary
462 11510 : pDesc->SetRegisterFmtColl( rChged.GetRegisterFmtColl() );
463 :
464 : // If UseOn or the Follow change, the paragraphs need to know about it.
465 11510 : bool bUseOn = false;
466 11510 : bool bFollow = false;
467 11510 : if ( pDesc->GetUseOn() != rChged.GetUseOn() )
468 96 : { pDesc->SetUseOn( rChged.GetUseOn() );
469 96 : bUseOn = true;
470 : }
471 11510 : if ( pDesc->GetFollow() != rChged.GetFollow() )
472 76 : { if ( rChged.GetFollow() == &rChged )
473 0 : { if ( pDesc->GetFollow() != pDesc )
474 0 : { pDesc->SetFollow( pDesc );
475 0 : bFollow = true;
476 : }
477 : }
478 : else
479 76 : { pDesc->SetFollow( rChged.pFollow );
480 76 : bFollow = true;
481 : }
482 : }
483 :
484 11510 : if ( (bUseOn || bFollow) && pTmpRoot)
485 : // Inform layout!
486 : {
487 18 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
488 18 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));
489 : }
490 :
491 : // Take over the page attributes.
492 11510 : ::lcl_DescSetAttr( rChged.GetMaster(), pDesc->GetMaster() );
493 11510 : ::lcl_DescSetAttr( rChged.GetLeft(), pDesc->GetLeft() );
494 11510 : ::lcl_DescSetAttr( rChged.GetFirstMaster(), pDesc->GetFirstMaster() );
495 11510 : ::lcl_DescSetAttr( rChged.GetFirstLeft(), pDesc->GetFirstLeft() );
496 :
497 : // If the FootnoteInfo changes, the pages are triggered.
498 11510 : if( !(pDesc->GetFtnInfo() == rChged.GetFtnInfo()) )
499 : {
500 3972 : pDesc->SetFtnInfo( rChged.GetFtnInfo() );
501 3972 : SwMsgPoolItem aInfo( RES_PAGEDESC_FTNINFO );
502 : {
503 3972 : pDesc->GetMaster().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
504 : }
505 : {
506 3972 : pDesc->GetLeft().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
507 : }
508 : {
509 3972 : pDesc->GetFirstMaster().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
510 : }
511 : {
512 3972 : pDesc->GetFirstLeft().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
513 3972 : }
514 : }
515 11510 : getIDocumentState().SetModified();
516 :
517 : // #i46909# no undo if header or footer changed
518 11510 : if( bHeaderFooterChanged )
519 : {
520 0 : GetIDocumentUndoRedo().DelAllUndoObj();
521 : }
522 :
523 : SfxBindings* pBindings =
524 11510 : ( GetDocShell() && GetDocShell()->GetDispatcher() ) ? GetDocShell()->GetDispatcher()->GetBindings() : 0;
525 11510 : if ( pBindings )
526 : {
527 768 : pBindings->Invalidate( SID_ATTR_PAGE_COLUMN );
528 768 : pBindings->Invalidate( SID_ATTR_PAGE );
529 768 : pBindings->Invalidate( SID_ATTR_PAGE_SIZE );
530 768 : pBindings->Invalidate( SID_ATTR_PAGE_ULSPACE );
531 768 : pBindings->Invalidate( SID_ATTR_PAGE_LRSPACE );
532 : }
533 :
534 : //h/f of first-left page must not be unique but same as first master or left
535 : assert((pDesc->IsFirstShared())
536 : ? pDesc->GetFirstLeft().GetHeader().GetHeaderFmt() == pDesc->GetLeft().GetHeader().GetHeaderFmt()
537 : : pDesc->GetFirstLeft().GetHeader().GetHeaderFmt() == pDesc->GetFirstMaster().GetHeader().GetHeaderFmt());
538 : assert((pDesc->IsFirstShared())
539 : ? pDesc->GetFirstLeft().GetFooter().GetFooterFmt() == pDesc->GetLeft().GetFooter().GetFooterFmt()
540 11510 : : pDesc->GetFirstLeft().GetFooter().GetFooterFmt() == pDesc->GetFirstMaster().GetFooter().GetFooterFmt());
541 11510 : }
542 :
543 : /// All descriptors whose Follow point to the to-be-deleted have to be adapted.
544 : // #i7983#
545 10556 : void SwDoc::PreDelPageDesc(SwPageDesc * pDel)
546 : {
547 10556 : if (0 == pDel)
548 10556 : return;
549 :
550 : // mba: test iteration as clients are removed while iteration
551 10556 : SwPageDescHint aHint( maPageDescs[0] );
552 10556 : pDel->CallSwClientNotify( aHint );
553 :
554 10556 : bool bHasLayout = getIDocumentLayoutAccess().HasLayout();
555 10556 : if ( mpFtnInfo->DependsOn( pDel ) )
556 : {
557 0 : mpFtnInfo->ChgPageDesc( maPageDescs[0] );
558 0 : if ( bHasLayout )
559 : {
560 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
561 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), false));
562 : }
563 : }
564 10556 : else if ( mpEndNoteInfo->DependsOn( pDel ) )
565 : {
566 0 : mpEndNoteInfo->ChgPageDesc( maPageDescs[0] );
567 0 : if ( bHasLayout )
568 : {
569 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
570 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), true));
571 : }
572 : }
573 :
574 36078 : for ( sal_uInt16 j = 0; j < maPageDescs.size(); ++j )
575 : {
576 25522 : if ( maPageDescs[j]->GetFollow() == pDel )
577 : {
578 38 : maPageDescs[j]->SetFollow( 0 );
579 38 : if( bHasLayout )
580 : {
581 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
582 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));
583 : }
584 : }
585 10556 : }
586 : }
587 :
588 0 : void SwDoc::BroadcastStyleOperation(const OUString& rName, SfxStyleFamily eFamily,
589 : sal_uInt16 nOp)
590 : {
591 0 : if (mpDocShell)
592 : {
593 0 : SfxStyleSheetBasePool * pPool = mpDocShell->GetStyleSheetPool();
594 :
595 0 : if (pPool)
596 : {
597 0 : pPool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
598 0 : SfxStyleSheetBase * pBase = pPool->Find(rName);
599 :
600 0 : if (pBase != NULL)
601 0 : pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase ));
602 : }
603 : }
604 0 : }
605 :
606 38 : void SwDoc::DelPageDesc( sal_uInt16 i, bool bBroadcast )
607 : {
608 : OSL_ENSURE( i < maPageDescs.size(), "PageDescs is out of range." );
609 : OSL_ENSURE( i != 0, "You cannot delete the default Pagedesc.");
610 38 : if ( i == 0 )
611 38 : return;
612 :
613 38 : SwPageDesc *pDel = maPageDescs[i];
614 :
615 38 : if (bBroadcast)
616 : BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PAGE,
617 0 : SFX_STYLESHEET_ERASED);
618 :
619 38 : if (GetIDocumentUndoRedo().DoesUndo())
620 : {
621 0 : SwUndo *const pUndo(new SwUndoPageDescDelete(*pDel, this));
622 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
623 : }
624 :
625 38 : PreDelPageDesc(pDel); // #i7983#
626 :
627 38 : maPageDescs.erase( maPageDescs.begin() + i );
628 38 : delete pDel;
629 38 : getIDocumentState().SetModified();
630 : }
631 :
632 6612 : SwPageDesc* SwDoc::MakePageDesc(const OUString &rName, const SwPageDesc *pCpy,
633 : bool bRegardLanguage, bool bBroadcast)
634 : {
635 : SwPageDesc *pNew;
636 6612 : if( pCpy )
637 : {
638 0 : pNew = new SwPageDesc( *pCpy );
639 0 : pNew->SetName( rName );
640 0 : if( rName != pCpy->GetName() )
641 : {
642 0 : pNew->SetPoolFmtId( USHRT_MAX );
643 0 : pNew->SetPoolHelpId( USHRT_MAX );
644 0 : pNew->SetPoolHlpFileId( UCHAR_MAX );
645 : }
646 : }
647 : else
648 : {
649 6612 : pNew = new SwPageDesc( rName, GetDfltFrmFmt(), this );
650 : // Set the default page format.
651 6612 : lcl_DefaultPageFmt( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft(), pNew->GetFirstMaster(), pNew->GetFirstLeft() );
652 :
653 : SvxFrameDirection aFrameDirection = bRegardLanguage ?
654 6570 : GetDefaultFrameDirection(GetAppLanguage())
655 13182 : : FRMDIR_HORI_LEFT_TOP;
656 :
657 6612 : pNew->GetMaster().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
658 6612 : pNew->GetLeft().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
659 6612 : pNew->GetFirstMaster().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
660 6612 : pNew->GetFirstLeft().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
661 : }
662 6612 : maPageDescs.push_back( pNew );
663 :
664 6612 : if (bBroadcast)
665 : BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PAGE,
666 0 : SFX_STYLESHEET_CREATED);
667 :
668 6612 : if (GetIDocumentUndoRedo().DoesUndo())
669 : {
670 122 : GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this));
671 : }
672 :
673 6612 : getIDocumentState().SetModified();
674 6612 : return pNew;
675 : }
676 :
677 62088 : SwPageDesc* SwDoc::FindPageDesc(const OUString& rName, sal_uInt16* pPos) const
678 : {
679 62088 : SwPageDesc* pRet = NULL;
680 62088 : if( pPos ) *pPos = USHRT_MAX;
681 :
682 154255 : for( sal_uInt16 n = 0, nEnd = maPageDescs.size(); n < nEnd; ++n )
683 139295 : if( maPageDescs[ n ]->HasName( rName ) )
684 : {
685 47128 : pRet = maPageDescs[ n ];
686 47128 : if( pPos )
687 11418 : *pPos = n;
688 47128 : break;
689 : }
690 62088 : return pRet;
691 : }
692 :
693 : // We collect the GlobalNames of the servers at runtime, who don't want to be notified
694 : // about printer changes. Thereby saving loading a lot of objects (luckily all foreign
695 : // objects are mapped to one ID).
696 : // Initialisation and deinitialisation can be found in init.cxx
697 : extern std::vector<SvGlobalName*> *pGlobalOLEExcludeList;
698 :
699 186 : void SwDoc::PrtOLENotify( bool bAll )
700 : {
701 186 : SwFEShell *pShell = 0;
702 186 : if ( getIDocumentLayoutAccess().GetCurrentViewShell() )
703 : {
704 136 : SwViewShell *pSh = getIDocumentLayoutAccess().GetCurrentViewShell();
705 136 : if ( !pSh->ISA(SwFEShell) )
706 0 : do
707 0 : { pSh = (SwViewShell*)pSh->GetNext();
708 0 : } while ( !pSh->ISA(SwFEShell) &&
709 0 : pSh != getIDocumentLayoutAccess().GetCurrentViewShell() );
710 :
711 136 : if ( pSh->ISA(SwFEShell) )
712 136 : pShell = (SwFEShell*)pSh;
713 : }
714 186 : if ( !pShell )
715 : {
716 : // This doesn't make sense without a Shell and thus without a client, because
717 : // the communication about size changes is implemented by these components.
718 : // Because we don't have a Shell we remember this unfortunate situation
719 : // in the document,
720 : // which is made up for later on when creating the first Shell.
721 50 : mbOLEPrtNotifyPending = true;
722 50 : if ( bAll )
723 50 : mbAllOLENotify = true;
724 : }
725 : else
726 : {
727 136 : if ( mbAllOLENotify )
728 12 : bAll = true;
729 :
730 136 : mbOLEPrtNotifyPending = mbAllOLENotify = false;
731 :
732 136 : SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), !bAll );
733 136 : if ( pNodes )
734 : {
735 : ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
736 8 : 0, pNodes->size(), GetDocShell());
737 8 : getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
738 :
739 18 : for( sal_uInt16 i = 0; i < pNodes->size(); ++i )
740 : {
741 10 : ::SetProgressState( i, GetDocShell() );
742 :
743 10 : SwOLENode* pOLENd = (*pNodes)[i];
744 10 : pOLENd->SetOLESizeInvalid( false );
745 :
746 : // At first load the Infos and see if it's not already in the exclude list.
747 10 : SvGlobalName aName;
748 :
749 10 : svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject();
750 10 : if ( xObj.is() )
751 10 : aName = SvGlobalName( xObj->getClassID() );
752 : else // Not yet loaded
753 : {
754 : // TODO/LATER: retrieve ClassID of an unloaded object
755 : // aName = ????
756 : }
757 :
758 10 : bool bFound = false;
759 36 : for ( sal_uInt16 j = 0;
760 18 : j < pGlobalOLEExcludeList->size() && !bFound;
761 : ++j )
762 : {
763 8 : bFound = *(*pGlobalOLEExcludeList)[j] == aName;
764 : }
765 10 : if ( bFound )
766 8 : continue;
767 :
768 : // We don't know it, so the object has to be loaded.
769 : // If it doesn't want to be informed
770 2 : if ( xObj.is() )
771 : {
772 2 : pGlobalOLEExcludeList->push_back( new SvGlobalName( aName ) );
773 : }
774 2 : }
775 8 : delete pNodes;
776 8 : getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
777 8 : ::EndProgress( GetDocShell() );
778 : }
779 : }
780 186 : }
781 :
782 0 : IMPL_LINK( SwDoc, DoUpdateModifiedOLE, Timer *, )
783 : {
784 0 : SwFEShell* pSh = (SwFEShell*)GetEditShell();
785 0 : if( pSh )
786 : {
787 0 : mbOLEPrtNotifyPending = mbAllOLENotify = false;
788 :
789 0 : SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), true );
790 0 : if( pNodes )
791 : {
792 : ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
793 0 : 0, pNodes->size(), GetDocShell());
794 0 : getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
795 0 : SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
796 :
797 0 : for( sal_uInt16 i = 0; i < pNodes->size(); ++i )
798 : {
799 0 : ::SetProgressState( i, GetDocShell() );
800 :
801 0 : SwOLENode* pOLENd = (*pNodes)[i];
802 0 : pOLENd->SetOLESizeInvalid( false );
803 :
804 : // We don't know it, so the object has to be loaded.
805 : // If it doesn't want to be informed
806 0 : if( pOLENd->GetOLEObj().GetOleRef().is() ) // Broken?
807 : {
808 0 : pOLENd->ModifyNotification( &aMsgHint, &aMsgHint );
809 : }
810 : }
811 0 : getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
812 0 : ::EndProgress( GetDocShell() );
813 0 : delete pNodes;
814 : }
815 : }
816 0 : return 0;
817 : }
818 :
819 0 : SwPageDesc * SwDoc::GetPageDesc( const OUString & rName )
820 : {
821 0 : return FindPageDesc(rName);
822 : }
823 :
824 0 : void SwDoc::DelPageDesc( const OUString & rName, bool bBroadcast )
825 : {
826 : sal_uInt16 nI;
827 :
828 0 : if (FindPageDesc(rName, &nI))
829 0 : DelPageDesc(nI, bBroadcast);
830 0 : }
831 :
832 4 : void SwDoc::ChgPageDesc( const OUString & rName, const SwPageDesc & rDesc)
833 : {
834 : sal_uInt16 nI;
835 :
836 4 : if (FindPageDesc(rName, &nI))
837 4 : ChgPageDesc(nI, rDesc);
838 4 : }
839 :
840 : /*
841 : * The HTML import cannot resist changing the page descriptions, I don't
842 : * know why. This function is meant to check the page descriptors for invalid
843 : * values.
844 : */
845 5316 : void SwDoc::CheckDefaultPageFmt()
846 : {
847 11790 : for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
848 : {
849 6474 : SwPageDesc& rDesc = GetPageDesc( i );
850 :
851 6474 : SwFrmFmt& rMaster = rDesc.GetMaster();
852 6474 : SwFrmFmt& rLeft = rDesc.GetLeft();
853 :
854 6474 : const SwFmtFrmSize& rMasterSize = rMaster.GetFrmSize();
855 6474 : const SwFmtFrmSize& rLeftSize = rLeft.GetFrmSize();
856 :
857 12948 : const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() ||
858 12948 : LONG_MAX == rMasterSize.GetHeight() ||
859 19422 : LONG_MAX == rLeftSize.GetWidth() ||
860 12948 : LONG_MAX == rLeftSize.GetHeight();
861 :
862 6474 : if ( bSetSize )
863 0 : lcl_DefaultPageFmt( rDesc.GetPoolFmtId(), rDesc.GetMaster(), rDesc.GetLeft(), rDesc.GetFirstMaster(), rDesc.GetFirstLeft() );
864 : }
865 5316 : }
866 :
867 8722 : void SwDoc::SetDefaultPageMode(bool bSquaredPageMode)
868 : {
869 8722 : if( !bSquaredPageMode == !IsSquaredPageMode() )
870 13868 : return;
871 :
872 : const SwTextGridItem& rGrid =
873 3576 : (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
874 3576 : SwTextGridItem aNewGrid = rGrid;
875 3576 : aNewGrid.SetSquaredMode(bSquaredPageMode);
876 3576 : aNewGrid.Init();
877 3576 : SetDefault(aNewGrid);
878 :
879 7596 : for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
880 : {
881 4020 : SwPageDesc& rDesc = GetPageDesc( i );
882 :
883 4020 : SwFrmFmt& rMaster = rDesc.GetMaster();
884 4020 : SwFrmFmt& rLeft = rDesc.GetLeft();
885 :
886 4020 : SwTextGridItem aGrid((SwTextGridItem&)rMaster.GetFmtAttr(RES_TEXTGRID));
887 4020 : aGrid.SwitchPaperMode( bSquaredPageMode );
888 4020 : rMaster.SetFmtAttr(aGrid);
889 4020 : rLeft.SetFmtAttr(aGrid);
890 7596 : }
891 : }
892 :
893 216397 : bool SwDoc::IsSquaredPageMode() const
894 : {
895 : const SwTextGridItem& rGrid =
896 216397 : (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
897 216397 : return rGrid.IsSquaredMode();
898 270 : }
899 :
900 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|