fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / oox / addressconverter.cxx
blob95319ce19566673071f9a3059cf33b936a3cadf7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "addressconverter.hxx"
22 #include <com/sun/star/container/XIndexAccess.hpp>
23 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
24 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
25 #include <osl/diagnose.h>
26 #include <rtl/strbuf.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <oox/core/filterbase.hxx>
29 #include <oox/helper/containerhelper.hxx>
30 #include "biffinputstream.hxx"
32 namespace oox {
33 namespace xls {
35 using namespace ::com::sun::star::container;
36 using namespace ::com::sun::star::sheet;
37 using namespace ::com::sun::star::table;
38 using namespace ::com::sun::star::uno;
40 namespace {
42 //! TODO: this limit may change, is there a way to obtain it via API?
43 const sal_Int16 API_MAXTAB = MAXTAB;
45 const sal_Int32 OOX_MAXCOL = static_cast< sal_Int32 >( (1 << 14) - 1 );
46 const sal_Int32 OOX_MAXROW = static_cast< sal_Int32 >( (1 << 20) - 1 );
47 const sal_Int16 OOX_MAXTAB = static_cast< sal_Int16 >( (1 << 15) - 1 );
49 const sal_Int32 BIFF2_MAXCOL = 255;
50 const sal_Int32 BIFF2_MAXROW = 16383;
51 const sal_Int16 BIFF2_MAXTAB = 0;
53 const sal_Int32 BIFF3_MAXCOL = BIFF2_MAXCOL;
54 const sal_Int32 BIFF3_MAXROW = BIFF2_MAXROW;
55 const sal_Int16 BIFF3_MAXTAB = BIFF2_MAXTAB;
57 const sal_Int32 BIFF4_MAXCOL = BIFF3_MAXCOL;
58 const sal_Int32 BIFF4_MAXROW = BIFF3_MAXROW;
59 const sal_Int16 BIFF4_MAXTAB = 32767;
61 const sal_Int32 BIFF5_MAXCOL = BIFF4_MAXCOL;
62 const sal_Int32 BIFF5_MAXROW = BIFF4_MAXROW;
63 const sal_Int16 BIFF5_MAXTAB = BIFF4_MAXTAB;
65 const sal_Int32 BIFF8_MAXCOL = BIFF5_MAXCOL;
66 const sal_Int32 BIFF8_MAXROW = 65535;
67 const sal_Int16 BIFF8_MAXTAB = BIFF5_MAXTAB;
69 } // namespace
71 CellAddress ApiCellRangeList::getBaseAddress() const
73 if( mvAddresses.empty() )
74 return CellAddress();
75 return CellAddress( mvAddresses.front().Sheet, mvAddresses.front().StartColumn, mvAddresses.front().StartRow );
78 com::sun::star::uno::Sequence< CellRangeAddress > ApiCellRangeList::toSequence() const
80 return ContainerHelper::vectorToSequence( mvAddresses );
83 void BinAddress::read( SequenceInputStream& rStrm )
85 mnRow = rStrm.readInt32();
86 mnCol = rStrm.readInt32();
89 void BinAddress::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
91 mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
92 mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
95 void BinRange::read( SequenceInputStream& rStrm )
97 maFirst.mnRow = rStrm.readInt32();
98 maLast.mnRow = rStrm.readInt32();
99 maFirst.mnCol = rStrm.readInt32();
100 maLast.mnCol = rStrm.readInt32();
103 void BinRange::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
105 maFirst.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
106 maLast.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
107 maFirst.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
108 maLast.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
111 void BinRangeList::read( SequenceInputStream& rStrm )
113 sal_Int32 nCount = rStrm.readInt32();
114 mvRanges.resize( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 16 ) );
115 for( ::std::vector< BinRange >::iterator aIt = mvRanges.begin(), aEnd = mvRanges.end(); aIt != aEnd; ++aIt )
116 aIt->read( rStrm );
119 AddressConverter::AddressConverter( const WorkbookHelper& rHelper ) :
120 WorkbookHelper( rHelper ),
121 mbColOverflow( false ),
122 mbRowOverflow( false ),
123 mbTabOverflow( false )
125 maDConChars.set( 0xFFFF, '\x01', 0xFFFF, '\x02', 0xFFFF );
126 switch( getFilterType() )
128 case FILTER_OOXML:
129 initializeMaxPos( OOX_MAXTAB, OOX_MAXCOL, OOX_MAXROW );
130 maLinkChars.set( 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF );
131 break;
132 case FILTER_BIFF: switch( getBiff() )
134 case BIFF2:
135 initializeMaxPos( BIFF2_MAXTAB, BIFF2_MAXCOL, BIFF2_MAXROW );
136 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
137 break;
138 case BIFF3:
139 initializeMaxPos( BIFF3_MAXTAB, BIFF3_MAXCOL, BIFF3_MAXROW );
140 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
141 break;
142 case BIFF4:
143 initializeMaxPos( BIFF4_MAXTAB, BIFF4_MAXCOL, BIFF4_MAXROW );
144 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, '\x00' );
145 break;
146 case BIFF5:
147 initializeMaxPos( BIFF5_MAXTAB, BIFF5_MAXCOL, BIFF5_MAXROW );
148 maLinkChars.set( '\x04', '\x01', '\x02', '\x03', '\x00' );
149 break;
150 case BIFF8:
151 initializeMaxPos( BIFF8_MAXTAB, BIFF8_MAXCOL, BIFF8_MAXROW );
152 maLinkChars.set( '\x04', '\x01', 0xFFFF, '\x02', '\x00' );
153 break;
154 case BIFF_UNKNOWN:
155 initializeMaxPos( 0, 0, 0 );
156 maLinkChars.set( 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF );
157 break;
159 break;
160 case FILTER_UNKNOWN:
161 initializeMaxPos( 0, 0, 0 );
162 maLinkChars.set( 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF );
163 break;
167 bool AddressConverter::parseOoxAddress2d(
168 sal_Int32& ornColumn, sal_Int32& ornRow,
169 const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
171 ornColumn = ornRow = 0;
172 if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
173 return false;
175 const sal_Unicode* pcChar = rString.getStr() + nStart;
176 const sal_Unicode* pcEndChar = pcChar + ::std::min( nLength, rString.getLength() - nStart );
178 enum { STATE_COL, STATE_ROW } eState = STATE_COL;
179 while( pcChar < pcEndChar )
181 sal_Unicode cChar = *pcChar;
182 switch( eState )
184 case STATE_COL:
186 if( ('a' <= cChar) && (cChar <= 'z') )
187 (cChar -= 'a') += 'A';
188 if( ('A' <= cChar) && (cChar <= 'Z') )
190 /* Return, if 1-based column index is already 6 characters
191 long (12356631 is column index for column AAAAAA). */
192 if( ornColumn >= 12356631 )
193 return false;
194 (ornColumn *= 26) += (cChar - 'A' + 1);
196 else if( ornColumn > 0 )
198 --pcChar;
199 eState = STATE_ROW;
201 else
202 return false;
204 break;
206 case STATE_ROW:
208 if( ('0' <= cChar) && (cChar <= '9') )
210 // return, if 1-based row is already 9 digits long
211 if( ornRow >= 100000000 )
212 return false;
213 (ornRow *= 10) += (cChar - '0');
215 else
216 return false;
218 break;
220 ++pcChar;
223 --ornColumn;
224 --ornRow;
225 return (ornColumn >= 0) && (ornRow >= 0);
228 bool AddressConverter::parseOoxAddress2d( sal_Int32& ornColumn, sal_Int32& ornRow, const char* pStr )
230 ornColumn = ornRow = 0;
232 enum { STATE_COL, STATE_ROW } eState = STATE_COL;
234 while (*pStr)
236 char cChar = *pStr;
237 switch( eState )
239 case STATE_COL:
241 if( ('a' <= cChar) && (cChar <= 'z') )
242 (cChar -= 'a') += 'A';
243 if( ('A' <= cChar) && (cChar <= 'Z') )
245 /* Return, if 1-based column index is already 6 characters
246 long (12356631 is column index for column AAAAAA). */
247 if( ornColumn >= 12356631 )
248 return false;
249 (ornColumn *= 26) += (cChar - 'A' + 1);
251 else if( ornColumn > 0 )
253 --pStr;
254 eState = STATE_ROW;
256 else
257 return false;
259 break;
261 case STATE_ROW:
263 if( ('0' <= cChar) && (cChar <= '9') )
265 // return, if 1-based row is already 9 digits long
266 if( ornRow >= 100000000 )
267 return false;
268 (ornRow *= 10) += (cChar - '0');
270 else
271 return false;
273 break;
275 ++pStr;
278 --ornColumn;
279 --ornRow;
280 return (ornColumn >= 0) && (ornRow >= 0);
283 bool AddressConverter::parseOoxRange2d(
284 sal_Int32& ornStartColumn, sal_Int32& ornStartRow,
285 sal_Int32& ornEndColumn, sal_Int32& ornEndRow,
286 const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
288 ornStartColumn = ornStartRow = ornEndColumn = ornEndRow = 0;
289 if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
290 return false;
292 sal_Int32 nEnd = nStart + ::std::min( nLength, rString.getLength() - nStart );
293 sal_Int32 nColonPos = rString.indexOf( ':', nStart );
294 if( (nStart < nColonPos) && (nColonPos + 1 < nEnd) )
296 return
297 parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nColonPos - nStart ) &&
298 parseOoxAddress2d( ornEndColumn, ornEndRow, rString, nColonPos + 1, nLength - nColonPos - 1 );
301 if( parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nLength ) )
303 ornEndColumn = ornStartColumn;
304 ornEndRow = ornStartRow;
305 return true;
308 return false;
311 bool AddressConverter::checkCol( sal_Int32 nCol, bool bTrackOverflow )
313 bool bValid = (0 <= nCol) && (nCol <= maMaxPos.Column);
314 if( !bValid && bTrackOverflow )
315 mbColOverflow = true;
316 return bValid;
319 bool AddressConverter::checkRow( sal_Int32 nRow, bool bTrackOverflow )
321 bool bValid = (0 <= nRow) && (nRow <= maMaxPos.Row);
322 if( !bValid && bTrackOverflow )
323 mbRowOverflow = true;
324 return bValid;
327 bool AddressConverter::checkTab( sal_Int16 nSheet, bool bTrackOverflow )
329 bool bValid = (0 <= nSheet) && (nSheet <= maMaxPos.Sheet);
330 if( !bValid && bTrackOverflow )
331 mbTabOverflow |= (nSheet > maMaxPos.Sheet); // do not warn for deleted refs (-1)
332 return bValid;
335 bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrackOverflow )
337 return
338 checkTab( rAddress.Sheet, bTrackOverflow ) &&
339 checkCol( rAddress.Column, bTrackOverflow ) &&
340 checkRow( rAddress.Row, bTrackOverflow );
343 bool AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
344 const OUString& rString, sal_Int16 nSheet )
346 orAddress.Sheet = nSheet;
347 return parseOoxAddress2d( orAddress.Column, orAddress.Row, rString );
350 bool AddressConverter::convertToCellAddressUnchecked(
351 com::sun::star::table::CellAddress& orAddress, const char* pStr, sal_Int16 nSheet )
353 orAddress.Sheet = nSheet;
354 return parseOoxAddress2d(orAddress.Column, orAddress.Row, pStr);
357 bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
358 const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
360 return
361 convertToCellAddressUnchecked( orAddress, rString, nSheet ) &&
362 checkCellAddress( orAddress, bTrackOverflow );
365 bool AddressConverter::convertToCellAddress(
366 com::sun::star::table::CellAddress& rAddress,
367 const char* pStr, sal_Int16 nSheet, bool bTrackOverflow )
369 if (!convertToCellAddressUnchecked(rAddress, pStr, nSheet))
370 return false;
372 return checkCellAddress(rAddress, bTrackOverflow);
375 CellAddress AddressConverter::createValidCellAddress(
376 const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
378 CellAddress aAddress;
379 if( !convertToCellAddress( aAddress, rString, nSheet, bTrackOverflow ) )
381 aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
382 aAddress.Column = ::std::min( aAddress.Column, maMaxPos.Column );
383 aAddress.Row = ::std::min( aAddress.Row, maMaxPos.Row );
385 return aAddress;
388 void AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
389 const BinAddress& rBinAddress, sal_Int16 nSheet )
391 orAddress.Sheet = nSheet;
392 orAddress.Column = rBinAddress.mnCol;
393 orAddress.Row = rBinAddress.mnRow;
396 bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
397 const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
399 convertToCellAddressUnchecked( orAddress, rBinAddress, nSheet );
400 return checkCellAddress( orAddress, bTrackOverflow );
403 CellAddress AddressConverter::createValidCellAddress(
404 const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
406 CellAddress aAddress;
407 if( !convertToCellAddress( aAddress, rBinAddress, nSheet, bTrackOverflow ) )
409 aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
410 aAddress.Column = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnCol, 0, maMaxPos.Column );
411 aAddress.Row = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnRow, 0, maMaxPos.Row );
413 return aAddress;
416 bool AddressConverter::checkCellRange( const CellRangeAddress& rRange, bool bAllowOverflow, bool bTrackOverflow )
418 return
419 (checkCol( rRange.EndColumn, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkCol to track overflow!
420 (checkRow( rRange.EndRow, bTrackOverflow ) || bAllowOverflow) && // bAllowOverflow after checkRow to track overflow!
421 checkTab( rRange.Sheet, bTrackOverflow ) &&
422 checkCol( rRange.StartColumn, bTrackOverflow ) &&
423 checkRow( rRange.StartRow, bTrackOverflow );
426 bool AddressConverter::validateCellRange( CellRangeAddress& orRange, bool bAllowOverflow, bool bTrackOverflow )
428 if( orRange.StartColumn > orRange.EndColumn )
429 ::std::swap( orRange.StartColumn, orRange.EndColumn );
430 if( orRange.StartRow > orRange.EndRow )
431 ::std::swap( orRange.StartRow, orRange.EndRow );
432 if( !checkCellRange( orRange, bAllowOverflow, bTrackOverflow ) )
433 return false;
434 if( orRange.EndColumn > maMaxPos.Column )
435 orRange.EndColumn = maMaxPos.Column;
436 if( orRange.EndRow > maMaxPos.Row )
437 orRange.EndRow = maMaxPos.Row;
438 return true;
441 bool AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
442 const OUString& rString, sal_Int16 nSheet )
444 orRange.Sheet = nSheet;
445 return parseOoxRange2d( orRange.StartColumn, orRange.StartRow, orRange.EndColumn, orRange.EndRow, rString );
448 bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
449 const OUString& rString, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
451 return
452 convertToCellRangeUnchecked( orRange, rString, nSheet ) &&
453 validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
456 void AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
457 const BinRange& rBinRange, sal_Int16 nSheet )
459 orRange.Sheet = nSheet;
460 orRange.StartColumn = rBinRange.maFirst.mnCol;
461 orRange.StartRow = rBinRange.maFirst.mnRow;
462 orRange.EndColumn = rBinRange.maLast.mnCol;
463 orRange.EndRow = rBinRange.maLast.mnRow;
466 bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
467 const BinRange& rBinRange, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
469 convertToCellRangeUnchecked( orRange, rBinRange, nSheet );
470 return validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
473 void AddressConverter::validateCellRangeList( ApiCellRangeList& orRanges, bool bTrackOverflow )
475 for( size_t nIndex = orRanges.size(); nIndex > 0; --nIndex )
476 if( !validateCellRange( orRanges[ nIndex - 1 ], true, bTrackOverflow ) )
477 orRanges.erase( orRanges.begin() + nIndex - 1 );
480 void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
481 const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
483 sal_Int32 nPos = 0;
484 sal_Int32 nLen = rString.getLength();
485 CellRangeAddress aRange;
486 while( (0 <= nPos) && (nPos < nLen) )
488 OUString aToken = rString.getToken( 0, ' ', nPos );
489 if( !aToken.isEmpty() && convertToCellRange( aRange, aToken, nSheet, true, bTrackOverflow ) )
490 orRanges.push_back( aRange );
494 void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
495 const BinRangeList& rBinRanges, sal_Int16 nSheet, bool bTrackOverflow )
497 CellRangeAddress aRange;
498 for( ::std::vector< BinRange >::const_iterator aIt = rBinRanges.begin(), aEnd = rBinRanges.end(); aIt != aEnd; ++aIt )
499 if( convertToCellRange( aRange, *aIt, nSheet, true, bTrackOverflow ) )
500 orRanges.push_back( aRange );
503 // private --------------------------------------------------------------------
505 void AddressConverter::ControlCharacters::set(
506 sal_Unicode cThisWorkbook, sal_Unicode cExternal,
507 sal_Unicode cThisSheet, sal_Unicode cInternal, sal_Unicode cSameSheet )
509 mcThisWorkbook = cThisWorkbook;
510 mcExternal = cExternal;
511 mcThisSheet = cThisSheet;
512 mcInternal = cInternal;
513 mcSameSheet = cSameSheet;
516 void AddressConverter::initializeMaxPos(
517 sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow )
519 maMaxXlsPos.Sheet = nMaxXlsTab;
520 maMaxXlsPos.Column = nMaxXlsCol;
521 maMaxXlsPos.Row = nMaxXlsRow;
523 // maximum cell position in Calc
526 Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW );
527 Reference< XCellRangeAddressable > xAddressable( xSheetsIA->getByIndex( 0 ), UNO_QUERY_THROW );
528 CellRangeAddress aRange = xAddressable->getRangeAddress();
529 maMaxApiPos = CellAddress( API_MAXTAB, aRange.EndColumn, aRange.EndRow );
530 maMaxPos = getBaseFilter().isImportFilter() ? maMaxApiPos : maMaxXlsPos;
532 catch( Exception& )
534 OSL_FAIL( "AddressConverter::AddressConverter - cannot get sheet limits" );
538 } // namespace xls
539 } // namespace oox
541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */