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