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 69380 : static void lcl_DefaultPageFormat( sal_uInt16 nPoolFormatId,
66 : SwFrameFormat &rFormat1,
67 : SwFrameFormat &rFormat2,
68 : SwFrameFormat &rFormat3,
69 : SwFrameFormat &rFormat4)
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 69380 : SwFormatFrmSize aFrmSize( ATT_FIX_SIZE );
77 69380 : const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize();
78 69380 : 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 69380 : if( RES_POOLPAGE_HTML == nPoolFormatId )
91 : {
92 0 : nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 );
93 0 : nMinLeft = nMinRight * 2;
94 : }
95 69380 : else if( MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
96 : {
97 0 : nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; // 2 centimetres
98 : }
99 : else
100 : {
101 69380 : nMinTop = nMinBottom = 1440; // as in MS Word: 1 Inch
102 69380 : nMinLeft = nMinRight = 1800; // 1,25 Inch
103 : }
104 :
105 : // set margins
106 138760 : SvxLRSpaceItem aLR( RES_LR_SPACE );
107 138760 : SvxULSpaceItem aUL( RES_UL_SPACE );
108 :
109 69380 : aUL.SetUpper( (sal_uInt16)nMinTop );
110 69380 : aUL.SetLower( (sal_uInt16)nMinBottom );
111 69380 : aLR.SetRight( nMinRight );
112 69380 : aLR.SetLeft( nMinLeft );
113 :
114 69380 : rFormat1.SetFormatAttr( aFrmSize );
115 69380 : rFormat1.SetFormatAttr( aLR );
116 69380 : rFormat1.SetFormatAttr( aUL );
117 :
118 69380 : rFormat2.SetFormatAttr( aFrmSize );
119 69380 : rFormat2.SetFormatAttr( aLR );
120 69380 : rFormat2.SetFormatAttr( aUL );
121 :
122 69380 : rFormat3.SetFormatAttr( aFrmSize );
123 69380 : rFormat3.SetFormatAttr( aLR );
124 69380 : rFormat3.SetFormatAttr( aUL );
125 :
126 69380 : rFormat4.SetFormatAttr( aFrmSize );
127 69380 : rFormat4.SetFormatAttr( aLR );
128 138760 : rFormat4.SetFormatAttr( aUL );
129 69380 : }
130 :
131 57283 : static void lcl_DescSetAttr( const SwFrameFormat &rSource, SwFrameFormat &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 57283 : 0};
151 :
152 : const SfxPoolItem* pItem;
153 515547 : for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 )
154 : {
155 2291320 : 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 1833056 : bool bExecuteId(true);
163 :
164 1833056 : if(bPage)
165 : {
166 : // When Page
167 1812096 : 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 SwFormat::GetItemState and not really in state SfxItemState::SET
173 : case RES_BACKGROUND:
174 113256 : bExecuteId = false;
175 113256 : break;
176 : default:
177 1698840 : break;
178 : }
179 : }
180 : else
181 : {
182 : // When not Page
183 20960 : 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 1310 : bExecuteId = false;
189 1310 : break;
190 : default:
191 19650 : break;
192 : }
193 : }
194 :
195 1833056 : if(bExecuteId)
196 : {
197 1718490 : if (SfxItemState::SET == rSource.GetItemState(nId, false, &pItem))
198 : {
199 436088 : rDest.SetFormatAttr(*pItem);
200 : }
201 : else
202 : {
203 1282402 : rDest.ResetFormatAttr(nId);
204 : }
205 : }
206 : }
207 : }
208 :
209 : // Transmit pool and help IDs too
210 57283 : rDest.SetPoolFormatId( rSource.GetPoolFormatId() );
211 57283 : rDest.SetPoolHelpId( rSource.GetPoolHelpId() );
212 57283 : rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() );
213 57283 : }
214 :
215 : namespace
216 : {
217 48702 : SwFrameFormat& getFrameFormat(SwPageDesc &rDesc, bool bLeft, bool bFirst)
218 : {
219 48702 : if (bFirst)
220 : {
221 32468 : if (bLeft)
222 16234 : return rDesc.GetFirstLeft();
223 16234 : return rDesc.GetFirstMaster();
224 : }
225 16234 : return rDesc.GetLeft();
226 : }
227 :
228 0 : const SwFrameFormat& getConstFrameFormat(const SwPageDesc &rDesc, bool bLeft, bool bFirst)
229 : {
230 0 : return getFrameFormat(const_cast<SwPageDesc&>(rDesc), bLeft, bFirst);
231 : }
232 : }
233 :
234 24351 : void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &rDesc, bool bLeft, bool bFirst)
235 : {
236 : assert(bLeft || bFirst);
237 24351 : SwFrameFormat& rDescFrameFormat = getFrameFormat(rDesc, bLeft, bFirst);
238 24351 : if (bFirst && bLeft)
239 : {
240 : // special case: always shared with something
241 8117 : rDescFrameFormat.SetFormatAttr( rChged.IsFirstShared()
242 8057 : ? rDesc.GetLeft().GetHeader()
243 24291 : : rDesc.GetFirstMaster().GetHeader());
244 : }
245 32468 : else if ((bFirst ? rChged.IsFirstShared() : rChged.IsHeaderShared())
246 32468 : || !rHead.IsActive())
247 : {
248 : // Left or first shares the header with the Master.
249 15848 : rDescFrameFormat.SetFormatAttr( rDesc.GetMaster().GetHeader() );
250 : }
251 386 : else if ( rHead.IsActive() )
252 : { // Left or first gets its own header if the Format doesn't alrady have one.
253 : // If it already has one and it points to the same Section as the
254 : // Right one, it needs to get an own Header.
255 : // The content is evidently copied.
256 386 : const SwFormatHeader &rFormatHead = rDescFrameFormat.GetHeader();
257 386 : if ( !rFormatHead.IsActive() )
258 : {
259 3 : SwFormatHeader aHead( getIDocumentLayoutAccess().MakeLayoutFormat( RND_STD_HEADERL, 0 ) );
260 3 : rDescFrameFormat.SetFormatAttr( aHead );
261 : // take over additional attributes (margins, borders ...)
262 3 : ::lcl_DescSetAttr( *rHead.GetHeaderFormat(), *aHead.GetHeaderFormat(), false);
263 : }
264 : else
265 : {
266 383 : const SwFrameFormat *pRight = rHead.GetHeaderFormat();
267 383 : const SwFormatContent &aRCnt = pRight->GetContent();
268 383 : const SwFormatContent &aCnt = rFormatHead.GetHeaderFormat()->GetContent();
269 :
270 383 : if (!aCnt.GetContentIdx())
271 : {
272 0 : const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst);
273 0 : rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetHeader() );
274 : }
275 708 : else if ((*aRCnt.GetContentIdx() == *aCnt.GetContentIdx()) ||
276 : // The ContentIdx is _always_ different when called from
277 : // SwDocStyleSheet::SetItemSet, because it deep-copies the
278 : // PageDesc. So check if it was previously shared.
279 325 : ((bFirst) ? rDesc.IsFirstShared() : rDesc.IsHeaderShared()))
280 : {
281 : SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(),
282 : (bFirst) ? "First header" : "Left header",
283 58 : GetDfltFrameFormat() );
284 58 : ::lcl_DescSetAttr( *pRight, *pFormat, false );
285 : // The section which the right header attribute is pointing
286 : // is copied, and the Index to the StartNode is set to
287 : // the left or first header attribute.
288 58 : SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
289 58 : SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwHeaderStartNode );
290 58 : SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), 0,
291 174 : *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() );
292 58 : aTmp = *pSttNd->EndOfSectionNode();
293 58 : GetNodes()._Copy( aRange, aTmp, false );
294 58 : aTmp = *pSttNd;
295 58 : GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp);
296 :
297 58 : pFormat->SetFormatAttr( SwFormatContent( pSttNd ) );
298 116 : rDescFrameFormat.SetFormatAttr( SwFormatHeader( pFormat ) );
299 : }
300 : else
301 : ::lcl_DescSetAttr( *pRight,
302 325 : *const_cast<SwFrameFormat*>(rFormatHead.GetHeaderFormat()), false );
303 : }
304 : }
305 24351 : }
306 :
307 24351 : void SwDoc::CopyMasterFooter(const SwPageDesc &rChged, const SwFormatFooter &rFoot, SwPageDesc &rDesc, bool bLeft, bool bFirst)
308 : {
309 : assert(bLeft || bFirst);
310 24351 : SwFrameFormat& rDescFrameFormat = getFrameFormat(rDesc, bLeft, bFirst);
311 24351 : if (bFirst && bLeft)
312 : {
313 : // special case: always shared with something
314 8117 : rDescFrameFormat.SetFormatAttr( rChged.IsFirstShared()
315 8057 : ? rDesc.GetLeft().GetFooter()
316 24291 : : rDesc.GetFirstMaster().GetFooter());
317 : }
318 32468 : else if ((bFirst ? rChged.IsFirstShared() : rChged.IsFooterShared())
319 32468 : || !rFoot.IsActive())
320 : {
321 : // Left or first shares the Header with the Master.
322 15965 : rDescFrameFormat.SetFormatAttr( rDesc.GetMaster().GetFooter() );
323 : }
324 269 : else if ( rFoot.IsActive() )
325 : { // Left or first gets its own Footer if the Format does not already have one.
326 : // If the Format already has a Footer and it points to the same section as the Right one,
327 : // it needs to get an own one.
328 : // The content is evidently copied.
329 269 : const SwFormatFooter &rFormatFoot = rDescFrameFormat.GetFooter();
330 269 : if ( !rFormatFoot.IsActive() )
331 : {
332 6 : SwFormatFooter aFoot( getIDocumentLayoutAccess().MakeLayoutFormat( RND_STD_FOOTER, 0 ) );
333 6 : rDescFrameFormat.SetFormatAttr( aFoot );
334 : // Take over additional attributes (margins, borders ...).
335 6 : ::lcl_DescSetAttr( *rFoot.GetFooterFormat(), *aFoot.GetFooterFormat(), false);
336 : }
337 : else
338 : {
339 263 : const SwFrameFormat *pRight = rFoot.GetFooterFormat();
340 263 : const SwFormatContent &aRCnt = pRight->GetContent();
341 263 : const SwFormatContent &aLCnt = rFormatFoot.GetFooterFormat()->GetContent();
342 263 : if( !aLCnt.GetContentIdx() )
343 : {
344 0 : const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst);
345 0 : rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetFooter() );
346 : }
347 474 : else if ((*aRCnt.GetContentIdx() == *aLCnt.GetContentIdx()) ||
348 : // The ContentIdx is _always_ different when called from
349 : // SwDocStyleSheet::SetItemSet, because it deep-copies the
350 : // PageDesc. So check if it was previously shared.
351 211 : ((bFirst) ? rDesc.IsFirstShared() : rDesc.IsFooterShared()))
352 : {
353 : SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(),
354 : (bFirst) ? "First footer" : "Left footer",
355 52 : GetDfltFrameFormat() );
356 52 : ::lcl_DescSetAttr( *pRight, *pFormat, false );
357 : // The section to which the right footer attribute is pointing
358 : // is copied, and the Index to the StartNode is set to
359 : // the left footer attribute.
360 52 : SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
361 52 : SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwFooterStartNode );
362 52 : SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), 0,
363 156 : *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() );
364 52 : aTmp = *pSttNd->EndOfSectionNode();
365 52 : GetNodes()._Copy( aRange, aTmp, false );
366 52 : aTmp = *pSttNd;
367 52 : GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp);
368 :
369 52 : pFormat->SetFormatAttr( SwFormatContent( pSttNd ) );
370 104 : rDescFrameFormat.SetFormatAttr( SwFormatFooter( pFormat ) );
371 : }
372 : else
373 : ::lcl_DescSetAttr( *pRight,
374 211 : *const_cast<SwFrameFormat*>(rFormatFoot.GetFooterFormat()), false );
375 : }
376 : }
377 24351 : }
378 :
379 8117 : void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged )
380 : {
381 : OSL_ENSURE( i < maPageDescs.size(), "PageDescs is out of range." );
382 :
383 8117 : SwPageDesc& rDesc = maPageDescs[i];
384 8117 : SwRootFrm* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
385 :
386 8117 : if (GetIDocumentUndoRedo().DoesUndo())
387 : {
388 117 : SwUndo *const pUndo(new SwUndoPageDesc(rDesc, rChged, this));
389 117 : GetIDocumentUndoRedo().AppendUndo(pUndo);
390 : }
391 8117 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
392 :
393 : // Mirror at first if needed.
394 8117 : if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR )
395 191 : const_cast<SwPageDesc&>(rChged).Mirror();
396 : else
397 : {
398 : // Or else transfer values from Master to Left
399 7926 : ::lcl_DescSetAttr(rChged.GetMaster(),
400 15852 : const_cast<SwPageDesc&>(rChged).GetLeft());
401 : }
402 8117 : ::lcl_DescSetAttr(rChged.GetMaster(),
403 16234 : const_cast<SwPageDesc&>(rChged).GetFirstMaster());
404 8117 : ::lcl_DescSetAttr(rChged.GetLeft(),
405 16234 : const_cast<SwPageDesc&>(rChged).GetFirstLeft());
406 :
407 : // Take over NumType.
408 8117 : if( rChged.GetNumType().GetNumberingType() != rDesc.GetNumType().GetNumberingType() )
409 : {
410 6 : rDesc.SetNumType( rChged.GetNumType() );
411 : // Notify page number fields that NumFormat has changed
412 6 : getIDocumentFieldsAccess().GetSysFieldType( RES_PAGENUMBERFLD )->UpdateFields();
413 6 : getIDocumentFieldsAccess().GetSysFieldType( RES_REFPAGEGETFLD )->UpdateFields();
414 :
415 : // If the numbering scheme has changed we could have QuoVadis/ErgoSum texts
416 : // that refer to a changed page, so we invalidate foot notes.
417 6 : SwFootnoteIdxs& rFootnoteIdxs = GetFootnoteIdxs();
418 6 : for( SwFootnoteIdxs::size_type nPos = 0; nPos < rFootnoteIdxs.size(); ++nPos )
419 : {
420 0 : SwTextFootnote *pTextFootnote = rFootnoteIdxs[ nPos ];
421 0 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
422 0 : pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumStr());
423 : }
424 : }
425 :
426 : // Take over orientation
427 8117 : rDesc.SetLandscape( rChged.GetLandscape() );
428 :
429 : // #i46909# no undo if header or footer changed
430 8117 : bool bHeaderFooterChanged = false;
431 :
432 : // Synch header.
433 8117 : const SwFormatHeader &rHead = rChged.GetMaster().GetHeader();
434 8117 : if (undoGuard.UndoWasEnabled())
435 : {
436 : // #i46909# no undo if header or footer changed
437 : // Did something change in the nodes?
438 117 : const SwFormatHeader &rOldHead = rDesc.GetMaster().GetHeader();
439 : bHeaderFooterChanged |=
440 234 : ( rHead.IsActive() != rOldHead.IsActive() ||
441 234 : rChged.IsHeaderShared() != rDesc.IsHeaderShared() ||
442 234 : rChged.IsFirstShared() != rDesc.IsFirstShared() );
443 : }
444 8117 : rDesc.GetMaster().SetFormatAttr( rHead );
445 8117 : CopyMasterHeader(rChged, rHead, rDesc, true, false); // Copy left header
446 8117 : CopyMasterHeader(rChged, rHead, rDesc, false, true); // Copy first master
447 8117 : CopyMasterHeader(rChged, rHead, rDesc, true, true); // Copy first left
448 8117 : rDesc.ChgHeaderShare( rChged.IsHeaderShared() );
449 :
450 : // Synch Footer.
451 8117 : const SwFormatFooter &rFoot = rChged.GetMaster().GetFooter();
452 8117 : if (undoGuard.UndoWasEnabled())
453 : {
454 : // #i46909# no undo if header or footer changed
455 : // Did something change in the Nodes?
456 117 : const SwFormatFooter &rOldFoot = rDesc.GetMaster().GetFooter();
457 : bHeaderFooterChanged |=
458 234 : ( rFoot.IsActive() != rOldFoot.IsActive() ||
459 234 : rChged.IsFooterShared() != rDesc.IsFooterShared() );
460 : }
461 8117 : rDesc.GetMaster().SetFormatAttr( rFoot );
462 8117 : CopyMasterFooter(rChged, rFoot, rDesc, true, false); // Copy left footer
463 8117 : CopyMasterFooter(rChged, rFoot, rDesc, false, true); // Copy first master
464 8117 : CopyMasterFooter(rChged, rFoot, rDesc, true, true); // Copy first left
465 8117 : rDesc.ChgFooterShare( rChged.IsFooterShared() );
466 : // there is just one first shared flag for both header and footer?
467 8117 : rDesc.ChgFirstShare( rChged.IsFirstShared() );
468 :
469 8117 : if ( rDesc.GetName() != rChged.GetName() )
470 3 : rDesc.SetName( rChged.GetName() );
471 :
472 : // A RegisterChange is triggered, if necessary
473 8117 : rDesc.SetRegisterFormatColl( rChged.GetRegisterFormatColl() );
474 :
475 : // If UseOn or the Follow change, the paragraphs need to know about it.
476 8117 : bool bUseOn = false;
477 8117 : bool bFollow = false;
478 8117 : if (rDesc.GetUseOn() != rChged.GetUseOn())
479 : {
480 87 : rDesc.SetUseOn( rChged.GetUseOn() );
481 87 : bUseOn = true;
482 : }
483 8117 : if (rDesc.GetFollow() != rChged.GetFollow())
484 : {
485 49 : if (rChged.GetFollow() == &rChged)
486 : {
487 0 : if (rDesc.GetFollow() != &rDesc)
488 : {
489 0 : rDesc.SetFollow( &rDesc );
490 0 : bFollow = true;
491 : }
492 : }
493 : else
494 : {
495 49 : rDesc.SetFollow( rChged.m_pFollow );
496 49 : bFollow = true;
497 : }
498 : }
499 :
500 8117 : if ( (bUseOn || bFollow) && pTmpRoot)
501 : // Inform layout!
502 : {
503 2 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
504 2 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));
505 : }
506 :
507 : // Take over the page attributes.
508 8117 : ::lcl_DescSetAttr( rChged.GetMaster(), rDesc.GetMaster() );
509 8117 : ::lcl_DescSetAttr( rChged.GetLeft(), rDesc.GetLeft() );
510 8117 : ::lcl_DescSetAttr( rChged.GetFirstMaster(), rDesc.GetFirstMaster() );
511 8117 : ::lcl_DescSetAttr( rChged.GetFirstLeft(), rDesc.GetFirstLeft() );
512 :
513 : // If the FootnoteInfo changes, the pages are triggered.
514 8117 : if( !(rDesc.GetFootnoteInfo() == rChged.GetFootnoteInfo()) )
515 : {
516 2537 : rDesc.SetFootnoteInfo( rChged.GetFootnoteInfo() );
517 2537 : sw::PageFootnoteHint aHint;
518 2537 : rDesc.GetMaster().CallSwClientNotify(aHint);
519 2537 : rDesc.GetLeft().CallSwClientNotify(aHint);
520 2537 : rDesc.GetFirstMaster().CallSwClientNotify(aHint);
521 2537 : rDesc.GetFirstLeft().CallSwClientNotify(aHint);
522 : }
523 8117 : getIDocumentState().SetModified();
524 :
525 : // #i46909# no undo if header or footer changed
526 8117 : if( bHeaderFooterChanged )
527 : {
528 0 : GetIDocumentUndoRedo().DelAllUndoObj();
529 : }
530 :
531 : SfxBindings* pBindings =
532 8117 : ( GetDocShell() && GetDocShell()->GetDispatcher() ) ? GetDocShell()->GetDispatcher()->GetBindings() : 0;
533 8117 : if ( pBindings )
534 : {
535 382 : pBindings->Invalidate( SID_ATTR_PAGE_COLUMN );
536 382 : pBindings->Invalidate( SID_ATTR_PAGE );
537 382 : pBindings->Invalidate( SID_ATTR_PAGE_SIZE );
538 382 : pBindings->Invalidate( SID_ATTR_PAGE_ULSPACE );
539 382 : pBindings->Invalidate( SID_ATTR_PAGE_LRSPACE );
540 : }
541 :
542 : //h/f of first-left page must not be unique but same as first master or left
543 : assert((rDesc.IsFirstShared())
544 : ? rDesc.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc.GetLeft().GetHeader().GetHeaderFormat()
545 : : rDesc.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc.GetFirstMaster().GetHeader().GetHeaderFormat());
546 : assert((rDesc.IsFirstShared())
547 : ? rDesc.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc.GetLeft().GetFooter().GetFooterFormat()
548 8117 : : rDesc.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc.GetFirstMaster().GetFooter().GetFooterFormat());
549 8117 : }
550 :
551 : /// All descriptors whose Follow point to the to-be-deleted have to be adapted.
552 : // #i7983#
553 7387 : void SwDoc::PreDelPageDesc(SwPageDesc * pDel)
554 : {
555 7387 : if (0 == pDel)
556 7387 : return;
557 :
558 : // mba: test iteration as clients are removed while iteration
559 7387 : SwPageDescHint aHint( &maPageDescs[0] );
560 7387 : pDel->CallSwClientNotify( aHint );
561 :
562 7387 : bool bHasLayout = getIDocumentLayoutAccess().HasLayout();
563 7387 : if ( mpFootnoteInfo->DependsOn( pDel ) )
564 : {
565 0 : mpFootnoteInfo->ChgPageDesc( &maPageDescs[0] );
566 0 : if ( bHasLayout )
567 : {
568 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
569 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFootnotePageDescs), false));
570 : }
571 : }
572 7387 : else if ( mpEndNoteInfo->DependsOn( pDel ) )
573 : {
574 0 : mpEndNoteInfo->ChgPageDesc( &maPageDescs[0] );
575 0 : if ( bHasLayout )
576 : {
577 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
578 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFootnotePageDescs), true));
579 : }
580 : }
581 :
582 92203 : for ( SwPageDescs::size_type j = 0; j < maPageDescs.size(); ++j )
583 : {
584 84816 : if ( maPageDescs[j].GetFollow() == pDel )
585 : {
586 22 : maPageDescs[j].SetFollow( 0 );
587 22 : if( bHasLayout )
588 : {
589 0 : std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
590 0 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));
591 : }
592 : }
593 7387 : }
594 : }
595 :
596 1 : void SwDoc::BroadcastStyleOperation(const OUString& rName, SfxStyleFamily eFamily,
597 : sal_uInt16 nOp)
598 : {
599 1 : if (mpDocShell)
600 : {
601 1 : SfxStyleSheetBasePool * pPool = mpDocShell->GetStyleSheetPool();
602 :
603 1 : if (pPool)
604 : {
605 1 : pPool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
606 1 : SfxStyleSheetBase * pBase = pPool->Find(rName);
607 :
608 1 : if (pBase != NULL)
609 1 : pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase ));
610 : }
611 : }
612 1 : }
613 :
614 22 : void SwDoc::DelPageDesc( size_t i, bool bBroadcast )
615 : {
616 : OSL_ENSURE( i < maPageDescs.size(), "PageDescs is out of range." );
617 : OSL_ENSURE( i != 0, "You cannot delete the default Pagedesc.");
618 22 : if ( i == 0 )
619 22 : return;
620 :
621 22 : SwPageDesc &rDel = maPageDescs[i];
622 :
623 22 : if (bBroadcast)
624 : BroadcastStyleOperation(rDel.GetName(), SFX_STYLE_FAMILY_PAGE,
625 1 : SfxStyleSheetHintId::ERASED);
626 :
627 22 : if (GetIDocumentUndoRedo().DoesUndo())
628 : {
629 0 : SwUndo *const pUndo(new SwUndoPageDescDelete(rDel, this));
630 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
631 : }
632 :
633 22 : PreDelPageDesc(&rDel); // #i7983#
634 :
635 22 : maPageDescs.erase( maPageDescs.begin() + i );
636 22 : getIDocumentState().SetModified();
637 : }
638 :
639 69380 : SwPageDesc* SwDoc::MakePageDesc(const OUString &rName, const SwPageDesc *pCpy,
640 : bool bRegardLanguage, bool bBroadcast)
641 : {
642 : SwPageDesc *pNew;
643 69380 : if( pCpy )
644 : {
645 0 : pNew = new SwPageDesc( *pCpy );
646 0 : pNew->SetName( rName );
647 0 : if( rName != pCpy->GetName() )
648 : {
649 0 : pNew->SetPoolFormatId( USHRT_MAX );
650 0 : pNew->SetPoolHelpId( USHRT_MAX );
651 0 : pNew->SetPoolHlpFileId( UCHAR_MAX );
652 : }
653 : }
654 : else
655 : {
656 69380 : pNew = new SwPageDesc( rName, GetDfltFrameFormat(), this );
657 : // Set the default page format.
658 69380 : lcl_DefaultPageFormat( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft(), pNew->GetFirstMaster(), pNew->GetFirstLeft() );
659 :
660 : SvxFrameDirection aFrameDirection = bRegardLanguage ?
661 69359 : GetDefaultFrameDirection(GetAppLanguage())
662 138739 : : FRMDIR_HORI_LEFT_TOP;
663 :
664 69380 : pNew->GetMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
665 69380 : pNew->GetLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
666 69380 : pNew->GetFirstMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
667 69380 : pNew->GetFirstLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
668 : }
669 69380 : maPageDescs.push_back( pNew );
670 :
671 69380 : if (bBroadcast)
672 : BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PAGE,
673 0 : SfxStyleSheetHintId::CREATED);
674 :
675 69380 : if (GetIDocumentUndoRedo().DoesUndo())
676 : {
677 115 : GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this));
678 : }
679 :
680 69380 : getIDocumentState().SetModified();
681 69380 : return pNew;
682 : }
683 :
684 : // We collect the GlobalNames of the servers at runtime, who don't want to be notified
685 : // about printer changes. Thereby saving loading a lot of objects (luckily all foreign
686 : // objects are mapped to one ID).
687 : // Initialisation and deinitialisation can be found in init.cxx
688 : extern std::vector<SvGlobalName*> *pGlobalOLEExcludeList;
689 :
690 132 : void SwDoc::PrtOLENotify( bool bAll )
691 : {
692 132 : SwFEShell *pShell = nullptr;
693 : {
694 132 : SwViewShell *pSh = getIDocumentLayoutAccess().GetCurrentViewShell();
695 132 : if ( pSh )
696 : {
697 81 : for(SwViewShell& rShell : pSh->GetRingContainer())
698 : {
699 80 : if(rShell.ISA(SwFEShell))
700 : {
701 79 : pShell = static_cast<SwFEShell*>(&rShell);
702 79 : break;
703 : }
704 : }
705 : }
706 : }
707 132 : if ( !pShell )
708 : {
709 : // This doesn't make sense without a Shell and thus without a client, because
710 : // the communication about size changes is implemented by these components.
711 : // Because we don't have a Shell we remember this unfortunate situation
712 : // in the document,
713 : // which is made up for later on when creating the first Shell.
714 53 : mbOLEPrtNotifyPending = true;
715 53 : if ( bAll )
716 53 : mbAllOLENotify = true;
717 : }
718 : else
719 : {
720 79 : if ( mbAllOLENotify )
721 17 : bAll = true;
722 :
723 79 : mbOLEPrtNotifyPending = mbAllOLENotify = false;
724 :
725 79 : SwOLENodes *pNodes = SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), !bAll );
726 79 : if ( pNodes )
727 : {
728 : ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
729 4 : 0, pNodes->size(), GetDocShell());
730 4 : getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
731 :
732 9 : for( SwOLENodes::size_type i = 0; i < pNodes->size(); ++i )
733 : {
734 5 : ::SetProgressState( i, GetDocShell() );
735 :
736 5 : SwOLENode* pOLENd = (*pNodes)[i];
737 5 : pOLENd->SetOLESizeInvalid( false );
738 :
739 : // At first load the Infos and see if it's not already in the exclude list.
740 5 : SvGlobalName aName;
741 :
742 5 : svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject();
743 5 : if ( xObj.is() )
744 5 : aName = SvGlobalName( xObj->getClassID() );
745 : else // Not yet loaded
746 : {
747 : // TODO/LATER: retrieve ClassID of an unloaded object
748 : // aName = ????
749 : }
750 :
751 5 : bool bFound = false;
752 18 : for ( std::vector<SvGlobalName*>::size_type j = 0;
753 9 : j < pGlobalOLEExcludeList->size() && !bFound;
754 : ++j )
755 : {
756 4 : bFound = *(*pGlobalOLEExcludeList)[j] == aName;
757 : }
758 5 : if ( bFound )
759 4 : continue;
760 :
761 : // We don't know it, so the object has to be loaded.
762 : // If it doesn't want to be informed
763 1 : if ( xObj.is() )
764 : {
765 1 : pGlobalOLEExcludeList->push_back( new SvGlobalName( aName ) );
766 : }
767 1 : }
768 4 : delete pNodes;
769 4 : getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
770 4 : ::EndProgress( GetDocShell() );
771 : }
772 : }
773 132 : }
774 :
775 0 : IMPL_LINK_NOARG_TYPED( SwDoc, DoUpdateModifiedOLE, Idle *, void )
776 : {
777 0 : SwFEShell* pSh = static_cast<SwFEShell*>(GetEditShell());
778 0 : if( pSh )
779 : {
780 0 : mbOLEPrtNotifyPending = mbAllOLENotify = false;
781 :
782 0 : SwOLENodes *pNodes = SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), true );
783 0 : if( pNodes )
784 : {
785 : ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
786 0 : 0, pNodes->size(), GetDocShell());
787 0 : getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
788 0 : SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
789 :
790 0 : for( SwOLENodes::size_type i = 0; i < pNodes->size(); ++i )
791 : {
792 0 : ::SetProgressState( i, GetDocShell() );
793 :
794 0 : SwOLENode* pOLENd = (*pNodes)[i];
795 0 : pOLENd->SetOLESizeInvalid( false );
796 :
797 : // We don't know it, so the object has to be loaded.
798 : // If it doesn't want to be informed
799 0 : if( pOLENd->GetOLEObj().GetOleRef().is() ) // Broken?
800 : {
801 0 : pOLENd->ModifyNotification( &aMsgHint, &aMsgHint );
802 : }
803 : }
804 0 : getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
805 0 : ::EndProgress( GetDocShell() );
806 0 : delete pNodes;
807 : }
808 : }
809 0 : }
810 :
811 : struct CompareSwPageDescName {
812 48255 : explicit CompareSwPageDescName(const OUString &rName) : mName(rName) {}
813 366501 : bool operator () (const SwPageDesc& other) const { return other.GetName() == mName; }
814 : const OUString &mName;
815 : };
816 :
817 : template <class UnaryPredicate>
818 56977 : static SwPageDesc* lcl_FindPageDesc( SwPageDescs *pPageDescs,
819 : size_t *pPos, UnaryPredicate pred )
820 : {
821 : SwPageDescs::iterator it = std::find_if(
822 56977 : pPageDescs->begin(), pPageDescs->end(), pred);
823 56977 : SwPageDesc* res = NULL;
824 56977 : if( it != pPageDescs->end() )
825 : {
826 46437 : res = &( *it ) ;;
827 46437 : if( pPos )
828 16779 : *pPos = std::distance( pPageDescs->begin(), it );
829 : }
830 10540 : else if( pPos )
831 1 : *pPos = SIZE_MAX;
832 56977 : return res;
833 : }
834 :
835 48255 : SwPageDesc* SwDoc::FindPageDesc( const OUString & rName, size_t* pPos )
836 : {
837 : return lcl_FindPageDesc<CompareSwPageDescName>(
838 48255 : &maPageDescs, pPos, CompareSwPageDescName(rName) );
839 : }
840 :
841 0 : SwPageDesc* SwDoc::FindPageDesc( const OUString & rName, size_t* pPos ) const
842 : {
843 : return lcl_FindPageDesc<CompareSwPageDescName>(
844 : const_cast <SwPageDescs *>( &maPageDescs ), pPos,
845 0 : CompareSwPageDescName(rName) );
846 : }
847 :
848 : struct CompareSwPageDescToPtr {
849 8722 : explicit CompareSwPageDescToPtr(const SwPageDesc* ptr) : mPtr(ptr) {}
850 8875 : bool operator () (const SwPageDesc& other) const { return &other == mPtr; }
851 : const SwPageDesc *mPtr;
852 : };
853 :
854 8722 : bool SwDoc::ContainsPageDesc( const SwPageDesc *pDesc, size_t* pPos )
855 : {
856 8722 : if (pDesc == NULL)
857 0 : return false;
858 : SwPageDesc *res = lcl_FindPageDesc<CompareSwPageDescToPtr>(
859 : &maPageDescs, pPos,
860 8722 : CompareSwPageDescToPtr(pDesc) );
861 8722 : return res != NULL;
862 : }
863 :
864 1 : void SwDoc::DelPageDesc( const OUString & rName, bool bBroadcast )
865 : {
866 : size_t nI;
867 :
868 1 : if (FindPageDesc(rName, &nI))
869 1 : DelPageDesc(nI, bBroadcast);
870 1 : }
871 :
872 2 : void SwDoc::ChgPageDesc( const OUString & rName, const SwPageDesc & rDesc)
873 : {
874 : size_t nI;
875 :
876 2 : if (FindPageDesc(rName, &nI))
877 2 : ChgPageDesc(nI, rDesc);
878 2 : }
879 :
880 : /*
881 : * The HTML import cannot resist changing the page descriptions, I don't
882 : * know why. This function is meant to check the page descriptors for invalid
883 : * values.
884 : */
885 3108 : void SwDoc::CheckDefaultPageFormat()
886 : {
887 6888 : for ( size_t i = 0; i < GetPageDescCnt(); ++i )
888 : {
889 3780 : SwPageDesc& rDesc = GetPageDesc( i );
890 :
891 3780 : SwFrameFormat& rMaster = rDesc.GetMaster();
892 3780 : SwFrameFormat& rLeft = rDesc.GetLeft();
893 :
894 3780 : const SwFormatFrmSize& rMasterSize = rMaster.GetFrmSize();
895 3780 : const SwFormatFrmSize& rLeftSize = rLeft.GetFrmSize();
896 :
897 7560 : const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() ||
898 7560 : LONG_MAX == rMasterSize.GetHeight() ||
899 11340 : LONG_MAX == rLeftSize.GetWidth() ||
900 7560 : LONG_MAX == rLeftSize.GetHeight();
901 :
902 3780 : if ( bSetSize )
903 0 : lcl_DefaultPageFormat( rDesc.GetPoolFormatId(), rDesc.GetMaster(), rDesc.GetLeft(), rDesc.GetFirstMaster(), rDesc.GetFirstLeft() );
904 : }
905 3108 : }
906 :
907 4930 : void SwDoc::SetDefaultPageMode(bool bSquaredPageMode)
908 : {
909 4930 : if( !bSquaredPageMode == !IsSquaredPageMode() )
910 7819 : return;
911 :
912 : const SwTextGridItem& rGrid =
913 2041 : static_cast<const SwTextGridItem&>(GetDefault( RES_TEXTGRID ));
914 2041 : SwTextGridItem aNewGrid = rGrid;
915 2041 : aNewGrid.SetSquaredMode(bSquaredPageMode);
916 2041 : aNewGrid.Init();
917 2041 : SetDefault(aNewGrid);
918 :
919 4309 : for ( size_t i = 0; i < GetPageDescCnt(); ++i )
920 : {
921 2268 : SwPageDesc& rDesc = GetPageDesc( i );
922 :
923 2268 : SwFrameFormat& rMaster = rDesc.GetMaster();
924 2268 : SwFrameFormat& rLeft = rDesc.GetLeft();
925 :
926 2268 : SwTextGridItem aGrid(static_cast<const SwTextGridItem&>(rMaster.GetFormatAttr(RES_TEXTGRID)));
927 2268 : aGrid.SwitchPaperMode( bSquaredPageMode );
928 2268 : rMaster.SetFormatAttr(aGrid);
929 2268 : rLeft.SetFormatAttr(aGrid);
930 4309 : }
931 : }
932 :
933 121010 : bool SwDoc::IsSquaredPageMode() const
934 : {
935 : const SwTextGridItem& rGrid =
936 121010 : static_cast<const SwTextGridItem&>(GetDefault( RES_TEXTGRID ));
937 121010 : return rGrid.IsSquaredMode();
938 177 : }
939 :
940 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|