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