xref: /aoo41x/main/sc/source/filter/excel/xipage.cxx (revision b3f79822)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 #include "xipage.hxx"
27 #include <svl/itemset.hxx>
28 #include <vcl/graph.hxx>
29 #include "scitems.hxx"
30 #include <svl/eitem.hxx>
31 #include <svl/intitem.hxx>
32 #include <svx/pageitem.hxx>
33 #include <editeng/sizeitem.hxx>
34 #include <editeng/lrspitem.hxx>
35 #include <editeng/ulspitem.hxx>
36 #include <editeng/brshitem.hxx>
37 #include "document.hxx"
38 #include "stlsheet.hxx"
39 #include "attrib.hxx"
40 #include "xistream.hxx"
41 #include "xihelper.hxx"
42 #include "xiescher.hxx"
43 
44 // Page settings ==============================================================
45 
XclImpPageSettings(const XclImpRoot & rRoot)46 XclImpPageSettings::XclImpPageSettings( const XclImpRoot& rRoot ) :
47     XclImpRoot( rRoot )
48 {
49     Initialize();
50 }
51 
Initialize()52 void XclImpPageSettings::Initialize()
53 {
54     maData.SetDefaults();
55     mbValidPaper = false;
56 }
57 
ReadSetup(XclImpStream & rStrm)58 void XclImpPageSettings::ReadSetup( XclImpStream& rStrm )
59 {
60     DBG_ASSERT_BIFF( GetBiff() >= EXC_BIFF4 );
61     if( GetBiff() < EXC_BIFF4 )
62         return;
63 
64     // BIFF4 - BIFF8
65     sal_uInt16 nFlags;
66     rStrm   >> maData.mnPaperSize >> maData.mnScaling >> maData.mnStartPage
67             >> maData.mnFitToWidth >> maData.mnFitToHeight >> nFlags;
68 
69     mbValidPaper = maData.mbValid = !::get_flag( nFlags, EXC_SETUP_INVALID );
70     maData.mbPrintInRows = ::get_flag( nFlags, EXC_SETUP_INROWS );
71     maData.mbPortrait = ::get_flag( nFlags, EXC_SETUP_PORTRAIT );
72     maData.mbBlackWhite = ::get_flag( nFlags, EXC_SETUP_BLACKWHITE );
73     maData.mbManualStart = true;
74 
75     // new in BIFF5 - BIFF8
76     if( GetBiff() >= EXC_BIFF5 )
77     {
78         rStrm   >> maData.mnHorPrintRes >> maData.mnVerPrintRes
79                 >> maData.mfHeaderMargin >> maData.mfFooterMargin >> maData.mnCopies;
80 
81         maData.mbDraftQuality = ::get_flag( nFlags, EXC_SETUP_DRAFT );
82         maData.mbPrintNotes = ::get_flag( nFlags, EXC_SETUP_PRINTNOTES );
83         maData.mbManualStart = ::get_flag( nFlags, EXC_SETUP_STARTPAGE );
84     }
85 }
86 
ReadMargin(XclImpStream & rStrm)87 void XclImpPageSettings::ReadMargin( XclImpStream& rStrm )
88 {
89     switch( rStrm.GetRecId() )
90     {
91         case EXC_ID_LEFTMARGIN:     rStrm >> maData.mfLeftMargin;   break;
92         case EXC_ID_RIGHTMARGIN:    rStrm >> maData.mfRightMargin;  break;
93         case EXC_ID_TOPMARGIN:      rStrm >> maData.mfTopMargin;    break;
94         case EXC_ID_BOTTOMMARGIN:   rStrm >> maData.mfBottomMargin; break;
95         default:    DBG_ERRORFILE( "XclImpPageSettings::ReadMargin - unknown record" );
96     }
97 }
98 
ReadCenter(XclImpStream & rStrm)99 void XclImpPageSettings::ReadCenter( XclImpStream& rStrm )
100 {
101     DBG_ASSERT_BIFF( GetBiff() >= EXC_BIFF3 );  // read it anyway
102     bool bCenter = (rStrm.ReaduInt16() != 0);
103     switch( rStrm.GetRecId() )
104     {
105         case EXC_ID_HCENTER:    maData.mbHorCenter = bCenter;   break;
106         case EXC_ID_VCENTER:    maData.mbVerCenter = bCenter;   break;
107         default:    DBG_ERRORFILE( "XclImpPageSettings::ReadCenter - unknown record" );
108     }
109 }
110 
ReadHeaderFooter(XclImpStream & rStrm)111 void XclImpPageSettings::ReadHeaderFooter( XclImpStream& rStrm )
112 {
113     String aString;
114     if( rStrm.GetRecLeft() )
115         aString = (GetBiff() <= EXC_BIFF5) ? rStrm.ReadByteString( false ) : rStrm.ReadUniString();
116 
117     switch( rStrm.GetRecId() )
118     {
119         case EXC_ID_HEADER:     maData.maHeader = aString;  break;
120         case EXC_ID_FOOTER:     maData.maFooter = aString;  break;
121         default:    DBG_ERRORFILE( "XclImpPageSettings::ReadHeaderFooter - unknown record" );
122     }
123 }
124 
ReadPageBreaks(XclImpStream & rStrm)125 void XclImpPageSettings::ReadPageBreaks( XclImpStream& rStrm )
126 {
127     ScfUInt16Vec* pVec = 0;
128     switch( rStrm.GetRecId() )
129     {
130         case EXC_ID_HORPAGEBREAKS:  pVec = &maData.maHorPageBreaks;     break;
131         case EXC_ID_VERPAGEBREAKS:  pVec = &maData.maVerPageBreaks;     break;
132         default:    DBG_ERRORFILE( "XclImpPageSettings::ReadPageBreaks - unknown record" );
133     }
134 
135     if( pVec )
136     {
137         bool bIgnore = GetBiff() == EXC_BIFF8;  // ignore start/end columns or rows in BIFF8
138 
139         sal_uInt16 nCount, nBreak;
140         rStrm >> nCount;
141         pVec->clear();
142         pVec->reserve( nCount );
143 
144         while( nCount-- )
145         {
146             rStrm >> nBreak;
147             if( nBreak )
148                 pVec->push_back( nBreak );
149             if( bIgnore )
150                 rStrm.Ignore( 4 );
151         }
152     }
153 }
154 
ReadPrintHeaders(XclImpStream & rStrm)155 void XclImpPageSettings::ReadPrintHeaders( XclImpStream& rStrm )
156 {
157     maData.mbPrintHeadings = (rStrm.ReaduInt16() != 0);
158 }
159 
ReadPrintGridLines(XclImpStream & rStrm)160 void XclImpPageSettings::ReadPrintGridLines( XclImpStream& rStrm )
161 {
162     maData.mbPrintGrid = (rStrm.ReaduInt16() != 0);
163 }
164 
ReadImgData(XclImpStream & rStrm)165 void XclImpPageSettings::ReadImgData( XclImpStream& rStrm )
166 {
167     Graphic aGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
168     if( aGraphic.GetType() != GRAPHIC_NONE )
169         maData.mxBrushItem.reset( new SvxBrushItem( aGraphic, GPOS_TILED, ATTR_BACKGROUND ) );
170 }
171 
SetPaperSize(sal_uInt16 nXclPaperSize,bool bPortrait)172 void XclImpPageSettings::SetPaperSize( sal_uInt16 nXclPaperSize, bool bPortrait )
173 {
174     maData.mnPaperSize = nXclPaperSize;
175     maData.mbPortrait = bPortrait;
176     mbValidPaper = true;
177 }
178 
179 // ----------------------------------------------------------------------------
180 
181 namespace {
182 
lclPutMarginItem(SfxItemSet & rItemSet,sal_uInt16 nRecId,double fMarginInch)183 void lclPutMarginItem( SfxItemSet& rItemSet, sal_uInt16 nRecId, double fMarginInch )
184 {
185     sal_uInt16 nMarginTwips = XclTools::GetTwipsFromInch( fMarginInch );
186     switch( nRecId )
187     {
188         case EXC_ID_TOPMARGIN:
189         case EXC_ID_BOTTOMMARGIN:
190         {
191             SvxULSpaceItem aItem( GETITEM( rItemSet, SvxULSpaceItem, ATTR_ULSPACE ) );
192             if( nRecId == EXC_ID_TOPMARGIN )
193                 aItem.SetUpperValue( nMarginTwips );
194             else
195                 aItem.SetLowerValue( nMarginTwips );
196             rItemSet.Put( aItem );
197         }
198         break;
199         case EXC_ID_LEFTMARGIN:
200         case EXC_ID_RIGHTMARGIN:
201         {
202             SvxLRSpaceItem aItem( GETITEM( rItemSet, SvxLRSpaceItem, ATTR_LRSPACE ) );
203             if( nRecId == EXC_ID_LEFTMARGIN )
204                 aItem.SetLeftValue( nMarginTwips );
205             else
206                 aItem.SetRightValue( nMarginTwips );
207             rItemSet.Put( aItem );
208         }
209         break;
210         default:
211             DBG_ERRORFILE( "XclImpPageSettings::SetMarginItem - unknown record id" );
212     }
213 }
214 
215 } // namespace
216 
Finalize()217 void XclImpPageSettings::Finalize()
218 {
219     ScDocument& rDoc = GetDoc();
220     SCTAB nScTab = GetCurrScTab();
221 
222     // *** create page style sheet ***
223 
224     String aStyleName( RTL_CONSTASCII_USTRINGPARAM( "PageStyle_" ) );
225     String aTableName;
226     if( GetDoc().GetName( nScTab, aTableName ) )
227         aStyleName.Append( aTableName );
228     else
229         aStyleName.Append( String::CreateFromInt32( nScTab + 1 ) );
230 
231     ScStyleSheet& rStyleSheet = ScfTools::MakePageStyleSheet( GetStyleSheetPool(), aStyleName, false );
232     SfxItemSet& rItemSet = rStyleSheet.GetItemSet();
233 
234     // *** page settings ***
235 
236     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_TOPDOWN,    !maData.mbPrintInRows ),    true );
237     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_HORCENTER,  maData.mbHorCenter ),       true );
238     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_VERCENTER,  maData.mbVerCenter ),       true );
239     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_HEADERS,    maData.mbPrintHeadings ),   true );
240     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_GRID,       maData.mbPrintGrid ),       true );
241     ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_PAGE_NOTES,      maData.mbPrintNotes ),      true );
242 
243     sal_uInt16 nStartPage = maData.mbManualStart ? maData.mnStartPage : 0;
244     ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, nStartPage ), true );
245 
246     if( maData.mxBrushItem.get() )
247         rItemSet.Put( *maData.mxBrushItem );
248 
249     if( mbValidPaper )
250     {
251         SvxPageItem aPageItem( GETITEM( rItemSet, SvxPageItem, ATTR_PAGE ) );
252         aPageItem.SetLandscape( !maData.mbPortrait );
253         rItemSet.Put( aPageItem );
254         ScfTools::PutItem( rItemSet, SvxSizeItem( ATTR_PAGE_SIZE, maData.GetScPaperSize() ), true );
255     }
256 
257     if( maData.mbFitToPages )
258         rItemSet.Put( ScPageScaleToItem( maData.mnFitToWidth, maData.mnFitToHeight ) );
259     else if( maData.mbValid )
260         rItemSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, maData.mnScaling ) );
261 
262     // *** margin preparations ***
263 
264     double fLeftMargin   = maData.mfLeftMargin;
265     double fRightMargin  = maData.mfRightMargin;
266     double fTopMargin    = maData.mfTopMargin;
267     double fBottomMargin = maData.mfBottomMargin;
268     // distances between header/footer and page area
269     double fHeaderHeight = 0.0;
270     double fHeaderDist = 0.0;
271     double fFooterHeight = 0.0;
272     double fFooterDist = 0.0;
273     // in Calc, "header/footer left/right margin" is X distance between header/footer and page margin
274     double fHdrLeftMargin  = maData.mfHdrLeftMargin  - maData.mfLeftMargin;
275     double fHdrRightMargin = maData.mfHdrRightMargin - maData.mfRightMargin;
276     double fFtrLeftMargin  = maData.mfFtrLeftMargin  - maData.mfLeftMargin;
277     double fFtrRightMargin = maData.mfFtrRightMargin - maData.mfRightMargin;
278 
279     // *** header and footer ***
280 
281     XclImpHFConverter aHFConv( GetRoot() );
282 
283     // header
284     bool bHasHeader = (maData.maHeader.Len() != 0);
285     SvxSetItem aHdrSetItem( GETITEM( rItemSet, SvxSetItem, ATTR_PAGE_HEADERSET ) );
286     SfxItemSet& rHdrItemSet = aHdrSetItem.GetItemSet();
287     rHdrItemSet.Put( SfxBoolItem( ATTR_PAGE_ON, bHasHeader ) );
288     if( bHasHeader )
289     {
290         aHFConv.ParseString( maData.maHeader );
291         aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERLEFT );
292         aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERRIGHT );
293         // #i23296# In Calc, "top margin" is distance to header
294         fTopMargin = maData.mfHeaderMargin;
295         // Calc uses distance between header and sheet data area
296         fHeaderHeight = XclTools::GetInchFromTwips( aHFConv.GetTotalHeight() );
297         fHeaderDist = maData.mfTopMargin - maData.mfHeaderMargin - fHeaderHeight;
298     }
299     if( fHeaderDist < 0.0 )
300     {
301         /*  #i23296# Header overlays sheet data:
302             -> set fixed header height to get correct sheet data position. */
303         ScfTools::PutItem( rHdrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, false ), true );
304         // shrink header height
305         long nHdrHeight = XclTools::GetTwipsFromInch( fHeaderHeight + fHeaderDist );
306         ScfTools::PutItem( rHdrItemSet, SvxSizeItem( ATTR_PAGE_SIZE, Size( 0, nHdrHeight ) ), true );
307         lclPutMarginItem( rHdrItemSet, EXC_ID_BOTTOMMARGIN, 0.0 );
308     }
309     else
310     {
311         // use dynamic header height
312         ScfTools::PutItem( rHdrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, true ), true );
313         lclPutMarginItem( rHdrItemSet, EXC_ID_BOTTOMMARGIN, fHeaderDist );
314     }
315     lclPutMarginItem( rHdrItemSet, EXC_ID_LEFTMARGIN,   fHdrLeftMargin );
316     lclPutMarginItem( rHdrItemSet, EXC_ID_RIGHTMARGIN,  fHdrRightMargin );
317     rItemSet.Put( aHdrSetItem );
318 
319     // footer
320     bool bHasFooter = (maData.maFooter.Len() != 0);
321     SvxSetItem aFtrSetItem( GETITEM( rItemSet, SvxSetItem, ATTR_PAGE_FOOTERSET ) );
322     SfxItemSet& rFtrItemSet = aFtrSetItem.GetItemSet();
323     rFtrItemSet.Put( SfxBoolItem( ATTR_PAGE_ON, bHasFooter ) );
324     if( bHasFooter )
325     {
326         aHFConv.ParseString( maData.maFooter );
327         aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERLEFT );
328         aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERRIGHT );
329         // #i23296# In Calc, "bottom margin" is distance to footer
330         fBottomMargin = maData.mfFooterMargin;
331         // Calc uses distance between footer and sheet data area
332         fFooterHeight = XclTools::GetInchFromTwips( aHFConv.GetTotalHeight() );
333         fFooterDist = maData.mfBottomMargin - maData.mfFooterMargin - fFooterHeight;
334     }
335     if( fFooterDist < 0.0 )
336     {
337         /*  #i23296# Footer overlays sheet data:
338             -> set fixed footer height to get correct sheet data end position. */
339         ScfTools::PutItem( rFtrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, false ), true );
340         // shrink footer height
341         long nFtrHeight = XclTools::GetTwipsFromInch( fFooterHeight + fFooterDist );
342         ScfTools::PutItem( rFtrItemSet, SvxSizeItem( ATTR_PAGE_SIZE, Size( 0, nFtrHeight ) ), true );
343         lclPutMarginItem( rFtrItemSet, EXC_ID_TOPMARGIN, 0.0 );
344     }
345     else
346     {
347         // use dynamic footer height
348         ScfTools::PutItem( rFtrItemSet, SfxBoolItem( ATTR_PAGE_DYNAMIC, true ), true );
349         lclPutMarginItem( rFtrItemSet, EXC_ID_TOPMARGIN, fFooterDist );
350     }
351     lclPutMarginItem( rFtrItemSet, EXC_ID_LEFTMARGIN,   fFtrLeftMargin );
352     lclPutMarginItem( rFtrItemSet, EXC_ID_RIGHTMARGIN,  fFtrRightMargin );
353     rItemSet.Put( aFtrSetItem );
354 
355     // *** set final margins ***
356 
357     lclPutMarginItem( rItemSet, EXC_ID_LEFTMARGIN,   fLeftMargin );
358     lclPutMarginItem( rItemSet, EXC_ID_RIGHTMARGIN,  fRightMargin );
359     lclPutMarginItem( rItemSet, EXC_ID_TOPMARGIN,    fTopMargin );
360     lclPutMarginItem( rItemSet, EXC_ID_BOTTOMMARGIN, fBottomMargin );
361 
362     // *** put style sheet into document ***
363 
364     rDoc.SetPageStyle( nScTab, rStyleSheet.GetName() );
365 
366     // *** page breaks ***
367 
368     ScfUInt16Vec::const_iterator aIt, aEnd;
369 
370     for( aIt = maData.maHorPageBreaks.begin(), aEnd = maData.maHorPageBreaks.end(); aIt != aEnd; ++aIt )
371     {
372         SCROW nScRow = static_cast< SCROW >( *aIt );
373         if( nScRow <= MAXROW )
374             rDoc.SetRowBreak(nScRow, nScTab, false, true);
375     }
376 
377     for( aIt = maData.maVerPageBreaks.begin(), aEnd = maData.maVerPageBreaks.end(); aIt != aEnd; ++aIt )
378     {
379         SCCOL nScCol = static_cast< SCCOL >( *aIt );
380         if( nScCol <= MAXCOL )
381             rDoc.SetColBreak(nScCol, nScTab, false, true);
382     }
383 }
384 
385 // ============================================================================
386 
387