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