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