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