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