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 75 : 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 75 : mbDirty( true )
58 : {
59 75 : }
60 :
61 150 : XclImpColRowSettings::~XclImpColRowSettings()
62 : {
63 150 : }
64 :
65 74 : void XclImpColRowSettings::SetDefWidth( sal_uInt16 nDefWidth, bool bStdWidthRec )
66 : {
67 74 : if( bStdWidthRec )
68 : {
69 : // STANDARDWIDTH record overrides DEFCOLWIDTH record
70 1 : mnDefWidth = nDefWidth;
71 1 : mbHasStdWidthRec = true;
72 : }
73 73 : else if( !mbHasStdWidthRec )
74 : {
75 : // use DEFCOLWIDTH record only, if no STANDARDWIDTH record exists
76 73 : mnDefWidth = nDefWidth;
77 : }
78 74 : }
79 :
80 278 : void XclImpColRowSettings::SetWidthRange( SCCOL nCol1, SCCOL nCol2, sal_uInt16 nWidth )
81 : {
82 278 : nCol2 = ::std::min( nCol2, MAXCOL );
83 278 : 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 39 : nCol2 = MAXCOL;
88 :
89 278 : nCol1 = ::std::min( nCol1, nCol2 );
90 278 : 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 40326 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
94 40048 : ApplyColFlag(nCol, EXC_COLROW_USED);
95 278 : }
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 1 : void XclImpColRowSettings::HideColRange( SCCOL nCol1, SCCOL nCol2 )
106 : {
107 1 : nCol2 = ::std::min( nCol2, MAXCOL );
108 1 : nCol1 = ::std::min( nCol1, nCol2 );
109 :
110 2 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
111 1 : ApplyColFlag(nCol, EXC_COLROW_HIDDEN);
112 1 : }
113 :
114 74 : void XclImpColRowSettings::SetDefHeight( sal_uInt16 nDefHeight, sal_uInt16 nFlags )
115 : {
116 74 : mnDefHeight = nDefHeight;
117 74 : mnDefRowFlags = nFlags;
118 74 : if( mnDefHeight == 0 )
119 : {
120 0 : mnDefHeight = static_cast< sal_uInt16 >( STD_ROW_HEIGHT );
121 0 : ::set_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN );
122 : }
123 74 : mbHasDefHeight = true;
124 74 : }
125 :
126 4596 : void XclImpColRowSettings::SetHeight( SCROW nScRow, sal_uInt16 nHeight )
127 : {
128 4596 : if (!ValidRow(nScRow))
129 : return;
130 :
131 4596 : sal_uInt16 nRawHeight = nHeight & EXC_ROW_HEIGHTMASK;
132 4596 : bool bDefHeight = ::get_flag( nHeight, EXC_ROW_FLAGDEFHEIGHT ) || (nRawHeight == 0);
133 4596 : maRowHeights.insert_back(nScRow, nScRow+1, nRawHeight);
134 4596 : sal_uInt8 nFlagVal = 0;
135 4596 : if (!maRowFlags.search(nScRow, nFlagVal).second)
136 : return;
137 :
138 4596 : ::set_flag(nFlagVal, EXC_COLROW_USED);
139 4596 : ::set_flag(nFlagVal, EXC_COLROW_DEFAULT, bDefHeight);
140 :
141 4596 : if (!bDefHeight && nRawHeight == 0)
142 0 : maHiddenRows.insert_back(nScRow, nScRow+1, true);
143 :
144 4596 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
145 :
146 4596 : if (nScRow > mnLastScRow)
147 4596 : mnLastScRow = nScRow;
148 : }
149 :
150 4596 : void XclImpColRowSettings::SetRowSettings( SCROW nScRow, sal_uInt16 nHeight, sal_uInt16 nFlags )
151 : {
152 4596 : if (!ValidRow(nScRow))
153 : return;
154 :
155 4596 : SetHeight(nScRow, nHeight);
156 :
157 4596 : sal_uInt8 nFlagVal = 0;
158 4596 : if (!maRowFlags.search(nScRow, nFlagVal).second)
159 : return;
160 :
161 4596 : if (::get_flag(nFlags, EXC_ROW_UNSYNCED))
162 725 : ::set_flag(nFlagVal, EXC_COLROW_MAN);
163 :
164 4596 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
165 :
166 4596 : if (::get_flag(nFlags, EXC_ROW_HIDDEN))
167 167 : maHiddenRows.insert_back(nScRow, nScRow+1, true);
168 : }
169 :
170 5 : void XclImpColRowSettings::SetManualRowHeight( SCROW nScRow )
171 : {
172 5 : if (!ValidRow(nScRow))
173 : return;
174 :
175 5 : sal_uInt8 nFlagVal = 0;
176 5 : if (!maRowFlags.search(nScRow, nFlagVal).second)
177 : return;
178 :
179 5 : ::set_flag(nFlagVal, EXC_COLROW_MAN);
180 5 : maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
181 : }
182 :
183 278 : 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 278 : nCol2 = ::std::min( nCol2, MAXCOL );
189 278 : nCol1 = ::std::min( nCol1, nCol2 );
190 278 : XclImpXFRangeBuffer& rXFRangeBuffer = GetXFRangeBuffer();
191 10413 : for( SCCOL nCol = nCol1; nCol <= nCol2; ++nCol )
192 10135 : rXFRangeBuffer.SetColumnDefXF( nCol, nXFIndex );
193 278 : }
194 :
195 75 : void XclImpColRowSettings::Convert( SCTAB nScTab )
196 : {
197 75 : if( !mbDirty )
198 : return;
199 :
200 75 : ScDocument& rDoc = GetDoc();
201 :
202 : // column widths ----------------------------------------------------------
203 :
204 75 : maColWidths.build_tree();
205 76875 : for( SCCOL nCol = 0; nCol <= MAXCOL; ++nCol )
206 : {
207 76800 : sal_uInt16 nWidth = mnDefWidth;
208 76800 : if (GetColFlag(nCol, EXC_COLROW_USED))
209 : {
210 : sal_uInt16 nTmp;
211 40048 : if (maColWidths.search_tree(nCol, nTmp))
212 40048 : 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 76800 : if( nWidth == 0 )
219 : {
220 0 : ApplyColFlag(nCol, EXC_COLROW_HIDDEN);
221 0 : nWidth = mnDefWidth;
222 : }
223 76800 : rDoc.SetColWidthOnly( nCol, nScTab, nWidth );
224 : }
225 :
226 : // row heights ------------------------------------------------------------
227 :
228 : // #i54252# set default row height
229 75 : rDoc.SetRowHeightOnly( 0, MAXROW, nScTab, mnDefHeight );
230 75 : if( ::get_flag( mnDefRowFlags, EXC_DEFROW_UNSYNCED ) )
231 : // first access to row flags, do not ask for old flags
232 8 : rDoc.SetRowFlags( 0, MAXROW, nScTab, CR_MANUALSIZE );
233 :
234 75 : maRowHeights.build_tree();
235 75 : if (!maRowHeights.is_tree_valid())
236 : return;
237 :
238 75 : ColRowFlagsType::const_iterator itrFlags = maRowFlags.begin(), itrFlagsEnd = maRowFlags.end();
239 75 : SCROW nPrevRow = -1;
240 75 : sal_uInt8 nPrevFlags = 0;
241 286 : for (; itrFlags != itrFlagsEnd; ++itrFlags)
242 : {
243 211 : SCROW nRow = itrFlags->first;
244 211 : sal_uInt8 nFlags = itrFlags->second;
245 211 : if (nPrevRow >= 0)
246 : {
247 136 : sal_uInt16 nHeight = 0;
248 :
249 136 : if (::get_flag(nPrevFlags, EXC_COLROW_USED))
250 : {
251 100 : 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 754 : for (SCROW i = nPrevRow; i <= nRow - 1; ++i)
259 : {
260 : SCROW nLast;
261 654 : if (!maRowHeights.search_tree(i, nHeight, NULL, &nLast))
262 : {
263 : // search failed for some reason
264 : return;
265 : }
266 :
267 654 : if (nLast > nRow)
268 2 : nLast = nRow;
269 :
270 654 : rDoc.SetRowHeightOnly(i, nLast-1, nScTab, nHeight);
271 654 : i = nLast-1;
272 : }
273 : }
274 :
275 100 : if (::get_flag(nPrevFlags, EXC_COLROW_MAN))
276 25 : rDoc.SetManualHeight(nPrevRow, nRow-1, nScTab, true);
277 : }
278 : else
279 : {
280 36 : nHeight = mnDefHeight;
281 36 : rDoc.SetRowHeightOnly(nPrevRow, nRow-1, nScTab, nHeight);
282 : }
283 : }
284 :
285 211 : nPrevRow = nRow;
286 211 : nPrevFlags = nFlags;
287 : }
288 :
289 : // ------------------------------------------------------------------------
290 :
291 75 : mbDirty = false;
292 : }
293 :
294 75 : void XclImpColRowSettings::ConvertHiddenFlags( SCTAB nScTab )
295 : {
296 75 : ScDocument& rDoc = GetDoc();
297 :
298 : // hide the columns
299 76875 : for( SCCOL nCol = 0; nCol <= MAXCOL; ++nCol )
300 76800 : if (GetColFlag(nCol, EXC_COLROW_HIDDEN))
301 1 : rDoc.ShowCol( nCol, nScTab, false );
302 :
303 : // #i38093# rows hidden by filter need extra flag
304 75 : SCROW nFirstFilterScRow = SCROW_MAX;
305 75 : SCROW nLastFilterScRow = SCROW_MAX;
306 75 : if( GetBiff() == EXC_BIFF8 )
307 : {
308 75 : const XclImpAutoFilterData* pFilter = GetFilterManager().GetByTab( nScTab );
309 : // #i70026# use IsFiltered() to set the CR_FILTERED flag for active filters only
310 75 : if( pFilter && pFilter->IsActive() && pFilter->IsFiltered() )
311 : {
312 5 : nFirstFilterScRow = pFilter->StartRow();
313 5 : 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 75 : SCROW nLastXLRow = GetRoot().GetXclMaxPos().Row();
320 75 : if (nLastXLRow < MAXROW)
321 : {
322 75 : bool bHidden = false;
323 75 : if (!maHiddenRows.search(nLastXLRow, bHidden).second)
324 75 : return;
325 :
326 75 : maHiddenRows.insert_back(nLastXLRow, MAXROWCOUNT, bHidden);
327 : }
328 :
329 75 : SCROW nPrevRow = -1;
330 75 : bool bPrevHidden = false;
331 75 : RowHiddenType::const_iterator itr = maHiddenRows.begin(), itrEnd = maHiddenRows.end();
332 202 : for (; itr != itrEnd; ++itr)
333 : {
334 127 : SCROW nRow = itr->first;
335 127 : bool bHidden = itr->second;
336 127 : if (nPrevRow >= 0)
337 : {
338 52 : if (bPrevHidden)
339 : {
340 26 : rDoc.SetRowHidden(nPrevRow, nRow-1, nScTab, true);
341 : // #i38093# rows hidden by filter need extra flag
342 26 : if (nFirstFilterScRow <= nPrevRow && nPrevRow <= nLastFilterScRow)
343 : {
344 25 : SCROW nLast = ::std::min(nRow-1, nLastFilterScRow);
345 25 : rDoc.SetRowFiltered(nPrevRow, nLast, nScTab, true);
346 : }
347 : }
348 : }
349 :
350 127 : nPrevRow = nRow;
351 127 : bPrevHidden = bHidden;
352 : }
353 :
354 : // #i47438# if default row format is hidden, hide remaining rows
355 75 : if( ::get_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN ) && (mnLastScRow < MAXROW) )
356 0 : rDoc.ShowRows( mnLastScRow + 1, MAXROW, nScTab, false );
357 : }
358 :
359 40049 : void XclImpColRowSettings::ApplyColFlag(SCCOL nCol, sal_uInt8 nNewVal)
360 : {
361 : // Get the original flag value.
362 40049 : sal_uInt8 nFlagVal = 0;
363 40049 : std::pair<ColRowFlagsType::const_iterator,bool> r = maColFlags.search(nCol, nFlagVal);
364 40049 : if (!r.second)
365 : // Search failed.
366 40049 : return;
367 :
368 40049 : ::set_flag(nFlagVal, nNewVal);
369 :
370 : // Re-insert the flag value.
371 40049 : maColFlags.insert(r.first, nCol, nCol+1, nFlagVal);
372 : }
373 :
374 153600 : bool XclImpColRowSettings::GetColFlag(SCCOL nCol, sal_uInt8 nMask) const
375 : {
376 153600 : sal_uInt8 nFlagVal = 0;
377 153600 : if (!maColFlags.search(nCol, nFlagVal).second)
378 0 : return false;
379 : // Search failed.
380 :
381 153600 : return ::get_flag(nFlagVal, nMask);
382 9 : }
383 :
384 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|