Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "colrowst.hxx"
21 :
22 : #include <string.h>
23 :
24 : #include "document.hxx"
25 : #include "root.hxx"
26 : #include "ftools.hxx"
27 : #include "xltable.hxx"
28 : #include "xistream.hxx"
29 : #include "xistyle.hxx"
30 : #include "queryparam.hxx"
31 :
32 : // for filter manager
33 : #include "excimp8.hxx"
34 :
35 : const sal_uInt8 EXC_COLROW_USED = 0x01;
36 : const sal_uInt8 EXC_COLROW_DEFAULT = 0x02;
37 : const sal_uInt8 EXC_COLROW_HIDDEN = 0x04;
38 : const sal_uInt8 EXC_COLROW_MAN = 0x08;
39 :
40 0 : XclImpColRowSettings::XclImpColRowSettings( const XclImpRoot& rRoot ) :
41 : XclImpRoot( rRoot ),
42 : maColWidths(0, MAXCOLCOUNT, 0),
43 : maColFlags(0, MAXCOLCOUNT, 0),
44 : maRowHeights(0, MAXROWCOUNT, 0),
45 : maRowFlags(0, MAXROWCOUNT, 0),
46 : maHiddenRows(0, MAXROWCOUNT, false),
47 : mnLastScRow( -1 ),
48 : mnDefWidth( STD_COL_WIDTH ),
49 : mnDefHeight( static_cast< sal_uInt16 >( ScGlobal::nStdRowHeight ) ),
50 : mnDefRowFlags( EXC_DEFROW_DEFAULTFLAGS ),
51 : mbHasStdWidthRec( false ),
52 : mbHasDefHeight( false ),
53 0 : mbDirty( true )
54 : {
55 0 : }
56 :
57 0 : XclImpColRowSettings::~XclImpColRowSettings()
58 : {
59 0 : }
60 :
61 0 : void XclImpColRowSettings::SetDefWidth( sal_uInt16 nDefWidth, bool bStdWidthRec )
62 : {
63 0 : if( bStdWidthRec )
64 : {
65 : // STANDARDWIDTH record overrides DEFCOLWIDTH record
66 0 : mnDefWidth = nDefWidth;
67 0 : mbHasStdWidthRec = true;
68 : }
69 0 : else if( !mbHasStdWidthRec )
70 : {
71 : // use DEFCOLWIDTH record only, if no STANDARDWIDTH record exists
72 0 : mnDefWidth = nDefWidth;
73 : }
74 0 : }
75 :
76 0 : void XclImpColRowSettings::SetWidthRange( SCCOL nCol1, SCCOL nCol2, sal_uInt16 nWidth )
77 : {
78 0 : nCol2 = ::std::min( nCol2, MAXCOL );
79 0 : if (nCol2 == 256)
80 : // In BIFF8, the column range is 0-255, and the use of 256 probably
81 : // means the range should extend to the max column if the loading app
82 : // support columns beyond 255.
83 0 : nCol2 = MAXCOL;
84 :
85 0 : nCol1 = ::std::min( nCol1, nCol2 );
86 0 : maColWidths.insert_back(nCol1, nCol2+1, nWidth);
87 :
88 : // We need to apply flag values individually since all flag values are aggregated for each column.
89 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
90 0 : ApplyColFlag(nCol, EXC_COLROW_USED);
91 0 : }
92 :
93 0 : void XclImpColRowSettings::HideCol( SCCOL nCol )
94 : {
95 0 : if (!ValidCol(nCol))
96 0 : return;
97 :
98 0 : ApplyColFlag(nCol, EXC_COLROW_HIDDEN);
99 : }
100 :
101 0 : void XclImpColRowSettings::HideColRange( SCCOL nCol1, SCCOL nCol2 )
102 : {
103 0 : nCol2 = ::std::min( nCol2, MAXCOL );
104 0 : nCol1 = ::std::min( nCol1, nCol2 );
105 :
106 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
107 0 : ApplyColFlag(nCol, EXC_COLROW_HIDDEN);
108 0 : }
109 :
110 0 : void XclImpColRowSettings::SetDefHeight( sal_uInt16 nDefHeight, sal_uInt16 nFlags )
111 : {
112 0 : mnDefHeight = nDefHeight;
113 0 : mnDefRowFlags = nFlags;
114 0 : if( mnDefHeight == 0 )
115 : {
116 0 : mnDefHeight = static_cast< sal_uInt16 >( ScGlobal::nStdRowHeight );
117 0 : ::set_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN );
118 : }
119 0 : mbHasDefHeight = true;
120 0 : }
121 :
122 0 : void XclImpColRowSettings::SetHeight( SCROW nScRow, sal_uInt16 nHeight )
123 : {
124 0 : if (!ValidRow(nScRow))
125 0 : return;
126 :
127 0 : sal_uInt16 nRawHeight = nHeight & EXC_ROW_HEIGHTMASK;
128 0 : bool bDefHeight = ::get_flag( nHeight, EXC_ROW_FLAGDEFHEIGHT ) || (nRawHeight == 0);
129 0 : maRowHeights.insert_back(nScRow, nScRow+1, nRawHeight);
130 0 : sal_uInt8 nFlagVal = 0;
131 0 : if (!maRowFlags.search(nScRow, nFlagVal).second)
132 0 : return;
133 :
134 0 : ::set_flag(nFlagVal, EXC_COLROW_USED);
135 0 : ::set_flag(nFlagVal, EXC_COLROW_DEFAULT, bDefHeight);
136 :
137 0 : if (!bDefHeight && nRawHeight == 0)
138 0 : maHiddenRows.insert_back(nScRow, nScRow+1, true);
139 :
140 0 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
141 :
142 0 : if (nScRow > mnLastScRow)
143 0 : mnLastScRow = nScRow;
144 : }
145 :
146 0 : void XclImpColRowSettings::SetRowSettings( SCROW nScRow, sal_uInt16 nHeight, sal_uInt16 nFlags )
147 : {
148 0 : if (!ValidRow(nScRow))
149 0 : return;
150 :
151 0 : SetHeight(nScRow, nHeight);
152 :
153 0 : sal_uInt8 nFlagVal = 0;
154 0 : if (!maRowFlags.search(nScRow, nFlagVal).second)
155 0 : return;
156 :
157 0 : if (::get_flag(nFlags, EXC_ROW_UNSYNCED))
158 0 : ::set_flag(nFlagVal, EXC_COLROW_MAN);
159 :
160 0 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
161 :
162 0 : if (::get_flag(nFlags, EXC_ROW_HIDDEN))
163 0 : maHiddenRows.insert_back(nScRow, nScRow+1, true);
164 : }
165 :
166 0 : void XclImpColRowSettings::SetManualRowHeight( SCROW nScRow )
167 : {
168 0 : if (!ValidRow(nScRow))
169 0 : return;
170 :
171 0 : sal_uInt8 nFlagVal = 0;
172 0 : if (!maRowFlags.search(nScRow, nFlagVal).second)
173 0 : return;
174 :
175 0 : ::set_flag(nFlagVal, EXC_COLROW_MAN);
176 0 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
177 : }
178 :
179 0 : void XclImpColRowSettings::SetDefaultXF( SCCOL nCol1, SCCOL nCol2, sal_uInt16 nXFIndex )
180 : {
181 : /* assign the default column formatting here to ensure that
182 : explicit cell formatting is not overwritten. */
183 : OSL_ENSURE( (nCol1 <= nCol2) && ValidCol( nCol2 ), "XclImpColRowSettings::SetDefaultXF - invalid column index" );
184 0 : nCol2 = ::std::min( nCol2, MAXCOL );
185 0 : nCol1 = ::std::min( nCol1, nCol2 );
186 0 : XclImpXFRangeBuffer& rXFRangeBuffer = GetXFRangeBuffer();
187 0 : for( SCCOL nCol = nCol1; nCol <= nCol2; ++nCol )
188 0 : rXFRangeBuffer.SetColumnDefXF( nCol, nXFIndex );
189 0 : }
190 :
191 0 : void XclImpColRowSettings::Convert( SCTAB nScTab )
192 : {
193 0 : if( !mbDirty )
194 0 : return;
195 :
196 0 : ScDocument& rDoc = GetDoc();
197 :
198 : // column widths ----------------------------------------------------------
199 :
200 0 : maColWidths.build_tree();
201 0 : for( SCCOL nCol = 0; nCol <= MAXCOL; ++nCol )
202 : {
203 0 : sal_uInt16 nWidth = mnDefWidth;
204 0 : if (GetColFlag(nCol, EXC_COLROW_USED))
205 : {
206 : sal_uInt16 nTmp;
207 0 : if (maColWidths.search_tree(nCol, nTmp).second)
208 0 : nWidth = nTmp;
209 : }
210 :
211 : /* Hidden columns: remember hidden state, but do not set hidden state
212 : in document here. Needed for #i11776#, no HIDDEN flags in the
213 : document, until filters and outlines are inserted. */
214 0 : if( nWidth == 0 )
215 : {
216 0 : ApplyColFlag(nCol, EXC_COLROW_HIDDEN);
217 0 : nWidth = mnDefWidth;
218 : }
219 0 : rDoc.SetColWidthOnly( nCol, nScTab, nWidth );
220 : }
221 :
222 : // row heights ------------------------------------------------------------
223 :
224 : // #i54252# set default row height
225 0 : rDoc.SetRowHeightOnly( 0, MAXROW, nScTab, mnDefHeight );
226 0 : if( ::get_flag( mnDefRowFlags, EXC_DEFROW_UNSYNCED ) )
227 : // first access to row flags, do not ask for old flags
228 0 : rDoc.SetRowFlags( 0, MAXROW, nScTab, CR_MANUALSIZE );
229 :
230 0 : maRowHeights.build_tree();
231 0 : if (!maRowHeights.is_tree_valid())
232 0 : return;
233 :
234 0 : ColRowFlagsType::const_iterator itrFlags = maRowFlags.begin(), itrFlagsEnd = maRowFlags.end();
235 0 : SCROW nPrevRow = -1;
236 0 : sal_uInt8 nPrevFlags = 0;
237 0 : for (; itrFlags != itrFlagsEnd; ++itrFlags)
238 : {
239 0 : SCROW nRow = itrFlags->first;
240 0 : sal_uInt8 nFlags = itrFlags->second;
241 0 : if (nPrevRow >= 0)
242 : {
243 0 : sal_uInt16 nHeight = 0;
244 :
245 0 : if (::get_flag(nPrevFlags, EXC_COLROW_USED))
246 : {
247 0 : if (::get_flag(nPrevFlags, EXC_COLROW_DEFAULT))
248 : {
249 0 : nHeight = mnDefHeight;
250 0 : rDoc.SetRowHeightOnly(nPrevRow, nRow-1, nScTab, nHeight);
251 : }
252 : else
253 : {
254 0 : for (SCROW i = nPrevRow; i <= nRow - 1; ++i)
255 : {
256 : SCROW nLast;
257 0 : if (!maRowHeights.search_tree(i, nHeight, NULL, &nLast).second)
258 : {
259 : // search failed for some reason
260 0 : return;
261 : }
262 :
263 0 : if (nLast > nRow)
264 0 : nLast = nRow;
265 :
266 0 : rDoc.SetRowHeightOnly(i, nLast-1, nScTab, nHeight);
267 0 : i = nLast-1;
268 : }
269 : }
270 :
271 0 : if (::get_flag(nPrevFlags, EXC_COLROW_MAN))
272 0 : rDoc.SetManualHeight(nPrevRow, nRow-1, nScTab, true);
273 : }
274 : else
275 : {
276 0 : nHeight = mnDefHeight;
277 0 : rDoc.SetRowHeightOnly(nPrevRow, nRow-1, nScTab, nHeight);
278 : }
279 : }
280 :
281 0 : nPrevRow = nRow;
282 0 : nPrevFlags = nFlags;
283 : }
284 :
285 0 : mbDirty = false;
286 : }
287 :
288 0 : void XclImpColRowSettings::ConvertHiddenFlags( SCTAB nScTab )
289 : {
290 0 : ScDocument& rDoc = GetDoc();
291 :
292 : // hide the columns
293 0 : for( SCCOL nCol = 0; nCol <= MAXCOL; ++nCol )
294 0 : if (GetColFlag(nCol, EXC_COLROW_HIDDEN))
295 0 : rDoc.ShowCol( nCol, nScTab, false );
296 :
297 : // #i38093# rows hidden by filter need extra flag
298 0 : SCROW nFirstFilterScRow = SCROW_MAX;
299 0 : SCROW nLastFilterScRow = SCROW_MAX;
300 0 : if( GetBiff() == EXC_BIFF8 )
301 : {
302 0 : const XclImpAutoFilterData* pFilter = GetFilterManager().GetByTab( nScTab );
303 : // #i70026# use IsFiltered() to set the CR_FILTERED flag for active filters only
304 0 : if( pFilter && pFilter->IsActive() && pFilter->IsFiltered() )
305 : {
306 0 : nFirstFilterScRow = pFilter->StartRow();
307 0 : nLastFilterScRow = pFilter->EndRow();
308 : }
309 : }
310 :
311 : // In case the excel row limit is lower than calc's, use the visibility of
312 : // the last row and extend it to calc's last row.
313 0 : SCROW nLastXLRow = GetRoot().GetXclMaxPos().Row();
314 0 : if (nLastXLRow < MAXROW)
315 : {
316 0 : bool bHidden = false;
317 0 : if (!maHiddenRows.search(nLastXLRow, bHidden).second)
318 0 : return;
319 :
320 0 : maHiddenRows.insert_back(nLastXLRow, MAXROWCOUNT, bHidden);
321 : }
322 :
323 0 : SCROW nPrevRow = -1;
324 0 : bool bPrevHidden = false;
325 0 : RowHiddenType::const_iterator itr = maHiddenRows.begin(), itrEnd = maHiddenRows.end();
326 0 : for (; itr != itrEnd; ++itr)
327 : {
328 0 : SCROW nRow = itr->first;
329 0 : bool bHidden = itr->second;
330 0 : if (nPrevRow >= 0)
331 : {
332 0 : if (bPrevHidden)
333 : {
334 0 : rDoc.SetRowHidden(nPrevRow, nRow-1, nScTab, true);
335 : // #i38093# rows hidden by filter need extra flag
336 0 : if (nFirstFilterScRow <= nPrevRow && nPrevRow <= nLastFilterScRow)
337 : {
338 0 : SCROW nLast = ::std::min(nRow-1, nLastFilterScRow);
339 0 : rDoc.SetRowFiltered(nPrevRow, nLast, nScTab, true);
340 : }
341 : }
342 : }
343 :
344 0 : nPrevRow = nRow;
345 0 : bPrevHidden = bHidden;
346 : }
347 :
348 : // #i47438# if default row format is hidden, hide remaining rows
349 0 : if( ::get_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN ) && (mnLastScRow < MAXROW) )
350 0 : rDoc.ShowRows( mnLastScRow + 1, MAXROW, nScTab, false );
351 : }
352 :
353 0 : void XclImpColRowSettings::ApplyColFlag(SCCOL nCol, sal_uInt8 nNewVal)
354 : {
355 : // Get the original flag value.
356 0 : sal_uInt8 nFlagVal = 0;
357 0 : std::pair<ColRowFlagsType::const_iterator,bool> r = maColFlags.search(nCol, nFlagVal);
358 0 : if (!r.second)
359 : // Search failed.
360 0 : return;
361 :
362 0 : ::set_flag(nFlagVal, nNewVal);
363 :
364 : // Re-insert the flag value.
365 0 : maColFlags.insert(r.first, nCol, nCol+1, nFlagVal);
366 : }
367 :
368 0 : bool XclImpColRowSettings::GetColFlag(SCCOL nCol, sal_uInt8 nMask) const
369 : {
370 0 : sal_uInt8 nFlagVal = 0;
371 0 : if (!maColFlags.search(nCol, nFlagVal).second)
372 0 : return false;
373 : // Search failed.
374 :
375 0 : return ::get_flag(nFlagVal, nMask);
376 0 : }
377 :
378 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|