xref: /AOO41X/main/oox/source/xls/viewsettings.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/xls/viewsettings.hxx"
29 
30 #include <com/sun/star/awt/Point.hpp>
31 #include <com/sun/star/awt/Size.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/container/XIndexContainer.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/document/XViewDataSupplier.hpp>
36 #include <comphelper/mediadescriptor.hxx>
37 #include "oox/core/filterbase.hxx"
38 #include "oox/helper/attributelist.hxx"
39 #include "oox/helper/containerhelper.hxx"
40 #include "oox/helper/propertymap.hxx"
41 #include "oox/helper/propertyset.hxx"
42 #include "oox/xls/addressconverter.hxx"
43 #include "oox/xls/biffinputstream.hxx"
44 #include "oox/xls/unitconverter.hxx"
45 #include "oox/xls/workbooksettings.hxx"
46 #include "oox/xls/worksheetbuffer.hxx"
47 
48 namespace oox {
49 namespace xls {
50 
51 // ============================================================================
52 
53 using namespace ::com::sun::star::awt;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::document;
56 using namespace ::com::sun::star::table;
57 using namespace ::com::sun::star::uno;
58 
59 using ::oox::core::FilterBase;
60 using ::rtl::OUString;
61 
62 // ============================================================================
63 
64 namespace {
65 
66 const sal_Int32 OOX_BOOKVIEW_TABBARRATIO_DEF        = 600;      /// Default tabbar ratio.
67 const sal_Int32 OOX_SHEETVIEW_NORMALZOOM_DEF        = 100;      /// Default zoom for normal view.
68 const sal_Int32 OOX_SHEETVIEW_SHEETLAYZOOM_DEF      = 60;       /// Default zoom for pagebreak preview.
69 const sal_Int32 OOX_SHEETVIEW_PAGELAYZOOM_DEF       = 100;      /// Default zoom for page layout view.
70 
71 const sal_uInt8 BIFF12_PANE_FROZEN                  = 0x01;
72 const sal_uInt8 BIFF12_PANE_FROZENNOSPLIT           = 0x02;
73 
74 const sal_uInt16 BIFF12_SHEETVIEW_WINPROTECTED      = 0x0001;
75 const sal_uInt16 BIFF12_SHEETVIEW_SHOWFORMULAS      = 0x0002;
76 const sal_uInt16 BIFF12_SHEETVIEW_SHOWGRID          = 0x0004;
77 const sal_uInt16 BIFF12_SHEETVIEW_SHOWHEADINGS      = 0x0008;
78 const sal_uInt16 BIFF12_SHEETVIEW_SHOWZEROS         = 0x0010;
79 const sal_uInt16 BIFF12_SHEETVIEW_RIGHTTOLEFT       = 0x0020;
80 const sal_uInt16 BIFF12_SHEETVIEW_SELECTED          = 0x0040;
81 const sal_uInt16 BIFF12_SHEETVIEW_SHOWRULER         = 0x0080;
82 const sal_uInt16 BIFF12_SHEETVIEW_SHOWOUTLINE       = 0x0100;
83 const sal_uInt16 BIFF12_SHEETVIEW_DEFGRIDCOLOR      = 0x0200;
84 const sal_uInt16 BIFF12_SHEETVIEW_SHOWWHITESPACE    = 0x0400;
85 
86 const sal_uInt16 BIFF12_CHARTSHEETVIEW_SELECTED     = 0x0001;
87 const sal_uInt16 BIFF12_CHARTSHEETVIEW_ZOOMTOFIT    = 0x0002;
88 
89 const sal_uInt8 BIFF12_WBVIEW_HIDDEN                = 0x01;
90 const sal_uInt8 BIFF12_WBVIEW_MINIMIZED             = 0x02;
91 const sal_uInt8 BIFF12_WBVIEW_SHOWHORSCROLL         = 0x08;
92 const sal_uInt8 BIFF12_WBVIEW_SHOWVERSCROLL         = 0x10;
93 const sal_uInt8 BIFF12_WBVIEW_SHOWTABBAR            = 0x20;
94 const sal_uInt8 BIFF12_WBVIEW_AUTOFILTERGROUP       = 0x40;
95 
96 const sal_uInt8 BIFF_PANE_BOTTOMRIGHT               = 0;        /// Bottom-right pane.
97 const sal_uInt8 BIFF_PANE_TOPRIGHT                  = 1;        /// Right, or top-right pane.
98 const sal_uInt8 BIFF_PANE_BOTTOMLEFT                = 2;        /// Bottom, or bottom-left pane.
99 const sal_uInt8 BIFF_PANE_TOPLEFT                   = 3;        /// Single, top, left, or top-left pane.
100 
101 const sal_uInt16 BIFF_WINDOW1_HIDDEN                = 0x0001;
102 const sal_uInt16 BIFF_WINDOW1_MINIMIZED             = 0x0002;
103 const sal_uInt16 BIFF_WINDOW1_SHOWHORSCROLL         = 0x0008;
104 const sal_uInt16 BIFF_WINDOW1_SHOWVERSCROLL         = 0x0010;
105 const sal_uInt16 BIFF_WINDOW1_SHOWTABBAR            = 0x0020;
106 
107 const sal_uInt16 BIFF_WINDOW2_SHOWFORMULAS          = 0x0001;
108 const sal_uInt16 BIFF_WINDOW2_SHOWGRID              = 0x0002;
109 const sal_uInt16 BIFF_WINDOW2_SHOWHEADINGS          = 0x0004;
110 const sal_uInt16 BIFF_WINDOW2_FROZEN                = 0x0008;
111 const sal_uInt16 BIFF_WINDOW2_SHOWZEROS             = 0x0010;
112 const sal_uInt16 BIFF_WINDOW2_DEFGRIDCOLOR          = 0x0020;
113 const sal_uInt16 BIFF_WINDOW2_RIGHTTOLEFT           = 0x0040;
114 const sal_uInt16 BIFF_WINDOW2_SHOWOUTLINE           = 0x0080;
115 const sal_uInt16 BIFF_WINDOW2_FROZENNOSPLIT         = 0x0100;
116 const sal_uInt16 BIFF_WINDOW2_SELECTED              = 0x0200;
117 const sal_uInt16 BIFF_WINDOW2_DISPLAYED             = 0x0400;
118 const sal_uInt16 BIFF_WINDOW2_PAGEBREAKMODE         = 0x0800;
119 
120 // Attention: view settings in Calc do not use com.sun.star.view.DocumentZoomType!
121 const sal_Int16 API_ZOOMTYPE_PERCENT                = 0;        /// Zoom value in percent.
122 
123 const sal_Int32 API_ZOOMVALUE_MIN                   = 20;       /// Minimum zoom in Calc.
124 const sal_Int32 API_ZOOMVALUE_MAX                   = 400;      /// Maximum zoom in Calc.
125 
126 // no predefined constants for split mode
127 const sal_Int16 API_SPLITMODE_NONE                  = 0;        /// No splits in window.
128 const sal_Int16 API_SPLITMODE_SPLIT                 = 1;        /// Window is split.
129 const sal_Int16 API_SPLITMODE_FREEZE                = 2;        /// Window has frozen panes.
130 
131 // no predefined constants for pane idetifiers
132 const sal_Int16 API_SPLITPANE_TOPLEFT               = 0;        /// Top-left, or top pane.
133 const sal_Int16 API_SPLITPANE_TOPRIGHT              = 1;        /// Top-right pane.
134 const sal_Int16 API_SPLITPANE_BOTTOMLEFT            = 2;        /// Bottom-left, bottom, left, or single pane.
135 const sal_Int16 API_SPLITPANE_BOTTOMRIGHT           = 3;        /// Bottom-right, or right pane.
136 
137 // ----------------------------------------------------------------------------
138 
139 /** Returns the OOXML pane identifier from the passed BIFF pane id. */
140 sal_Int32 lclGetOoxPaneId( sal_Int32 nBiffPaneId, sal_Int32 nDefaultPaneId )
141 {
142     static const sal_Int32 spnPaneIds[] = { XML_bottomRight, XML_topRight, XML_bottomLeft, XML_topLeft };
143     return STATIC_ARRAY_SELECT( spnPaneIds, nBiffPaneId, nDefaultPaneId );
144 }
145 
146 } // namespace
147 
148 // ============================================================================
149 
150 PaneSelectionModel::PaneSelectionModel() :
151     mnActiveCellId( 0 )
152 {
153 }
154 
155 // ----------------------------------------------------------------------------
156 
157 SheetViewModel::SheetViewModel() :
158     mnWorkbookViewId( 0 ),
159     mnViewType( XML_normal ),
160     mnActivePaneId( XML_topLeft ),
161     mnPaneState( XML_split ),
162     mfSplitX( 0.0 ),
163     mfSplitY( 0.0 ),
164     mnCurrentZoom( 0 ),
165     mnNormalZoom( 0 ),
166     mnSheetLayoutZoom( 0 ),
167     mnPageLayoutZoom( 0 ),
168     mbSelected( false ),
169     mbRightToLeft( false ),
170     mbDefGridColor( true ),
171     mbShowFormulas( false ),
172     mbShowGrid( true ),
173     mbShowHeadings( true ),
174     mbShowZeros( true ),
175     mbShowOutline( true ),
176     mbZoomToFit( false )
177 {
178     maGridColor.setIndexed( OOX_COLOR_WINDOWTEXT );
179 }
180 
181 bool SheetViewModel::isPageBreakPreview() const
182 {
183     return mnViewType == XML_pageBreakPreview;
184 }
185 
186 sal_Int32 SheetViewModel::getNormalZoom() const
187 {
188     const sal_Int32& rnZoom = isPageBreakPreview() ? mnNormalZoom : mnCurrentZoom;
189     sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_NORMALZOOM_DEF;
190     return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX );
191 }
192 
193 sal_Int32 SheetViewModel::getPageBreakZoom() const
194 {
195     const sal_Int32& rnZoom = isPageBreakPreview() ? mnCurrentZoom : mnSheetLayoutZoom;
196     sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_SHEETLAYZOOM_DEF;
197     return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX );
198 }
199 
200 sal_Int32 SheetViewModel::getGridColor( const FilterBase& rFilter ) const
201 {
202     return mbDefGridColor ? API_RGB_TRANSPARENT : maGridColor.getColor( rFilter.getGraphicHelper() );
203 }
204 
205 const PaneSelectionModel* SheetViewModel::getPaneSelection( sal_Int32 nPaneId ) const
206 {
207     return maPaneSelMap.get( nPaneId ).get();
208 }
209 
210 const PaneSelectionModel* SheetViewModel::getActiveSelection() const
211 {
212     return getPaneSelection( mnActivePaneId );
213 }
214 
215 PaneSelectionModel& SheetViewModel::createPaneSelection( sal_Int32 nPaneId )
216 {
217     PaneSelectionModelMap::mapped_type& rxPaneSel = maPaneSelMap[ nPaneId ];
218     if( !rxPaneSel )
219         rxPaneSel.reset( new PaneSelectionModel );
220     return *rxPaneSel;
221 }
222 
223 // ----------------------------------------------------------------------------
224 
225 SheetViewSettings::SheetViewSettings( const WorksheetHelper& rHelper ) :
226     WorksheetHelper( rHelper )
227 {
228 }
229 
230 void SheetViewSettings::importSheetView( const AttributeList& rAttribs )
231 {
232     SheetViewModel& rModel = *createSheetView();
233     rModel.maGridColor.setIndexed( rAttribs.getInteger( XML_colorId, OOX_COLOR_WINDOWTEXT ) );
234     rModel.maFirstPos        = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false );
235     rModel.mnWorkbookViewId  = rAttribs.getToken( XML_workbookViewId, 0 );
236     rModel.mnViewType        = rAttribs.getToken( XML_view, XML_normal );
237     rModel.mnCurrentZoom     = rAttribs.getInteger( XML_zoomScale, 100 );
238     rModel.mnNormalZoom      = rAttribs.getInteger( XML_zoomScaleNormal, 0 );
239     rModel.mnSheetLayoutZoom = rAttribs.getInteger( XML_zoomScaleSheetLayoutView, 0 );
240     rModel.mnPageLayoutZoom  = rAttribs.getInteger( XML_zoomScalePageLayoutView, 0 );
241     rModel.mbSelected        = rAttribs.getBool( XML_tabSelected, false );
242     rModel.mbRightToLeft     = rAttribs.getBool( XML_rightToLeft, false );
243     rModel.mbDefGridColor    = rAttribs.getBool( XML_defaultGridColor, true );
244     rModel.mbShowFormulas    = rAttribs.getBool( XML_showFormulas, false );
245     rModel.mbShowGrid        = rAttribs.getBool( XML_showGridLines, true );
246     rModel.mbShowHeadings    = rAttribs.getBool( XML_showRowColHeaders, true );
247     rModel.mbShowZeros       = rAttribs.getBool( XML_showZeros, true );
248     rModel.mbShowOutline     = rAttribs.getBool( XML_showOutlineSymbols, true );
249 }
250 
251 void SheetViewSettings::importPane( const AttributeList& rAttribs )
252 {
253     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" );
254     if( !maSheetViews.empty() )
255     {
256         SheetViewModel& rModel = *maSheetViews.back();
257         rModel.maSecondPos    = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false );
258         rModel.mnActivePaneId = rAttribs.getToken( XML_activePane, XML_topLeft );
259         rModel.mnPaneState    = rAttribs.getToken( XML_state, XML_split );
260         rModel.mfSplitX       = rAttribs.getDouble( XML_xSplit, 0.0 );
261         rModel.mfSplitY       = rAttribs.getDouble( XML_ySplit, 0.0 );
262     }
263 }
264 
265 void SheetViewSettings::importSelection( const AttributeList& rAttribs )
266 {
267     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" );
268     if( !maSheetViews.empty() )
269     {
270         // pane this selection belongs to
271         sal_Int32 nPaneId = rAttribs.getToken( XML_pane, XML_topLeft );
272         PaneSelectionModel& rSelData = maSheetViews.back()->createPaneSelection( nPaneId );
273         // cursor position
274         rSelData.maActiveCell = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_activeCell, OUString() ), getSheetIndex(), false );
275         rSelData.mnActiveCellId = rAttribs.getInteger( XML_activeCellId, 0 );
276         // selection
277         rSelData.maSelection.clear();
278         getAddressConverter().convertToCellRangeList( rSelData.maSelection, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), false );
279     }
280 }
281 
282 void SheetViewSettings::importChartSheetView( const AttributeList& rAttribs )
283 {
284     SheetViewModel& rModel = *createSheetView();
285     rModel.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 );
286     rModel.mnCurrentZoom    = rAttribs.getInteger( XML_zoomScale, 100 );
287     rModel.mbSelected       = rAttribs.getBool( XML_tabSelected, false );
288     rModel.mbZoomToFit      = rAttribs.getBool( XML_zoomToFit, false );
289 }
290 
291 void SheetViewSettings::importSheetView( SequenceInputStream& rStrm )
292 {
293     SheetViewModel& rModel = *createSheetView();
294     sal_uInt16 nFlags;
295     sal_Int32 nViewType;
296     BinAddress aFirstPos;
297     rStrm >> nFlags >> nViewType >> aFirstPos;
298     rModel.maGridColor.importColorId( rStrm );
299     rModel.mnCurrentZoom = rStrm.readuInt16();
300     rModel.mnNormalZoom = rStrm.readuInt16();
301     rModel.mnSheetLayoutZoom = rStrm.readuInt16();
302     rModel.mnPageLayoutZoom = rStrm.readuInt16();
303     rStrm >> rModel.mnWorkbookViewId;
304 
305     rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false );
306     static const sal_Int32 spnViewTypes[] = { XML_normal, XML_pageBreakPreview, XML_pageLayout };
307     rModel.mnViewType = STATIC_ARRAY_SELECT( spnViewTypes, nViewType, XML_normal );
308     rModel.mbSelected     = getFlag( nFlags, BIFF12_SHEETVIEW_SELECTED );
309     rModel.mbRightToLeft  = getFlag( nFlags, BIFF12_SHEETVIEW_RIGHTTOLEFT );
310     rModel.mbDefGridColor = getFlag( nFlags, BIFF12_SHEETVIEW_DEFGRIDCOLOR );
311     rModel.mbShowFormulas = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWFORMULAS );
312     rModel.mbShowGrid     = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWGRID );
313     rModel.mbShowHeadings = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWHEADINGS );
314     rModel.mbShowZeros    = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWZEROS );
315     rModel.mbShowOutline  = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWOUTLINE );
316 }
317 
318 void SheetViewSettings::importPane( SequenceInputStream& rStrm )
319 {
320     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" );
321     if( !maSheetViews.empty() )
322     {
323         SheetViewModel& rModel = *maSheetViews.back();
324 
325         BinAddress aSecondPos;
326         sal_Int32 nActivePaneId;
327         sal_uInt8 nFlags;
328         rStrm >> rModel.mfSplitX >> rModel.mfSplitY >> aSecondPos >> nActivePaneId >> nFlags;
329 
330         rModel.maSecondPos    = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false );
331         rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft );
332         rModel.mnPaneState    = getFlagValue( nFlags, BIFF12_PANE_FROZEN, getFlagValue( nFlags, BIFF12_PANE_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split );
333     }
334 }
335 
336 void SheetViewSettings::importSelection( SequenceInputStream& rStrm )
337 {
338     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" );
339     if( !maSheetViews.empty() )
340     {
341         // pane this selection belongs to
342         sal_Int32 nPaneId = rStrm.readInt32();
343         PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) );
344         // cursor position
345         BinAddress aActiveCell;
346         rStrm >> aActiveCell >> rPaneSel.mnActiveCellId;
347         rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false );
348         // selection
349         BinRangeList aSelection;
350         rStrm >> aSelection;
351         rPaneSel.maSelection.clear();
352         getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false );
353     }
354 }
355 
356 void SheetViewSettings::importChartSheetView( SequenceInputStream& rStrm )
357 {
358     SheetViewModel& rModel = *createSheetView();
359     sal_uInt16 nFlags;
360     rStrm >> nFlags >> rModel.mnCurrentZoom >> rModel.mnWorkbookViewId;
361 
362     rModel.mbSelected  = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_SELECTED );
363     rModel.mbZoomToFit = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_ZOOMTOFIT );
364 }
365 
366 void SheetViewSettings::importWindow2( BiffInputStream& rStrm )
367 {
368     OSL_ENSURE( maSheetViews.empty(), "SheetViewSettings::importWindow2 - multiple WINDOW2 records" );
369     SheetViewModel& rModel = *createSheetView();
370     if( getBiff() == BIFF2 )
371     {
372         rModel.mbShowFormulas = rStrm.readuInt8() != 0;
373         rModel.mbShowGrid = rStrm.readuInt8() != 0;
374         rModel.mbShowHeadings = rStrm.readuInt8() != 0;
375         rModel.mnPaneState = (rStrm.readuInt8() == 0) ? XML_split : XML_frozen;
376         rModel.mbShowZeros = rStrm.readuInt8() != 0;
377         BinAddress aFirstPos;
378         rStrm >> aFirstPos;
379         rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false );
380         rModel.mbDefGridColor = rStrm.readuInt8() != 0;
381         rModel.maGridColor.importColorRgb( rStrm );
382     }
383     else
384     {
385         sal_uInt16 nFlags;
386         BinAddress aFirstPos;
387         rStrm >> nFlags >> aFirstPos;
388 
389         rModel.maFirstPos     = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false );
390         rModel.mnPaneState    = getFlagValue( nFlags, BIFF_WINDOW2_FROZEN, getFlagValue( nFlags, BIFF_WINDOW2_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split );
391         rModel.mbSelected     = getFlag( nFlags, BIFF_WINDOW2_SELECTED );
392         rModel.mbRightToLeft  = getFlag( nFlags, BIFF_WINDOW2_RIGHTTOLEFT );
393         rModel.mbDefGridColor = getFlag( nFlags, BIFF_WINDOW2_DEFGRIDCOLOR );
394         rModel.mbShowFormulas = getFlag( nFlags, BIFF_WINDOW2_SHOWFORMULAS );
395         rModel.mbShowGrid     = getFlag( nFlags, BIFF_WINDOW2_SHOWGRID );
396         rModel.mbShowHeadings = getFlag( nFlags, BIFF_WINDOW2_SHOWHEADINGS );
397         rModel.mbShowZeros    = getFlag( nFlags, BIFF_WINDOW2_SHOWZEROS );
398         rModel.mbShowOutline  = getFlag( nFlags, BIFF_WINDOW2_SHOWOUTLINE );
399 
400         if( getBiff() == BIFF8 )
401         {
402             rModel.mnViewType = getFlagValue( nFlags, BIFF_WINDOW2_PAGEBREAKMODE, XML_pageBreakPreview, XML_normal );
403 
404             rModel.maGridColor.importColorId( rStrm );
405             // zoom data not included in chart sheets
406             if( (getSheetType() != SHEETTYPE_CHARTSHEET) && (rStrm.getRemaining() >= 6) )
407             {
408                 rStrm.skip( 2 );
409                 sal_uInt16 nPageZoom, nNormalZoom;
410                 rStrm >> nPageZoom >> nNormalZoom;
411                 rModel.mnSheetLayoutZoom = nPageZoom;
412                 rModel.mnNormalZoom = nNormalZoom;
413             }
414         }
415         else
416         {
417             rModel.maGridColor.importColorRgb( rStrm );
418         }
419     }
420 }
421 
422 void SheetViewSettings::importPane( BiffInputStream& rStrm )
423 {
424     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" );
425     if( !maSheetViews.empty() )
426     {
427         sal_uInt8 nActivePaneId;
428         sal_uInt16 nSplitX, nSplitY;
429         BinAddress aSecondPos;
430         rStrm >> nSplitX >> nSplitY >> aSecondPos >> nActivePaneId;
431 
432         SheetViewModel& rModel = *maSheetViews.back();
433         rModel.mfSplitX = nSplitX;
434         rModel.mfSplitY = nSplitY;
435         rModel.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false );
436         rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft );
437     }
438 }
439 
440 void SheetViewSettings::importScl( BiffInputStream& rStrm )
441 {
442     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importScl - missing leading WINDOW2 record" );
443     if( !maSheetViews.empty() )
444     {
445         sal_uInt16 nNum, nDenom;
446         rStrm >> nNum >> nDenom;
447         OSL_ENSURE( nDenom > 0, "SheetViewSettings::importScl - invalid denominator" );
448         if( nDenom > 0 )
449             maSheetViews.back()->mnCurrentZoom = getLimitedValue< sal_Int32, sal_uInt16 >( (nNum * 100) / nDenom, 10, 400 );
450     }
451 }
452 
453 void SheetViewSettings::importSelection( BiffInputStream& rStrm )
454 {
455     OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" );
456     if( !maSheetViews.empty() )
457     {
458         // pane this selection belongs to
459         sal_uInt8 nPaneId = rStrm.readuInt8();
460         PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) );
461         // cursor position
462         BinAddress aActiveCell;
463         sal_uInt16 nActiveCellId;
464         rStrm >> aActiveCell >> nActiveCellId;
465         rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false );
466         rPaneSel.mnActiveCellId = nActiveCellId;
467         // selection
468         rPaneSel.maSelection.clear();
469         BinRangeList aSelection;
470         aSelection.read( rStrm, false );
471         getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false );
472     }
473 }
474 
475 void SheetViewSettings::finalizeImport()
476 {
477     // force creation of sheet view model to get the Excel defaults
478     SheetViewModelRef xModel = maSheetViews.empty() ? createSheetView() : maSheetViews.front();
479 
480     // #i59590# #158194# special handling for chart sheets (Excel ignores some settings in chart sheets)
481     if( getSheetType() == SHEETTYPE_CHARTSHEET )
482     {
483         xModel->maPaneSelMap.clear();
484         xModel->maFirstPos = xModel->maSecondPos = CellAddress( getSheetIndex(), 0, 0 );
485         xModel->mnViewType = XML_normal;
486         xModel->mnActivePaneId = XML_topLeft;
487         xModel->mnPaneState = XML_split;
488         xModel->mfSplitX = xModel->mfSplitY = 0.0;
489         xModel->mbRightToLeft = false;
490         xModel->mbDefGridColor = true;
491         xModel->mbShowFormulas = false;
492         xModel->mbShowGrid = true;
493         xModel->mbShowHeadings = true;
494         xModel->mbShowZeros = true;
495         xModel->mbShowOutline = true;
496     }
497 
498     // sheet selected (active sheet must be selected)
499     bool bSelected = xModel->mbSelected || (getSheetIndex() == getViewSettings().getActiveCalcSheet());
500 
501     // visible area and current cursor position (selection not supported via API)
502     CellAddress aFirstPos = xModel->maFirstPos;
503     const PaneSelectionModel* pPaneSel = xModel->getActiveSelection();
504     CellAddress aCursor = pPaneSel ? pPaneSel->maActiveCell : aFirstPos;
505 
506     // freeze/split position default
507     sal_Int16 nHSplitMode = API_SPLITMODE_NONE;
508     sal_Int16 nVSplitMode = API_SPLITMODE_NONE;
509     sal_Int32 nHSplitPos = 0;
510     sal_Int32 nVSplitPos = 0;
511     // active pane default
512     sal_Int16 nActivePane = API_SPLITPANE_BOTTOMLEFT;
513 
514     // freeze/split position
515     if( (xModel->mnPaneState == XML_frozen) || (xModel->mnPaneState == XML_frozenSplit) )
516     {
517         /*  Frozen panes: handle split position as row/column positions.
518             #i35812# Excel uses number of visible rows/columns in the
519                 frozen area (rows/columns scolled outside are not incuded),
520                 Calc uses absolute position of first unfrozen row/column. */
521         const CellAddress& rMaxApiPos = getAddressConverter().getMaxApiAddress();
522         if( (xModel->mfSplitX >= 1.0) && (xModel->maFirstPos.Column + xModel->mfSplitX <= rMaxApiPos.Column) )
523             nHSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Column + xModel->mfSplitX );
524         nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE;
525         if( (xModel->mfSplitY >= 1.0) && (xModel->maFirstPos.Row + xModel->mfSplitY <= rMaxApiPos.Row) )
526             nVSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Row + xModel->mfSplitY );
527         nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE;
528     }
529     else if( xModel->mnPaneState == XML_split )
530     {
531         // split window: view settings API uses twips...
532         nHSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitX + 0.5, 0, SAL_MAX_INT32 );
533         nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE;
534         nVSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitY + 0.5, 0, SAL_MAX_INT32 );
535         nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE;
536     }
537 
538     // active pane
539     switch( xModel->mnActivePaneId )
540     {
541         // no horizontal split -> always use left panes
542         // no vertical split -> always use *bottom* panes
543         case XML_topLeft:
544             nActivePane = (nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT;
545         break;
546         case XML_topRight:
547             nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ?
548                 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT) :
549                 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMRIGHT : API_SPLITPANE_TOPRIGHT);
550         break;
551         case XML_bottomLeft:
552             nActivePane = API_SPLITPANE_BOTTOMLEFT;
553         break;
554         case XML_bottomRight:
555             nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_BOTTOMRIGHT;
556         break;
557     }
558 
559     // write the sheet view settings into the property sequence
560     PropertyMap aPropMap;
561     aPropMap[ PROP_TableSelected ]                <<= bSelected;
562     aPropMap[ PROP_CursorPositionX ]              <<= aCursor.Column;
563     aPropMap[ PROP_CursorPositionY ]              <<= aCursor.Row;
564     aPropMap[ PROP_HorizontalSplitMode ]          <<= nHSplitMode;
565     aPropMap[ PROP_VerticalSplitMode ]            <<= nVSplitMode;
566     aPropMap[ PROP_HorizontalSplitPositionTwips ] <<= nHSplitPos;
567     aPropMap[ PROP_VerticalSplitPositionTwips ]   <<= nVSplitPos;
568     aPropMap[ PROP_ActiveSplitRange ]             <<= nActivePane;
569     aPropMap[ PROP_PositionLeft ]                 <<= aFirstPos.Column;
570     aPropMap[ PROP_PositionTop ]                  <<= aFirstPos.Row;
571     aPropMap[ PROP_PositionRight ]                <<= xModel->maSecondPos.Column;
572     aPropMap[ PROP_PositionBottom ]               <<= ((nVSplitPos > 0) ? xModel->maSecondPos.Row : xModel->maFirstPos.Row);
573     aPropMap[ PROP_ZoomType ]                     <<= API_ZOOMTYPE_PERCENT;
574     aPropMap[ PROP_ZoomValue ]                    <<= static_cast< sal_Int16 >( xModel->getNormalZoom() );
575     aPropMap[ PROP_PageViewZoomValue ]            <<= static_cast< sal_Int16 >( xModel->getPageBreakZoom() );
576     aPropMap[ PROP_GridColor ]                    <<= xModel->getGridColor( getBaseFilter() );
577     aPropMap[ PROP_ShowPageBreakPreview ]         <<= xModel->isPageBreakPreview();
578     aPropMap[ PROP_ShowFormulas ]                 <<= xModel->mbShowFormulas;
579     aPropMap[ PROP_ShowGrid ]                     <<= xModel->mbShowGrid;
580     aPropMap[ PROP_HasColumnRowHeaders ]          <<= xModel->mbShowHeadings;
581     aPropMap[ PROP_ShowZeroValues ]               <<= xModel->mbShowZeros;
582     aPropMap[ PROP_IsOutlineSymbolsSet ]          <<= xModel->mbShowOutline;
583 
584     // store sheet view settings in global view settings object
585     getViewSettings().setSheetViewSettings( getSheetIndex(), xModel, Any( aPropMap.makePropertyValueSequence() ) );
586 }
587 
588 bool SheetViewSettings::isSheetRightToLeft() const
589 {
590     return !maSheetViews.empty() && maSheetViews.front()->mbRightToLeft;
591 }
592 
593 // private --------------------------------------------------------------------
594 
595 SheetViewModelRef SheetViewSettings::createSheetView()
596 {
597     SheetViewModelRef xModel( new SheetViewModel );
598     maSheetViews.push_back( xModel );
599     return xModel;
600 }
601 
602 // ============================================================================
603 
604 WorkbookViewModel::WorkbookViewModel() :
605     mnWinX( 0 ),
606     mnWinY( 0 ),
607     mnWinWidth( 0 ),
608     mnWinHeight( 0 ),
609     mnActiveSheet( 0 ),
610     mnFirstVisSheet( 0 ),
611     mnTabBarWidth( OOX_BOOKVIEW_TABBARRATIO_DEF ),
612     mnVisibility( XML_visible ),
613     mbShowTabBar( true ),
614     mbShowHorScroll( true ),
615     mbShowVerScroll( true ),
616     mbMinimized( false )
617 {
618 }
619 
620 // ----------------------------------------------------------------------------
621 
622 ViewSettings::ViewSettings( const WorkbookHelper& rHelper ) :
623     WorkbookHelper( rHelper ),
624     mbValidOleSize( false )
625 {
626 }
627 
628 void ViewSettings::importWorkbookView( const AttributeList& rAttribs )
629 {
630     WorkbookViewModel& rModel = createWorkbookView();
631     rModel.mnWinX          = rAttribs.getInteger( XML_xWindow, 0 );
632     rModel.mnWinY          = rAttribs.getInteger( XML_yWindow, 0 );
633     rModel.mnWinWidth      = rAttribs.getInteger( XML_windowWidth, 0 );
634     rModel.mnWinHeight     = rAttribs.getInteger( XML_windowHeight, 0 );
635     rModel.mnActiveSheet   = rAttribs.getInteger( XML_activeTab, 0 );
636     rModel.mnFirstVisSheet = rAttribs.getInteger( XML_firstSheet, 0 );
637     rModel.mnTabBarWidth   = rAttribs.getInteger( XML_tabRatio, 600 );
638     rModel.mnVisibility    = rAttribs.getToken( XML_visibility, XML_visible );
639     rModel.mbShowTabBar    = rAttribs.getBool( XML_showSheetTabs, true );
640     rModel.mbShowHorScroll = rAttribs.getBool( XML_showHorizontalScroll, true );
641     rModel.mbShowVerScroll = rAttribs.getBool( XML_showVerticalScroll, true );
642     rModel.mbMinimized     = rAttribs.getBool( XML_minimized, false );
643 }
644 
645 void ViewSettings::importOleSize( const AttributeList& rAttribs )
646 {
647     OUString aRange = rAttribs.getString( XML_ref, OUString() );
648     mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aRange, 0, true, false );
649 }
650 
651 void ViewSettings::importWorkbookView( SequenceInputStream& rStrm )
652 {
653     WorkbookViewModel& rModel = createWorkbookView();
654     sal_uInt8 nFlags;
655     rStrm >> rModel.mnWinX >> rModel.mnWinY >> rModel.mnWinWidth >> rModel.mnWinHeight >> rModel.mnTabBarWidth >> rModel.mnFirstVisSheet >> rModel.mnActiveSheet >> nFlags;
656     rModel.mnVisibility    = getFlagValue( nFlags, BIFF12_WBVIEW_HIDDEN, XML_hidden, XML_visible );
657     rModel.mbShowTabBar    = getFlag( nFlags, BIFF12_WBVIEW_SHOWTABBAR );
658     rModel.mbShowHorScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWHORSCROLL );
659     rModel.mbShowVerScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWVERSCROLL );
660     rModel.mbMinimized     = getFlag( nFlags, BIFF12_WBVIEW_MINIMIZED );
661 }
662 
663 void ViewSettings::importOleSize( SequenceInputStream& rStrm )
664 {
665     BinRange aBinRange;
666     rStrm >> aBinRange;
667     mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false );
668 }
669 
670 void ViewSettings::importWindow1( BiffInputStream& rStrm )
671 {
672     sal_uInt16 nWinX, nWinY, nWinWidth, nWinHeight;
673     rStrm >> nWinX >> nWinY >> nWinWidth >> nWinHeight;
674 
675     // WINDOW1 record occures in every sheet in BIFF4W
676     OSL_ENSURE( maBookViews.empty() || ((getBiff() == BIFF4) && isWorkbookFile()),
677         "ViewSettings::importWindow1 - multiple WINDOW1 records" );
678     WorkbookViewModel& rModel = createWorkbookView();
679     rModel.mnWinX = nWinX;
680     rModel.mnWinY = nWinY;
681     rModel.mnWinWidth = nWinWidth;
682     rModel.mnWinHeight = nWinHeight;
683 
684     if( getBiff() <= BIFF4 )
685     {
686         sal_uInt8 nHidden;
687         rStrm >> nHidden;
688         rModel.mnVisibility = (nHidden == 0) ? XML_visible : XML_hidden;
689     }
690     else
691     {
692         sal_uInt16 nFlags, nActiveTab, nFirstVisTab, nSelectCnt, nTabBarWidth;
693         rStrm >> nFlags >> nActiveTab >> nFirstVisTab >> nSelectCnt >> nTabBarWidth;
694 
695         rModel.mnActiveSheet = nActiveTab;
696         rModel.mnFirstVisSheet = nFirstVisTab;
697         rModel.mnTabBarWidth = nTabBarWidth;
698         rModel.mnVisibility = getFlagValue( nFlags, BIFF_WINDOW1_HIDDEN, XML_hidden, XML_visible );
699         rModel.mbMinimized = getFlag( nFlags, BIFF_WINDOW1_MINIMIZED );
700         rModel.mbShowHorScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWHORSCROLL );
701         rModel.mbShowVerScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWVERSCROLL );
702         rModel.mbShowTabBar = getFlag( nFlags, BIFF_WINDOW1_SHOWTABBAR );
703     }
704 }
705 
706 void ViewSettings::importOleSize( BiffInputStream& rStrm )
707 {
708     rStrm.skip( 2 );
709     BinRange aBinRange;
710     aBinRange.read( rStrm, false );
711     mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false );
712 }
713 
714 void ViewSettings::setSheetViewSettings( sal_Int16 nSheet, const SheetViewModelRef& rxSheetView, const Any& rProperties )
715 {
716     maSheetViews[ nSheet ] = rxSheetView;
717     maSheetProps[ nSheet ] = rProperties;
718 }
719 
720 void ViewSettings::setSheetUsedArea( const CellRangeAddress& rUsedArea )
721 {
722     maSheetUsedAreas[ rUsedArea.Sheet ] = rUsedArea;
723 }
724 
725 void ViewSettings::finalizeImport()
726 {
727     const WorksheetBuffer& rWorksheets = getWorksheets();
728     if( rWorksheets.getWorksheetCount() <= 0 ) return;
729 
730     // force creation of workbook view model to get the Excel defaults
731     const WorkbookViewModel& rModel = maBookViews.empty() ? createWorkbookView() : *maBookViews.front();
732 
733     // show object mode is part of workbook settings
734     sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode();
735 
736     // view settings for all sheets
737     Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getComponentContext() );
738     if( !xSheetsNC.is() ) return;
739     for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt )
740         ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second );
741 
742     // use active sheet to set sheet properties that are document-global in Calc
743     sal_Int16 nActiveSheet = getActiveCalcSheet();
744     SheetViewModelRef& rxActiveSheetView = maSheetViews[ nActiveSheet ];
745     OSL_ENSURE( rxActiveSheetView.get(), "ViewSettings::finalizeImport - missing active sheet view settings" );
746     if( !rxActiveSheetView )
747         rxActiveSheetView.reset( new SheetViewModel );
748 
749     Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getComponentContext() );
750     if( xContainer.is() ) try
751     {
752         PropertyMap aPropMap;
753         aPropMap[ PROP_Tables ]                        <<= xSheetsNC;
754         aPropMap[ PROP_ActiveTable ]                   <<= rWorksheets.getCalcSheetName( nActiveSheet );
755         aPropMap[ PROP_HasHorizontalScrollBar ]        <<= rModel.mbShowHorScroll;
756         aPropMap[ PROP_HasVerticalScrollBar ]          <<= rModel.mbShowVerScroll;
757         aPropMap[ PROP_HasSheetTabs ]                  <<= rModel.mbShowTabBar;
758         aPropMap[ PROP_RelativeHorizontalTabbarWidth ] <<= double( rModel.mnTabBarWidth / 1000.0 );
759         aPropMap[ PROP_ShowObjects ]                   <<= nShowMode;
760         aPropMap[ PROP_ShowCharts ]                    <<= nShowMode;
761         aPropMap[ PROP_ShowDrawing ]                   <<= nShowMode;
762         aPropMap[ PROP_GridColor ]                     <<= rxActiveSheetView->getGridColor( getBaseFilter() );
763         aPropMap[ PROP_ShowPageBreakPreview ]          <<= rxActiveSheetView->isPageBreakPreview();
764         aPropMap[ PROP_ShowFormulas ]                  <<= rxActiveSheetView->mbShowFormulas;
765         aPropMap[ PROP_ShowGrid ]                      <<= rxActiveSheetView->mbShowGrid;
766         aPropMap[ PROP_HasColumnRowHeaders ]           <<= rxActiveSheetView->mbShowHeadings;
767         aPropMap[ PROP_ShowZeroValues ]                <<= rxActiveSheetView->mbShowZeros;
768         aPropMap[ PROP_IsOutlineSymbolsSet ]           <<= rxActiveSheetView->mbShowOutline;
769 
770         xContainer->insertByIndex( 0, Any( aPropMap.makePropertyValueSequence() ) );
771         Reference< XIndexAccess > xIAccess( xContainer, UNO_QUERY_THROW );
772         Reference< XViewDataSupplier > xViewDataSuppl( getDocument(), UNO_QUERY_THROW );
773         xViewDataSuppl->setViewData( xIAccess );
774     }
775     catch( Exception& )
776     {
777         OSL_ENSURE( false, "ViewSettings::finalizeImport - cannot create document view settings" );
778     }
779 
780     /*  Set visible area to be used if this document is an embedded OLE object.
781         #i44077# If a new OLE object is inserted from file, there is no OLESIZE
782         record in the Excel file. In this case, use the used area calculated
783         from file contents (used cells and drawing objects). */
784     maOleSize.Sheet = nActiveSheet;
785     const CellRangeAddress* pVisibleArea = mbValidOleSize ?
786         &maOleSize : ContainerHelper::getMapElement( maSheetUsedAreas, nActiveSheet );
787     if( pVisibleArea )
788     {
789         // calculate the visible area in units of 1/100 mm
790         PropertySet aRangeProp( getCellRangeFromDoc( *pVisibleArea ) );
791         Point aPos;
792         Size aSize;
793         if( aRangeProp.getProperty( aPos, PROP_Position ) && aRangeProp.getProperty( aSize, PROP_Size ) )
794         {
795             // set the visible area as sequence of long at the media descriptor
796             Sequence< sal_Int32 > aWinExtent( 4 );
797             aWinExtent[ 0 ] = aPos.X;
798             aWinExtent[ 1 ] = aPos.Y;
799             aWinExtent[ 2 ] = aPos.X + aSize.Width;
800             aWinExtent[ 3 ] = aPos.Y + aSize.Height;
801             getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "WinExtent" ) ] <<= aWinExtent;
802         }
803     }
804 }
805 
806 sal_Int16 ViewSettings::getActiveCalcSheet() const
807 {
808     return maBookViews.empty() ? 0 : ::std::max< sal_Int16 >( getWorksheets().getCalcSheetIndex( maBookViews.front()->mnActiveSheet ), 0 );
809 }
810 
811 // private --------------------------------------------------------------------
812 
813 WorkbookViewModel& ViewSettings::createWorkbookView()
814 {
815     WorkbookViewModelRef xModel( new WorkbookViewModel );
816     maBookViews.push_back( xModel );
817     return *xModel;
818 }
819 
820 // ============================================================================
821 
822 } // namespace xls
823 } // namespace oox
824