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 <xeview.hxx>
21 #include <document.hxx>
22 #include <scextopt.hxx>
23 #include <viewopti.hxx>
24 #include <xelink.hxx>
25 #include <xestyle.hxx>
26 #include <xehelper.hxx>
27 #include <xltools.hxx>
28 #include <oox/token/tokens.hxx>
29 #include <oox/export/utils.hxx>
30 
31 using namespace ::oox;
32 
33 // Workbook view settings records =============================================
34 
XclExpWindow1(const XclExpRoot & rRoot)35 XclExpWindow1::XclExpWindow1( const XclExpRoot& rRoot )
36     : XclExpRecord(EXC_ID_WINDOW1, 18)
37     , mnFlags(0)
38     , mnTabBarSize(600)
39 {
40     const ScViewOptions& rViewOpt = rRoot.GetDoc().GetViewOptions();
41     ::set_flag( mnFlags, EXC_WIN1_HOR_SCROLLBAR,    rViewOpt.GetOption( VOPT_HSCROLL ) );
42     ::set_flag( mnFlags, EXC_WIN1_VER_SCROLLBAR,    rViewOpt.GetOption( VOPT_VSCROLL ) );
43     ::set_flag( mnFlags, EXC_WIN1_TABBAR,           rViewOpt.GetOption( VOPT_TABCONTROLS ) );
44 
45     double fTabBarWidth = rRoot.GetExtDocOptions().GetDocSettings().mfTabBarWidth;
46     if( (0.0 <= fTabBarWidth) && (fTabBarWidth <= 1.0) )
47         mnTabBarSize = static_cast< sal_uInt16 >( fTabBarWidth * 1000.0 + 0.5 );
48 }
49 
SaveXml(XclExpXmlStream & rStrm)50 void XclExpWindow1::SaveXml( XclExpXmlStream& rStrm )
51 {
52     const XclExpTabInfo& rTabInfo = rStrm.GetRoot().GetTabInfo();
53 
54     rStrm.GetCurrentStream()->singleElement( XML_workbookView,
55             // OOXTODO: XML_visibility, // ST_visibility
56             // OOXTODO: XML_minimized,  // bool
57             XML_showHorizontalScroll,   ToPsz( ::get_flag( mnFlags, EXC_WIN1_HOR_SCROLLBAR ) ),
58             XML_showVerticalScroll,     ToPsz( ::get_flag( mnFlags, EXC_WIN1_VER_SCROLLBAR ) ),
59             XML_showSheetTabs,          ToPsz( ::get_flag( mnFlags, EXC_WIN1_TABBAR ) ),
60             XML_xWindow,                "0",
61             XML_yWindow,                "0",
62             XML_windowWidth,            OString::number(0x4000),
63             XML_windowHeight,           OString::number(0x2000),
64             XML_tabRatio,               OString::number(mnTabBarSize),
65             XML_firstSheet,             OString::number(rTabInfo.GetFirstVisXclTab()),
66             XML_activeTab,              OString::number(rTabInfo.GetDisplayedXclTab())
67             // OOXTODO: XML_autoFilterDateGrouping,     // bool; AUTOFILTER12? 87Eh
68     );
69 }
70 
WriteBody(XclExpStream & rStrm)71 void XclExpWindow1::WriteBody( XclExpStream& rStrm )
72 {
73     const XclExpTabInfo& rTabInfo = rStrm.GetRoot().GetTabInfo();
74 
75     rStrm   << sal_uInt16( 0 )              // X position of the window
76             << sal_uInt16( 0 )              // Y position of the window
77             << sal_uInt16( 0x4000 )         // width of the window
78             << sal_uInt16( 0x2000 )         // height of the window
79             << mnFlags
80             << rTabInfo.GetDisplayedXclTab()
81             << rTabInfo.GetFirstVisXclTab()
82             << rTabInfo.GetXclSelectedCount()
83             << mnTabBarSize;
84 }
85 
86 // Sheet view settings records ================================================
87 
XclExpWindow2(const XclExpRoot & rRoot,const XclTabViewData & rData,sal_uInt32 nGridColorId)88 XclExpWindow2::XclExpWindow2( const XclExpRoot& rRoot,
89         const XclTabViewData& rData, sal_uInt32 nGridColorId ) :
90     XclExpRecord( EXC_ID_WINDOW2, (rRoot.GetBiff() == EXC_BIFF8) ? 18 : 10 ),
91     maGridColor( rData.maGridColor ),
92     mnGridColorId( nGridColorId ),
93     mnFlags( 0 ),
94     maFirstXclPos( rData.maFirstXclPos ),
95     mnNormalZoom( rData.mnNormalZoom ),
96     mnPageZoom( rData.mnPageZoom )
97 {
98     ::set_flag( mnFlags, EXC_WIN2_SHOWFORMULAS,     rData.mbShowFormulas );
99     ::set_flag( mnFlags, EXC_WIN2_SHOWGRID,         rData.mbShowGrid );
100     ::set_flag( mnFlags, EXC_WIN2_SHOWHEADINGS,     rData.mbShowHeadings );
101     ::set_flag( mnFlags, EXC_WIN2_FROZEN,           rData.mbFrozenPanes );
102     ::set_flag( mnFlags, EXC_WIN2_SHOWZEROS,        rData.mbShowZeros );
103     ::set_flag( mnFlags, EXC_WIN2_DEFGRIDCOLOR,     rData.mbDefGridColor );
104     ::set_flag( mnFlags, EXC_WIN2_MIRRORED,         rData.mbMirrored );
105     ::set_flag( mnFlags, EXC_WIN2_SHOWOUTLINE,      rData.mbShowOutline );
106     ::set_flag( mnFlags, EXC_WIN2_FROZENNOSPLIT,    rData.mbFrozenPanes );
107     ::set_flag( mnFlags, EXC_WIN2_SELECTED,         rData.mbSelected );
108     ::set_flag( mnFlags, EXC_WIN2_DISPLAYED,        rData.mbDisplayed );
109     ::set_flag( mnFlags, EXC_WIN2_PAGEBREAKMODE,    rData.mbPageMode );
110 }
111 
WriteBody(XclExpStream & rStrm)112 void XclExpWindow2::WriteBody( XclExpStream& rStrm )
113 {
114     const XclExpRoot& rRoot = rStrm.GetRoot();
115 
116     rStrm   << mnFlags
117             << maFirstXclPos;
118 
119     switch( rRoot.GetBiff() )
120     {
121         case EXC_BIFF3:
122         case EXC_BIFF4:
123         case EXC_BIFF5:
124             rStrm   << maGridColor;
125         break;
126         case EXC_BIFF8:
127             rStrm   << rRoot.GetPalette().GetColorIndex( mnGridColorId )
128                     << sal_uInt16( 0 )
129                     << mnPageZoom
130                     << mnNormalZoom
131                     << sal_uInt32( 0 );
132         break;
133         default:    DBG_ERROR_BIFF();
134     }
135 }
136 
XclExpScl(sal_uInt16 nZoom)137 XclExpScl::XclExpScl( sal_uInt16 nZoom ) :
138     XclExpRecord( EXC_ID_SCL, 4 ),
139     mnNum( nZoom ),
140     mnDenom( 100 )
141 {
142     Shorten( 2 );
143     Shorten( 5 );
144 }
145 
Shorten(sal_uInt16 nFactor)146 void XclExpScl::Shorten( sal_uInt16 nFactor )
147 {
148     while( (mnNum % nFactor == 0) && (mnDenom % nFactor == 0) )
149     {
150         mnNum = mnNum / nFactor;
151         mnDenom = mnDenom / nFactor;
152     }
153 }
154 
WriteBody(XclExpStream & rStrm)155 void XclExpScl::WriteBody( XclExpStream& rStrm )
156 {
157     OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF4 );
158     rStrm << mnNum << mnDenom;
159 }
160 
XclExpPane(const XclTabViewData & rData)161 XclExpPane::XclExpPane( const XclTabViewData& rData ) :
162     XclExpRecord( EXC_ID_PANE, 10 ),
163     mnSplitX( rData.mnSplitX ),
164     mnSplitY( rData.mnSplitY ),
165     maSecondXclPos( rData.maSecondXclPos ),
166     mnActivePane( rData.mnActivePane ),
167     mbFrozenPanes( rData.mbFrozenPanes )
168 {
169     OSL_ENSURE( rData.IsSplit(), "XclExpPane::XclExpPane - no PANE record for unsplit view" );
170 }
171 
lcl_GetActivePane(sal_uInt8 nActivePane)172 static const char* lcl_GetActivePane( sal_uInt8 nActivePane )
173 {
174     switch( nActivePane )
175     {
176         case EXC_PANE_TOPLEFT:      return "topLeft";
177         case EXC_PANE_TOPRIGHT:     return "topRight";
178         case EXC_PANE_BOTTOMLEFT:   return "bottomLeft";
179         case EXC_PANE_BOTTOMRIGHT:  return "bottomRight";
180     }
181     return "**error: lcl_GetActivePane";
182 }
183 
SaveXml(XclExpXmlStream & rStrm)184 void XclExpPane::SaveXml( XclExpXmlStream& rStrm )
185 {
186     rStrm.GetCurrentStream()->singleElement( XML_pane,
187             XML_xSplit,         OString::number(mnSplitX),
188             XML_ySplit,         OString::number(mnSplitY),
189             XML_topLeftCell,    XclXmlUtils::ToOString( rStrm.GetRoot().GetStringBuf(), maSecondXclPos ).getStr(),
190             XML_activePane,     lcl_GetActivePane( mnActivePane ),
191             XML_state,          mbFrozenPanes ? "frozen" : "split" );
192 }
193 
WriteBody(XclExpStream & rStrm)194 void XclExpPane::WriteBody( XclExpStream& rStrm )
195 {
196     rStrm   << mnSplitX
197             << static_cast<sal_uInt16>( mnSplitY )
198             << maSecondXclPos
199             << mnActivePane;
200     if( rStrm.GetRoot().GetBiff() >= EXC_BIFF5 )
201         rStrm << sal_uInt8( 0 );
202 }
203 
XclExpSelection(const XclTabViewData & rData,sal_uInt8 nPane)204 XclExpSelection::XclExpSelection( const XclTabViewData& rData, sal_uInt8 nPane ) :
205     XclExpRecord( EXC_ID_SELECTION, 15 ),
206     mnPane( nPane )
207 {
208     if( const XclSelectionData* pSelData = rData.GetSelectionData( nPane ) )
209         maSelData = *pSelData;
210 
211     // find the cursor position in the selection list (or add it)
212     XclRangeList& rXclSel = maSelData.maXclSelection;
213     auto aIt = std::find_if(rXclSel.begin(), rXclSel.end(),
214         [this](const XclRange& rRange) { return rRange.Contains(maSelData.maXclCursor); });
215     if (aIt != rXclSel.end())
216     {
217         maSelData.mnCursorIdx = static_cast< sal_uInt16 >( std::distance(rXclSel.begin(), aIt) );
218     }
219     else
220     {
221         /*  Cursor cell not found in list? (e.g. inactive pane, or removed in
222             ConvertRangeList(), because Calc cursor on invalid pos)
223             -> insert the valid Excel cursor. */
224         maSelData.mnCursorIdx = static_cast< sal_uInt16 >( rXclSel.size() );
225         rXclSel.push_back( XclRange( maSelData.maXclCursor ) );
226     }
227 }
228 
SaveXml(XclExpXmlStream & rStrm)229 void XclExpSelection::SaveXml( XclExpXmlStream& rStrm )
230 {
231     rStrm.GetCurrentStream()->singleElement( XML_selection,
232             XML_pane,           lcl_GetActivePane( mnPane ),
233             XML_activeCell,     XclXmlUtils::ToOString( rStrm.GetRoot().GetStringBuf(), maSelData.maXclCursor ).getStr(),
234             XML_activeCellId,   OString::number(maSelData.mnCursorIdx),
235             XML_sqref,          XclXmlUtils::ToOString(&rStrm.GetRoot().GetDoc(), maSelData.maXclSelection) );
236 }
237 
WriteBody(XclExpStream & rStrm)238 void XclExpSelection::WriteBody( XclExpStream& rStrm )
239 {
240     rStrm   << mnPane                   // pane for this selection
241             << maSelData.maXclCursor    // cell cursor
242             << maSelData.mnCursorIdx;   // index to range containing cursor
243     maSelData.maXclSelection.Write( rStrm, false );
244 }
245 
XclExpTabBgColor(const XclTabViewData & rTabViewData)246 XclExpTabBgColor::XclExpTabBgColor( const XclTabViewData& rTabViewData ) :
247     XclExpRecord( EXC_ID_SHEETEXT, 18 ),
248     mrTabViewData( rTabViewData )
249 {
250 }
251 //TODO Fix savexml...
252 /*void XclExpTabBgColor::SaveXml( XclExpXmlStream& rStrm )
253 {
254 }*/
255 
WriteBody(XclExpStream & rStrm)256 void XclExpTabBgColor::WriteBody( XclExpStream& rStrm )
257 {
258     if ( mrTabViewData.IsDefaultTabBgColor() )
259         return;
260     sal_uInt16 const rt = 0x0862; //rt
261     sal_uInt16 const grbitFrt = 0x0000; //grbit must be set to 0
262     sal_uInt32 unused = 0x00000000; //Use twice...
263     sal_uInt32 const cb = 0x00000014; // Record Size, may be larger in future...
264     sal_uInt16 const reserved = 0x0000; //trailing bits are 0
265     sal_uInt16 TabBgColorIndex;
266     XclExpPalette& rPal = rStrm.GetRoot().GetPalette();
267     TabBgColorIndex = rPal.GetColorIndex(mrTabViewData.mnTabBgColorId);
268     if (TabBgColorIndex < 8 || TabBgColorIndex > 63 ) // only numbers 8 - 63 are valid numbers
269         TabBgColorIndex = 127; //Excel specs: 127 makes excel ignore tab color information.
270     rStrm << rt << grbitFrt << unused << unused << cb << TabBgColorIndex << reserved;
271 }
272 
273 // Sheet view settings ========================================================
274 
275 namespace {
276 
277 /** Converts a Calc zoom factor into an Excel zoom factor. Returns 0 for a default zoom value. */
lclGetXclZoom(long nScZoom,sal_uInt16 nDefXclZoom)278 sal_uInt16 lclGetXclZoom( long nScZoom, sal_uInt16 nDefXclZoom )
279 {
280     sal_uInt16 nXclZoom = limit_cast< sal_uInt16 >( nScZoom, EXC_ZOOM_MIN, EXC_ZOOM_MAX );
281     return (nXclZoom == nDefXclZoom) ? 0 : nXclZoom;
282 }
283 
284 } // namespace
285 
XclExpTabViewSettings(const XclExpRoot & rRoot,SCTAB nScTab)286 XclExpTabViewSettings::XclExpTabViewSettings( const XclExpRoot& rRoot, SCTAB nScTab ) :
287     XclExpRoot( rRoot ),
288     mnGridColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT ) ),
289     mbHasTabSettings(false)
290 {
291     // *** sheet flags ***
292 
293     const XclExpTabInfo& rTabInfo = GetTabInfo();
294     maData.mbSelected       = rTabInfo.IsSelectedTab( nScTab );
295     maData.mbDisplayed      = rTabInfo.IsDisplayedTab( nScTab );
296     maData.mbMirrored       = rTabInfo.IsMirroredTab( nScTab );
297 
298     const ScViewOptions& rViewOpt = GetDoc().GetViewOptions();
299     maData.mbShowFormulas   = rViewOpt.GetOption( VOPT_FORMULAS );
300     maData.mbShowHeadings   = rViewOpt.GetOption( VOPT_HEADER );
301     maData.mbShowZeros      = rViewOpt.GetOption( VOPT_NULLVALS );
302     maData.mbShowOutline    = rViewOpt.GetOption( VOPT_OUTLINER );
303 
304     // *** sheet options: cursor, selection, splits, grid color, zoom ***
305 
306     if( const ScExtTabSettings* pTabSett = GetExtDocOptions().GetTabSettings( nScTab ) )
307     {
308         mbHasTabSettings = true;
309         const ScExtTabSettings& rTabSett = *pTabSett;
310         XclExpAddressConverter& rAddrConv = GetAddressConverter();
311 
312         // first visible cell in top-left pane
313         if( (rTabSett.maFirstVis.Col() >= 0) && (rTabSett.maFirstVis.Row() >= 0) )
314             maData.maFirstXclPos = rAddrConv.CreateValidAddress( rTabSett.maFirstVis, false );
315 
316         // first visible cell in additional pane(s)
317         if( (rTabSett.maSecondVis.Col() >= 0) && (rTabSett.maSecondVis.Row() >= 0) )
318             maData.maSecondXclPos = rAddrConv.CreateValidAddress( rTabSett.maSecondVis, false );
319 
320         // active pane
321         switch( rTabSett.meActivePane )
322         {
323             case SCEXT_PANE_TOPLEFT:        maData.mnActivePane = EXC_PANE_TOPLEFT;     break;
324             case SCEXT_PANE_TOPRIGHT:       maData.mnActivePane = EXC_PANE_TOPRIGHT;    break;
325             case SCEXT_PANE_BOTTOMLEFT:     maData.mnActivePane = EXC_PANE_BOTTOMLEFT;  break;
326             case SCEXT_PANE_BOTTOMRIGHT:    maData.mnActivePane = EXC_PANE_BOTTOMRIGHT; break;
327         }
328 
329         // freeze/split position
330         maData.mbFrozenPanes = rTabSett.mbFrozenPanes;
331         if( maData.mbFrozenPanes )
332         {
333             /*  Frozen panes: handle split position as row/column positions.
334                 #i35812# Excel uses number of visible rows/columns, Calc uses position of freeze. */
335             SCCOL nFreezeScCol = rTabSett.maFreezePos.Col();
336             if( (0 < nFreezeScCol) && (nFreezeScCol <= GetXclMaxPos().Col()) )
337                 maData.mnSplitX = static_cast< sal_uInt16 >( nFreezeScCol ) - maData.maFirstXclPos.mnCol;
338             SCROW nFreezeScRow = rTabSett.maFreezePos.Row();
339             if( (0 < nFreezeScRow) && (nFreezeScRow <= GetXclMaxPos().Row()) )
340                 maData.mnSplitY = static_cast< sal_uInt32 >( nFreezeScRow ) - maData.maFirstXclPos.mnRow;
341             // if both splits are left out (address overflow), remove the frozen flag
342             maData.mbFrozenPanes = maData.IsSplit();
343 
344             // #i20671# frozen panes: mostright/mostbottom pane is active regardless of cursor position
345             if( maData.HasPane( EXC_PANE_BOTTOMRIGHT ) )
346                 maData.mnActivePane = EXC_PANE_BOTTOMRIGHT;
347             else if( maData.HasPane( EXC_PANE_TOPRIGHT ) )
348                 maData.mnActivePane = EXC_PANE_TOPRIGHT;
349             else if( maData.HasPane( EXC_PANE_BOTTOMLEFT ) )
350                 maData.mnActivePane = EXC_PANE_BOTTOMLEFT;
351         }
352         else
353         {
354             // split window: position is in twips
355             maData.mnSplitX = static_cast<sal_uInt16>(rTabSett.maSplitPos.X());
356             maData.mnSplitY = static_cast<sal_uInt32>(rTabSett.maSplitPos.Y());
357         }
358 
359         // selection
360         CreateSelectionData( EXC_PANE_TOPLEFT,     rTabSett.maCursor, rTabSett.maSelection );
361         CreateSelectionData( EXC_PANE_TOPRIGHT,    rTabSett.maCursor, rTabSett.maSelection );
362         CreateSelectionData( EXC_PANE_BOTTOMLEFT,  rTabSett.maCursor, rTabSett.maSelection );
363         CreateSelectionData( EXC_PANE_BOTTOMRIGHT, rTabSett.maCursor, rTabSett.maSelection );
364 
365         // grid color
366         const Color& rGridColor = rTabSett.maGridColor;
367         maData.mbDefGridColor = rGridColor == COL_AUTO;
368         if( !maData.mbDefGridColor )
369         {
370             if( GetBiff() == EXC_BIFF8 )
371                 mnGridColorId = GetPalette().InsertColor( rGridColor, EXC_COLOR_GRID );
372             else
373                 maData.maGridColor = rGridColor;
374         }
375         maData.mbShowGrid       = rTabSett.mbShowGrid;
376 
377         // view mode and zoom
378         maData.mbPageMode       = (GetBiff() == EXC_BIFF8) && rTabSett.mbPageMode;
379         maData.mnNormalZoom     = lclGetXclZoom( rTabSett.mnNormalZoom, EXC_WIN2_NORMALZOOM_DEF );
380         maData.mnPageZoom       = lclGetXclZoom( rTabSett.mnPageZoom, EXC_WIN2_PAGEZOOM_DEF );
381         maData.mnCurrentZoom    = maData.mbPageMode ? maData.mnPageZoom : maData.mnNormalZoom;
382     }
383 
384     // Tab Bg Color
385     if ( GetBiff() == EXC_BIFF8 && !GetDoc().IsDefaultTabBgColor(nScTab) )
386     {
387         XclExpPalette& rPal = GetPalette();
388         maData.maTabBgColor = GetDoc().GetTabBgColor(nScTab);
389         maData.mnTabBgColorId = rPal.InsertColor(maData.maTabBgColor, EXC_COLOR_TABBG, EXC_COLOR_NOTABBG );
390     }
391 }
392 
Save(XclExpStream & rStrm)393 void XclExpTabViewSettings::Save( XclExpStream& rStrm )
394 {
395     WriteWindow2( rStrm );
396     WriteScl( rStrm );
397     WritePane( rStrm );
398     WriteSelection( rStrm, EXC_PANE_TOPLEFT );
399     WriteSelection( rStrm, EXC_PANE_TOPRIGHT );
400     WriteSelection( rStrm, EXC_PANE_BOTTOMLEFT );
401     WriteSelection( rStrm, EXC_PANE_BOTTOMRIGHT );
402     WriteTabBgColor( rStrm );
403 }
404 
lcl_WriteSelection(XclExpXmlStream & rStrm,const XclTabViewData & rData,sal_uInt8 nPane)405 static void lcl_WriteSelection( XclExpXmlStream& rStrm, const XclTabViewData& rData, sal_uInt8 nPane )
406 {
407     if( rData.HasPane( nPane ) )
408         XclExpSelection( rData, nPane ).SaveXml( rStrm );
409 }
410 
lcl_GetZoom(sal_uInt16 nZoom)411 static OString lcl_GetZoom( sal_uInt16 nZoom )
412 {
413     if( nZoom )
414         return OString::number( nZoom );
415     return "100";
416 }
417 
SaveXml(XclExpXmlStream & rStrm)418 void XclExpTabViewSettings::SaveXml( XclExpXmlStream& rStrm )
419 {
420     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
421     rWorksheet->startElement(XML_sheetViews);
422 
423     // handle missing viewdata at embedded XLSX OLE objects
424     if( !mbHasTabSettings && maData.mbSelected )
425     {
426         SCCOL nPosLeft = rStrm.GetRoot().GetDoc().GetPosLeft();
427         SCROW nPosTop = rStrm.GetRoot().GetDoc().GetPosTop();
428         if (nPosLeft > 0 || nPosTop > 0)
429         {
430             ScAddress aLeftTop(nPosLeft, nPosTop, 0);
431             XclExpAddressConverter& rAddrConv = GetAddressConverter();
432             maData.maFirstXclPos = rAddrConv.CreateValidAddress( aLeftTop, false );
433         }
434     }
435 
436     rWorksheet->startElement( XML_sheetView,
437             // OOXTODO: XML_windowProtection,
438             XML_showFormulas,               ToPsz( maData.mbShowFormulas ),
439             XML_showGridLines,              ToPsz( maData.mbShowGrid ),
440             XML_showRowColHeaders,          ToPsz( maData.mbShowHeadings ),
441             XML_showZeros,                  ToPsz( maData.mbShowZeros ),
442             XML_rightToLeft,                ToPsz( maData.mbMirrored ),
443             XML_tabSelected,                ToPsz( maData.mbSelected ),
444             // OOXTODO: XML_showRuler,
445             XML_showOutlineSymbols,         ToPsz( maData.mbShowOutline ),
446             XML_defaultGridColor,           mnGridColorId == XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT ) ? "true" : "false",
447             // OOXTODO: XML_showWhiteSpace,
448             XML_view,                       maData.mbPageMode ? "pageBreakPreview" : "normal",  // OOXTODO: pageLayout
449             XML_topLeftCell,                XclXmlUtils::ToOString( rStrm.GetRoot().GetStringBuf(), maData.maFirstXclPos ).getStr(),
450             XML_colorId,                    OString::number(rStrm.GetRoot().GetPalette().GetColorIndex(mnGridColorId)),
451             XML_zoomScale,                  lcl_GetZoom(maData.mnCurrentZoom),
452             XML_zoomScaleNormal,            lcl_GetZoom(maData.mnNormalZoom),
453             // OOXTODO: XML_zoomScaleSheetLayoutView,
454             XML_zoomScalePageLayoutView,    lcl_GetZoom(maData.mnPageZoom),
455             XML_workbookViewId,             "0"     // OOXTODO? 0-based index of document(xl/workbook.xml)/workbook/bookviews/workbookView
456                                                     //          should always be 0, as we only generate 1 such element.
457     );
458     if( maData.IsSplit() )
459     {
460         XclExpPane aPane( maData );
461         aPane.SaveXml( rStrm );
462     }
463     lcl_WriteSelection( rStrm, maData, EXC_PANE_TOPLEFT );
464     lcl_WriteSelection( rStrm, maData, EXC_PANE_TOPRIGHT );
465     lcl_WriteSelection( rStrm, maData, EXC_PANE_BOTTOMLEFT );
466     lcl_WriteSelection( rStrm, maData, EXC_PANE_BOTTOMRIGHT );
467     rWorksheet->endElement( XML_sheetView );
468     // OOXTODO: XML_extLst
469     rWorksheet->endElement( XML_sheetViews );
470 }
471 
472 // private --------------------------------------------------------------------
473 
CreateSelectionData(sal_uInt8 nPane,const ScAddress & rCursor,const ScRangeList & rSelection)474 void XclExpTabViewSettings::CreateSelectionData( sal_uInt8 nPane,
475         const ScAddress& rCursor, const ScRangeList& rSelection )
476 {
477     if( maData.HasPane( nPane ) )
478     {
479         XclSelectionData& rSelData = maData.CreateSelectionData( nPane );
480 
481         // first step: use top-left visible cell as cursor
482         rSelData.maXclCursor.mnCol = ((nPane == EXC_PANE_TOPLEFT) || (nPane == EXC_PANE_BOTTOMLEFT)) ?
483             maData.maFirstXclPos.mnCol : maData.maSecondXclPos.mnCol;
484         rSelData.maXclCursor.mnRow = ((nPane == EXC_PANE_TOPLEFT) || (nPane == EXC_PANE_TOPRIGHT)) ?
485             maData.maFirstXclPos.mnRow : maData.maSecondXclPos.mnRow;
486 
487         // second step, active pane: create actual selection data with current cursor position
488         if( nPane == maData.mnActivePane )
489         {
490             XclExpAddressConverter& rAddrConv = GetAddressConverter();
491             // cursor position (keep top-left pane position from above, if rCursor is invalid)
492             if( (rCursor.Col() >= 0) && (rCursor.Row() >= 0) )
493                 rSelData.maXclCursor = rAddrConv.CreateValidAddress( rCursor, false );
494             // selection
495             rAddrConv.ConvertRangeList( rSelData.maXclSelection, rSelection, false );
496         }
497     }
498 }
499 
WriteWindow2(XclExpStream & rStrm) const500 void XclExpTabViewSettings::WriteWindow2( XclExpStream& rStrm ) const
501 {
502 //  #i43553# GCC 3.3 parse error
503 //    XclExpWindow2( GetRoot(), maData, mnGridColorId ).Save( rStrm );
504     XclExpWindow2 aWindow2( GetRoot(), maData, mnGridColorId );
505     aWindow2.Save( rStrm );
506 }
507 
WriteScl(XclExpStream & rStrm) const508 void XclExpTabViewSettings::WriteScl( XclExpStream& rStrm ) const
509 {
510     if( maData.mnCurrentZoom != 0 )
511         XclExpScl( maData.mnCurrentZoom ).Save( rStrm );
512 }
513 
WritePane(XclExpStream & rStrm) const514 void XclExpTabViewSettings::WritePane( XclExpStream& rStrm ) const
515 {
516     if( maData.IsSplit() )
517 //  #i43553# GCC 3.3 parse error
518 //        XclExpPane( GetRoot(), maData ).Save( rStrm );
519     {
520         XclExpPane aPane( maData );
521         aPane.Save( rStrm );
522     }
523 }
524 
WriteSelection(XclExpStream & rStrm,sal_uInt8 nPane) const525 void XclExpTabViewSettings::WriteSelection( XclExpStream& rStrm, sal_uInt8 nPane ) const
526 {
527     if( maData.HasPane( nPane ) )
528         XclExpSelection( maData, nPane ).Save( rStrm );
529 }
530 
WriteTabBgColor(XclExpStream & rStrm) const531 void XclExpTabViewSettings::WriteTabBgColor( XclExpStream& rStrm ) const
532 {
533     if ( !maData.IsDefaultTabBgColor() )
534         XclExpTabBgColor( maData ).Save( rStrm );
535 }
536 
537 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
538