1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/xls/addressconverter.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <com/sun/star/container/XIndexAccess.hpp>
27cdf0e10cSrcweir #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
28cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
29cdf0e10cSrcweir #include <osl/diagnose.h>
30cdf0e10cSrcweir #include <rtl/strbuf.hxx>
31cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
32cdf0e10cSrcweir #include "oox/core/filterbase.hxx"
33cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx"
34cdf0e10cSrcweir #include "oox/xls/biffoutputstream.hxx"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir namespace oox {
37cdf0e10cSrcweir namespace xls {
38cdf0e10cSrcweir 
39cdf0e10cSrcweir // ============================================================================
40cdf0e10cSrcweir 
41cdf0e10cSrcweir using namespace ::com::sun::star::container;
42cdf0e10cSrcweir using namespace ::com::sun::star::sheet;
43cdf0e10cSrcweir using namespace ::com::sun::star::table;
44cdf0e10cSrcweir using namespace ::com::sun::star::uno;
45cdf0e10cSrcweir 
46cdf0e10cSrcweir using ::rtl::OStringBuffer;
47cdf0e10cSrcweir using ::rtl::OUString;
48cdf0e10cSrcweir using ::rtl::OUStringBuffer;
49cdf0e10cSrcweir using ::rtl::OUStringToOString;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir // ============================================================================
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace {
54cdf0e10cSrcweir 
55cdf0e10cSrcweir //! TODO: this limit may change, is there a way to obtain it via API?
56cdf0e10cSrcweir const sal_Int16 API_MAXTAB          = 255;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir const sal_Int32 OOX_MAXCOL          = static_cast< sal_Int32 >( (1 << 14) - 1 );
59cdf0e10cSrcweir const sal_Int32 OOX_MAXROW          = static_cast< sal_Int32 >( (1 << 20) - 1 );
60cdf0e10cSrcweir const sal_Int16 OOX_MAXTAB          = static_cast< sal_Int16 >( (1 << 15) - 1 );
61cdf0e10cSrcweir 
62cdf0e10cSrcweir const sal_Int32 BIFF2_MAXCOL        = 255;
63cdf0e10cSrcweir const sal_Int32 BIFF2_MAXROW        = 16383;
64cdf0e10cSrcweir const sal_Int16 BIFF2_MAXTAB        = 0;
65cdf0e10cSrcweir 
66cdf0e10cSrcweir const sal_Int32 BIFF3_MAXCOL        = BIFF2_MAXCOL;
67cdf0e10cSrcweir const sal_Int32 BIFF3_MAXROW        = BIFF2_MAXROW;
68cdf0e10cSrcweir const sal_Int16 BIFF3_MAXTAB        = BIFF2_MAXTAB;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir const sal_Int32 BIFF4_MAXCOL        = BIFF3_MAXCOL;
71cdf0e10cSrcweir const sal_Int32 BIFF4_MAXROW        = BIFF3_MAXROW;
72cdf0e10cSrcweir const sal_Int16 BIFF4_MAXTAB        = 32767;
73cdf0e10cSrcweir 
74cdf0e10cSrcweir const sal_Int32 BIFF5_MAXCOL        = BIFF4_MAXCOL;
75cdf0e10cSrcweir const sal_Int32 BIFF5_MAXROW        = BIFF4_MAXROW;
76cdf0e10cSrcweir const sal_Int16 BIFF5_MAXTAB        = BIFF4_MAXTAB;
77cdf0e10cSrcweir 
78cdf0e10cSrcweir const sal_Int32 BIFF8_MAXCOL        = BIFF5_MAXCOL;
79cdf0e10cSrcweir const sal_Int32 BIFF8_MAXROW        = 65535;
80cdf0e10cSrcweir const sal_Int16 BIFF8_MAXTAB        = BIFF5_MAXTAB;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir const sal_Unicode BIFF_URL_DRIVE    = '\x01';       /// DOS drive letter or UNC path.
83cdf0e10cSrcweir const sal_Unicode BIFF_URL_ROOT     = '\x02';       /// Root directory of current drive.
84cdf0e10cSrcweir const sal_Unicode BIFF_URL_SUBDIR   = '\x03';       /// Subdirectory delimiter.
85cdf0e10cSrcweir const sal_Unicode BIFF_URL_PARENT   = '\x04';       /// Parent directory.
86cdf0e10cSrcweir const sal_Unicode BIFF_URL_RAW      = '\x05';       /// Unencoded URL.
87cdf0e10cSrcweir const sal_Unicode BIFF_URL_INSTALL  = '\x06';       /// Application installation directory.
88cdf0e10cSrcweir const sal_Unicode BIFF_URL_INSTALL2 = '\x07';       /// Alternative application installation directory.
89cdf0e10cSrcweir const sal_Unicode BIFF_URL_LIBRARY  = '\x08';       /// Library directory in application installation.
90cdf0e10cSrcweir const sal_Unicode BIFF4_URL_SHEET   = '\x09';       /// BIFF4 internal sheet.
91cdf0e10cSrcweir const sal_Unicode BIFF_URL_UNC      = '@';          /// UNC path root.
92cdf0e10cSrcweir 
93cdf0e10cSrcweir const sal_Unicode BIFF_DCON_ENCODED = '\x01';       /// First character of an encoded path from DCON* records.
94cdf0e10cSrcweir const sal_Unicode BIFF_DCON_INTERN  = '\x02';       /// First character of an encoded sheet name from DCON* records.
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 
lclGetBiffAddressSize(bool bCol16Bit,bool bRow32Bit)97cdf0e10cSrcweir inline sal_uInt8 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir     return (bCol16Bit ? 2 : 1) + (bRow32Bit ? 4 : 2);
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
lclGetBiffRangeSize(bool bCol16Bit,bool bRow32Bit)102cdf0e10cSrcweir inline sal_uInt8 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir     return 2 * lclGetBiffAddressSize( bCol16Bit, bRow32Bit );
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
107cdf0e10cSrcweir } // namespace
108cdf0e10cSrcweir 
109cdf0e10cSrcweir // ============================================================================
110cdf0e10cSrcweir // ============================================================================
111cdf0e10cSrcweir 
getBaseAddress() const112cdf0e10cSrcweir CellAddress ApiCellRangeList::getBaseAddress() const
113cdf0e10cSrcweir {
114cdf0e10cSrcweir     if( empty() )
115cdf0e10cSrcweir         return CellAddress();
116cdf0e10cSrcweir     return CellAddress( front().Sheet, front().StartColumn, front().StartRow );
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir // ============================================================================
120cdf0e10cSrcweir 
read(SequenceInputStream & rStrm)121cdf0e10cSrcweir void BinAddress::read( SequenceInputStream& rStrm )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     rStrm >> mnRow >> mnCol;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
read(BiffInputStream & rStrm,bool bCol16Bit,bool bRow32Bit)126cdf0e10cSrcweir void BinAddress::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir     mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
129cdf0e10cSrcweir     mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
130cdf0e10cSrcweir }
131cdf0e10cSrcweir 
write(BiffOutputStream & rStrm,bool bCol16Bit,bool bRow32Bit) const132cdf0e10cSrcweir void BinAddress::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const
133cdf0e10cSrcweir {
134cdf0e10cSrcweir     if( bRow32Bit )
135cdf0e10cSrcweir         rStrm << mnRow;
136cdf0e10cSrcweir     else
137cdf0e10cSrcweir         rStrm << static_cast< sal_uInt16 >( mnRow );
138cdf0e10cSrcweir     if( bCol16Bit )
139cdf0e10cSrcweir         rStrm << static_cast< sal_uInt16 >( mnCol );
140cdf0e10cSrcweir     else
141cdf0e10cSrcweir         rStrm << static_cast< sal_uInt8 >( mnCol );
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir // ============================================================================
145cdf0e10cSrcweir 
contains(const BinAddress & rAddr) const146cdf0e10cSrcweir bool BinRange::contains( const BinAddress& rAddr ) const
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     return  (maFirst.mnCol <= rAddr.mnCol) && (rAddr.mnCol <= maLast.mnCol) &&
149cdf0e10cSrcweir             (maFirst.mnRow <= rAddr.mnRow) && (rAddr.mnRow <= maLast.mnRow);
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
read(SequenceInputStream & rStrm)152cdf0e10cSrcweir void BinRange::read( SequenceInputStream& rStrm )
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     rStrm >> maFirst.mnRow >> maLast.mnRow >> maFirst.mnCol >> maLast.mnCol;
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
read(BiffInputStream & rStrm,bool bCol16Bit,bool bRow32Bit)157cdf0e10cSrcweir void BinRange::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
158cdf0e10cSrcweir {
159cdf0e10cSrcweir     maFirst.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
160cdf0e10cSrcweir     maLast.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16();
161cdf0e10cSrcweir     maFirst.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
162cdf0e10cSrcweir     maLast.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8();
163cdf0e10cSrcweir }
164cdf0e10cSrcweir 
write(BiffOutputStream & rStrm,bool bCol16Bit,bool bRow32Bit) const165cdf0e10cSrcweir void BinRange::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const
166cdf0e10cSrcweir {
167cdf0e10cSrcweir     if( bRow32Bit )
168cdf0e10cSrcweir         rStrm << maFirst.mnRow << maLast.mnRow;
169cdf0e10cSrcweir     else
170cdf0e10cSrcweir         rStrm << static_cast< sal_uInt16 >( maFirst.mnRow ) << static_cast< sal_uInt16 >( maLast.mnRow );
171cdf0e10cSrcweir     if( bCol16Bit )
172cdf0e10cSrcweir         rStrm << static_cast< sal_uInt16 >( maFirst.mnCol ) << static_cast< sal_uInt16 >( maLast.mnCol );
173cdf0e10cSrcweir     else
174cdf0e10cSrcweir         rStrm << static_cast< sal_uInt8 >( maFirst.mnCol ) << static_cast< sal_uInt8 >( maLast.mnCol );
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir // ============================================================================
178cdf0e10cSrcweir 
getEnclosingRange() const179cdf0e10cSrcweir BinRange BinRangeList::getEnclosingRange() const
180cdf0e10cSrcweir {
181cdf0e10cSrcweir     BinRange aRange;
182cdf0e10cSrcweir     if( !empty() )
183cdf0e10cSrcweir     {
184cdf0e10cSrcweir         const_iterator aIt = begin(), aEnd = end();
185cdf0e10cSrcweir         aRange = *aIt;
186cdf0e10cSrcweir         for( ++aIt; aIt != aEnd; ++aIt )
187cdf0e10cSrcweir         {
188cdf0e10cSrcweir             aRange.maFirst.mnCol = ::std::min( aRange.maFirst.mnCol, aIt->maFirst.mnCol );
189cdf0e10cSrcweir             aRange.maFirst.mnRow = ::std::min( aRange.maFirst.mnRow, aIt->maFirst.mnRow );
190cdf0e10cSrcweir             aRange.maLast.mnCol  = ::std::max( aRange.maLast.mnCol, aIt->maLast.mnCol );
191cdf0e10cSrcweir             aRange.maLast.mnRow  = ::std::max( aRange.maLast.mnRow, aIt->maLast.mnRow );
192cdf0e10cSrcweir         }
193cdf0e10cSrcweir     }
194cdf0e10cSrcweir     return aRange;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
read(SequenceInputStream & rStrm)197cdf0e10cSrcweir void BinRangeList::read( SequenceInputStream& rStrm )
198cdf0e10cSrcweir {
199cdf0e10cSrcweir     sal_Int32 nCount = rStrm.readInt32();
200cdf0e10cSrcweir     resize( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 16 ) );
201cdf0e10cSrcweir     for( iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
202cdf0e10cSrcweir         aIt->read( rStrm );
203cdf0e10cSrcweir }
204cdf0e10cSrcweir 
read(BiffInputStream & rStrm,bool bCol16Bit,bool bRow32Bit)205cdf0e10cSrcweir void BinRangeList::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit )
206cdf0e10cSrcweir {
207cdf0e10cSrcweir     sal_uInt16 nCount = rStrm.readuInt16();
208cdf0e10cSrcweir     resize( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / lclGetBiffRangeSize( bCol16Bit, bRow32Bit ) ) );
209cdf0e10cSrcweir     for( iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
210cdf0e10cSrcweir         aIt->read( rStrm, bCol16Bit, bRow32Bit );
211cdf0e10cSrcweir }
212cdf0e10cSrcweir 
write(BiffOutputStream & rStrm,bool bCol16Bit,bool bRow32Bit) const213cdf0e10cSrcweir void BinRangeList::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const
214cdf0e10cSrcweir {
215cdf0e10cSrcweir     writeSubList( rStrm, 0, size(), bCol16Bit, bRow32Bit );
216cdf0e10cSrcweir }
217cdf0e10cSrcweir 
writeSubList(BiffOutputStream & rStrm,size_t nBegin,size_t nCount,bool bCol16Bit,bool bRow32Bit) const218cdf0e10cSrcweir void BinRangeList::writeSubList( BiffOutputStream& rStrm, size_t nBegin, size_t nCount, bool bCol16Bit, bool bRow32Bit ) const
219cdf0e10cSrcweir {
220cdf0e10cSrcweir     OSL_ENSURE( nBegin <= size(), "BiffRangeList::writeSubList - invalid start position" );
221cdf0e10cSrcweir     size_t nEnd = ::std::min< size_t >( nBegin + nCount, size() );
222cdf0e10cSrcweir     sal_uInt16 nBiffCount = getLimitedValue< sal_uInt16, size_t >( nEnd - nBegin, 0, SAL_MAX_UINT16 );
223cdf0e10cSrcweir     rStrm << nBiffCount;
224cdf0e10cSrcweir     rStrm.setPortionSize( lclGetBiffRangeSize( bCol16Bit, bRow32Bit ) );
225cdf0e10cSrcweir     for( const_iterator aIt = begin() + nBegin, aEnd = begin() + nEnd; aIt != aEnd; ++aIt )
226cdf0e10cSrcweir         aIt->write( rStrm, bCol16Bit, bRow32Bit );
227cdf0e10cSrcweir }
228cdf0e10cSrcweir 
229cdf0e10cSrcweir // ============================================================================
230cdf0e10cSrcweir // ============================================================================
231cdf0e10cSrcweir 
AddressConverter(const WorkbookHelper & rHelper)232cdf0e10cSrcweir AddressConverter::AddressConverter( const WorkbookHelper& rHelper ) :
233cdf0e10cSrcweir     WorkbookHelper( rHelper ),
234cdf0e10cSrcweir     mbColOverflow( false ),
235cdf0e10cSrcweir     mbRowOverflow( false ),
236cdf0e10cSrcweir     mbTabOverflow( false )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir     maDConChars.set( 0xFFFF, '\x01', 0xFFFF, '\x02', 0xFFFF );
239cdf0e10cSrcweir     switch( getFilterType() )
240cdf0e10cSrcweir     {
241cdf0e10cSrcweir         case FILTER_OOXML:
242cdf0e10cSrcweir             initializeMaxPos( OOX_MAXTAB, OOX_MAXCOL, OOX_MAXROW );
243cdf0e10cSrcweir         break;
244cdf0e10cSrcweir         case FILTER_BIFF: switch( getBiff() )
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             case BIFF2:
247cdf0e10cSrcweir                 initializeMaxPos( BIFF2_MAXTAB, BIFF2_MAXCOL, BIFF2_MAXROW );
248cdf0e10cSrcweir                 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
249cdf0e10cSrcweir             break;
250cdf0e10cSrcweir             case BIFF3:
251cdf0e10cSrcweir                 initializeMaxPos( BIFF3_MAXTAB, BIFF3_MAXCOL, BIFF3_MAXROW );
252cdf0e10cSrcweir                 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, 0xFFFF );
253cdf0e10cSrcweir             break;
254cdf0e10cSrcweir             case BIFF4:
255cdf0e10cSrcweir                 initializeMaxPos( BIFF4_MAXTAB, BIFF4_MAXCOL, BIFF4_MAXROW );
256cdf0e10cSrcweir                 maLinkChars.set( 0xFFFF, '\x01', '\x02', 0xFFFF, '\x00' );
257cdf0e10cSrcweir             break;
258cdf0e10cSrcweir             case BIFF5:
259cdf0e10cSrcweir                 initializeMaxPos( BIFF5_MAXTAB, BIFF5_MAXCOL, BIFF5_MAXROW );
260cdf0e10cSrcweir                 maLinkChars.set( '\x04', '\x01', '\x02', '\x03', '\x00' );
261cdf0e10cSrcweir             break;
262cdf0e10cSrcweir             case BIFF8:
263cdf0e10cSrcweir                 initializeMaxPos( BIFF8_MAXTAB, BIFF8_MAXCOL, BIFF8_MAXROW );
264cdf0e10cSrcweir                 maLinkChars.set( '\x04', '\x01', 0xFFFF, '\x02', '\x00' );
265cdf0e10cSrcweir             break;
266cdf0e10cSrcweir             case BIFF_UNKNOWN: break;
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir         break;
269cdf0e10cSrcweir         case FILTER_UNKNOWN: break;
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir // ----------------------------------------------------------------------------
274cdf0e10cSrcweir 
parseOoxAddress2d(sal_Int32 & ornColumn,sal_Int32 & ornRow,const OUString & rString,sal_Int32 nStart,sal_Int32 nLength)275cdf0e10cSrcweir bool AddressConverter::parseOoxAddress2d(
276cdf0e10cSrcweir         sal_Int32& ornColumn, sal_Int32& ornRow,
277cdf0e10cSrcweir         const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
278cdf0e10cSrcweir {
279cdf0e10cSrcweir     ornColumn = ornRow = 0;
280cdf0e10cSrcweir     if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
281cdf0e10cSrcweir         return false;
282cdf0e10cSrcweir 
283cdf0e10cSrcweir     const sal_Unicode* pcChar = rString.getStr() + nStart;
284cdf0e10cSrcweir     const sal_Unicode* pcEndChar = pcChar + ::std::min( nLength, rString.getLength() - nStart );
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     enum { STATE_COL, STATE_ROW } eState = STATE_COL;
287cdf0e10cSrcweir     while( pcChar < pcEndChar )
288cdf0e10cSrcweir     {
289cdf0e10cSrcweir         sal_Unicode cChar = *pcChar;
290cdf0e10cSrcweir         switch( eState )
291cdf0e10cSrcweir         {
292cdf0e10cSrcweir             case STATE_COL:
293cdf0e10cSrcweir             {
294cdf0e10cSrcweir                 if( ('a' <= cChar) && (cChar <= 'z') )
295cdf0e10cSrcweir                     (cChar -= 'a') += 'A';
296cdf0e10cSrcweir                 if( ('A' <= cChar) && (cChar <= 'Z') )
297cdf0e10cSrcweir                 {
298cdf0e10cSrcweir                     /*  Return, if 1-based column index is already 6 characters
299cdf0e10cSrcweir                         long (12356631 is column index for column AAAAAA). */
300cdf0e10cSrcweir                     if( ornColumn >= 12356631 )
301cdf0e10cSrcweir                         return false;
302cdf0e10cSrcweir                     (ornColumn *= 26) += (cChar - 'A' + 1);
303cdf0e10cSrcweir                 }
304cdf0e10cSrcweir                 else if( ornColumn > 0 )
305cdf0e10cSrcweir                 {
306cdf0e10cSrcweir                     --pcChar;
307cdf0e10cSrcweir                     eState = STATE_ROW;
308cdf0e10cSrcweir                 }
309cdf0e10cSrcweir                 else
310cdf0e10cSrcweir                     return false;
311cdf0e10cSrcweir             }
312cdf0e10cSrcweir             break;
313cdf0e10cSrcweir 
314cdf0e10cSrcweir             case STATE_ROW:
315cdf0e10cSrcweir             {
316cdf0e10cSrcweir                 if( ('0' <= cChar) && (cChar <= '9') )
317cdf0e10cSrcweir                 {
318cdf0e10cSrcweir                     // return, if 1-based row is already 9 digits long
319cdf0e10cSrcweir                     if( ornRow >= 100000000 )
320cdf0e10cSrcweir                         return false;
321cdf0e10cSrcweir                     (ornRow *= 10) += (cChar - '0');
322cdf0e10cSrcweir                 }
323cdf0e10cSrcweir                 else
324cdf0e10cSrcweir                     return false;
325cdf0e10cSrcweir             }
326cdf0e10cSrcweir             break;
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir         ++pcChar;
329cdf0e10cSrcweir     }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     --ornColumn;
332cdf0e10cSrcweir     --ornRow;
333cdf0e10cSrcweir     return (ornColumn >= 0) && (ornRow >= 0);
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
parseOoxRange2d(sal_Int32 & ornStartColumn,sal_Int32 & ornStartRow,sal_Int32 & ornEndColumn,sal_Int32 & ornEndRow,const OUString & rString,sal_Int32 nStart,sal_Int32 nLength)336cdf0e10cSrcweir bool AddressConverter::parseOoxRange2d(
337cdf0e10cSrcweir         sal_Int32& ornStartColumn, sal_Int32& ornStartRow,
338cdf0e10cSrcweir         sal_Int32& ornEndColumn, sal_Int32& ornEndRow,
339cdf0e10cSrcweir         const OUString& rString, sal_Int32 nStart, sal_Int32 nLength )
340cdf0e10cSrcweir {
341cdf0e10cSrcweir     ornStartColumn = ornStartRow = ornEndColumn = ornEndRow = 0;
342cdf0e10cSrcweir     if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) )
343cdf0e10cSrcweir         return false;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     sal_Int32 nEnd = nStart + ::std::min( nLength, rString.getLength() - nStart );
346cdf0e10cSrcweir     sal_Int32 nColonPos = rString.indexOf( ':', nStart );
347cdf0e10cSrcweir     if( (nStart < nColonPos) && (nColonPos + 1 < nEnd) )
348cdf0e10cSrcweir     {
349cdf0e10cSrcweir         return
350cdf0e10cSrcweir             parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nColonPos - nStart ) &&
351cdf0e10cSrcweir             parseOoxAddress2d( ornEndColumn, ornEndRow, rString, nColonPos + 1, nLength - nColonPos - 1 );
352cdf0e10cSrcweir     }
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     if( parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nLength ) )
355cdf0e10cSrcweir     {
356cdf0e10cSrcweir         ornEndColumn = ornStartColumn;
357cdf0e10cSrcweir         ornEndRow = ornStartRow;
358cdf0e10cSrcweir         return true;
359cdf0e10cSrcweir     }
360cdf0e10cSrcweir 
361cdf0e10cSrcweir     return false;
362cdf0e10cSrcweir }
363cdf0e10cSrcweir 
364cdf0e10cSrcweir namespace {
365cdf0e10cSrcweir 
lclAppendUrlChar(OUStringBuffer & orUrl,sal_Unicode cChar,bool bEncodeSpecial)366cdf0e10cSrcweir bool lclAppendUrlChar( OUStringBuffer& orUrl, sal_Unicode cChar, bool bEncodeSpecial )
367cdf0e10cSrcweir {
368cdf0e10cSrcweir     // #126855# encode special characters
369cdf0e10cSrcweir     if( bEncodeSpecial ) switch( cChar )
370cdf0e10cSrcweir     {
371cdf0e10cSrcweir         case '#':   orUrl.appendAscii( "%23" );  return true;
372cdf0e10cSrcweir         case '%':   orUrl.appendAscii( "%25" );  return true;
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir     orUrl.append( cChar );
375cdf0e10cSrcweir     return cChar >= ' ';
376cdf0e10cSrcweir }
377cdf0e10cSrcweir 
378cdf0e10cSrcweir } // namespace
379cdf0e10cSrcweir 
parseBiffTargetUrl(OUString & orClassName,OUString & orTargetUrl,OUString & orSheetName,const OUString & rBiffTargetUrl,bool bFromDConRec)380cdf0e10cSrcweir BiffTargetType AddressConverter::parseBiffTargetUrl(
381cdf0e10cSrcweir         OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName,
382cdf0e10cSrcweir         const OUString& rBiffTargetUrl, bool bFromDConRec )
383cdf0e10cSrcweir {
384cdf0e10cSrcweir     OUStringBuffer aTargetUrl;
385cdf0e10cSrcweir     OUStringBuffer aSheetName;
386cdf0e10cSrcweir     // default target type: some URL with/without sheet name, may be overridden below
387cdf0e10cSrcweir     BiffTargetType eTargetType = BIFF_TARGETTYPE_URL;
388cdf0e10cSrcweir     const ControlCharacters& rCChars = bFromDConRec ? maDConChars : maLinkChars;
389cdf0e10cSrcweir 
390cdf0e10cSrcweir     enum
391cdf0e10cSrcweir     {
392cdf0e10cSrcweir         STATE_START,
393cdf0e10cSrcweir         STATE_ENCODED_PATH_START,       /// Start of encoded file path.
394cdf0e10cSrcweir         STATE_ENCODED_PATH,             /// Inside encoded file path.
395cdf0e10cSrcweir         STATE_ENCODED_DRIVE,            /// DOS drive letter or start of UNC path.
396cdf0e10cSrcweir         STATE_ENCODED_URL,              /// Encoded URL, e.g. http links.
397cdf0e10cSrcweir         STATE_UNENCODED,                /// Unencoded URL, could be DDE or OLE.
398cdf0e10cSrcweir         STATE_DDE_OLE,                  /// Second part of DDE or OLE link.
399cdf0e10cSrcweir         STATE_FILENAME,                 /// File name enclosed in brackets.
400cdf0e10cSrcweir         STATE_SHEETNAME,                /// Sheet name following enclosed file name.
401cdf0e10cSrcweir         STATE_UNSUPPORTED,              /// Unsupported special paths.
402cdf0e10cSrcweir         STATE_ERROR
403cdf0e10cSrcweir     }
404cdf0e10cSrcweir     eState = STATE_START;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     const sal_Unicode* pcChar = rBiffTargetUrl.getStr();
407cdf0e10cSrcweir     const sal_Unicode* pcEnd = pcChar + rBiffTargetUrl.getLength();
408cdf0e10cSrcweir     for( ; (eState != STATE_ERROR) && (pcChar < pcEnd); ++pcChar )
409cdf0e10cSrcweir     {
410cdf0e10cSrcweir         sal_Unicode cChar = *pcChar;
411cdf0e10cSrcweir         switch( eState )
412cdf0e10cSrcweir         {
413cdf0e10cSrcweir             case STATE_START:
414cdf0e10cSrcweir                 if( (cChar == rCChars.mcThisWorkbook) || (cChar == rCChars.mcThisSheet) || (cChar == rCChars.mcSameSheet) )
415cdf0e10cSrcweir                 {
416cdf0e10cSrcweir                     if( pcChar + 1 < pcEnd )
417cdf0e10cSrcweir                         eState = STATE_ERROR;
418cdf0e10cSrcweir                     if( cChar == rCChars.mcSameSheet )
419cdf0e10cSrcweir                         eTargetType = BIFF_TARGETTYPE_SAMESHEET;
420cdf0e10cSrcweir                 }
421cdf0e10cSrcweir                 else if( cChar == rCChars.mcExternal )
422cdf0e10cSrcweir                     eState = (pcChar + 1 < pcEnd) ? STATE_ENCODED_PATH_START : STATE_ERROR;
423cdf0e10cSrcweir                 else if( cChar == rCChars.mcInternal )
424cdf0e10cSrcweir                     eState = (pcChar + 1 < pcEnd) ? STATE_SHEETNAME : STATE_ERROR;
425cdf0e10cSrcweir                 else
426cdf0e10cSrcweir                     eState = lclAppendUrlChar( aTargetUrl, cChar, true ) ? STATE_UNENCODED : STATE_ERROR;
427cdf0e10cSrcweir             break;
428cdf0e10cSrcweir 
429cdf0e10cSrcweir             case STATE_ENCODED_PATH_START:
430cdf0e10cSrcweir                 if( cChar == BIFF_URL_DRIVE )
431cdf0e10cSrcweir                     eState = STATE_ENCODED_DRIVE;
432cdf0e10cSrcweir                 else if( cChar == BIFF_URL_ROOT )
433cdf0e10cSrcweir                 {
434cdf0e10cSrcweir                     aTargetUrl.append( sal_Unicode( '/' ) );
435cdf0e10cSrcweir                     eState = STATE_ENCODED_PATH;
436cdf0e10cSrcweir                 }
437cdf0e10cSrcweir                 else if( cChar == BIFF_URL_PARENT )
438cdf0e10cSrcweir                     aTargetUrl.appendAscii( "../" );
439cdf0e10cSrcweir                 else if( cChar == BIFF_URL_RAW )
440cdf0e10cSrcweir                     eState = STATE_ENCODED_URL;
441cdf0e10cSrcweir                 else if( cChar == BIFF_URL_INSTALL )
442cdf0e10cSrcweir                     eState = STATE_UNSUPPORTED;
443cdf0e10cSrcweir                 else if( cChar == BIFF_URL_INSTALL2 )
444cdf0e10cSrcweir                     eState = STATE_UNSUPPORTED;
445cdf0e10cSrcweir                 else if( cChar == BIFF_URL_LIBRARY )
446cdf0e10cSrcweir                 {
447cdf0e10cSrcweir                     eState = STATE_ENCODED_PATH;
448cdf0e10cSrcweir                     eTargetType = BIFF_TARGETTYPE_LIBRARY;
449cdf0e10cSrcweir                 }
450cdf0e10cSrcweir                 else if( (getBiff() == BIFF4) && (cChar == BIFF4_URL_SHEET) )
451cdf0e10cSrcweir                     eState = STATE_SHEETNAME;
452cdf0e10cSrcweir                 else if( cChar == '[' )
453cdf0e10cSrcweir                     eState = STATE_FILENAME;
454cdf0e10cSrcweir                 else if( lclAppendUrlChar( aTargetUrl, cChar, true ) )
455cdf0e10cSrcweir                     eState = STATE_ENCODED_PATH;
456cdf0e10cSrcweir                 else
457cdf0e10cSrcweir                     eState = STATE_ERROR;
458cdf0e10cSrcweir             break;
459cdf0e10cSrcweir 
460cdf0e10cSrcweir             case STATE_ENCODED_PATH:
461cdf0e10cSrcweir                 if( cChar == BIFF_URL_SUBDIR )
462cdf0e10cSrcweir                     aTargetUrl.append( sal_Unicode( '/' ) );
463cdf0e10cSrcweir                 else if( cChar == '[' )
464cdf0e10cSrcweir                     eState = STATE_FILENAME;
465cdf0e10cSrcweir                 else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) )
466cdf0e10cSrcweir                     eState = STATE_ERROR;
467cdf0e10cSrcweir             break;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir             case STATE_ENCODED_DRIVE:
470cdf0e10cSrcweir                 if( cChar == BIFF_URL_UNC )
471cdf0e10cSrcweir                 {
472cdf0e10cSrcweir                     aTargetUrl.appendAscii( "file://" );
473cdf0e10cSrcweir                     eState = STATE_ENCODED_PATH;
474cdf0e10cSrcweir                 }
475cdf0e10cSrcweir                 else
476cdf0e10cSrcweir                 {
477cdf0e10cSrcweir                     aTargetUrl.appendAscii( "file:///" );
478cdf0e10cSrcweir                     eState = lclAppendUrlChar( aTargetUrl, cChar, false ) ? STATE_ENCODED_PATH : STATE_ERROR;
479cdf0e10cSrcweir                     aTargetUrl.appendAscii( ":/" );
480cdf0e10cSrcweir                 }
481cdf0e10cSrcweir             break;
482cdf0e10cSrcweir 
483cdf0e10cSrcweir             case STATE_ENCODED_URL:
484cdf0e10cSrcweir             {
485cdf0e10cSrcweir                 sal_Int32 nLength = cChar;
486cdf0e10cSrcweir                 if( nLength + 1 == pcEnd - pcChar )
487cdf0e10cSrcweir                     aTargetUrl.append( pcChar + 1, nLength );
488cdf0e10cSrcweir                 else
489cdf0e10cSrcweir                     eState = STATE_ERROR;
490cdf0e10cSrcweir             }
491cdf0e10cSrcweir             break;
492cdf0e10cSrcweir 
493cdf0e10cSrcweir             case STATE_UNENCODED:
494cdf0e10cSrcweir                 if( cChar == BIFF_URL_SUBDIR )
495cdf0e10cSrcweir                 {
496cdf0e10cSrcweir                     orClassName = aTargetUrl.makeStringAndClear();
497cdf0e10cSrcweir                     eState = bFromDConRec ? STATE_ERROR : STATE_DDE_OLE;
498cdf0e10cSrcweir                     eTargetType = BIFF_TARGETTYPE_DDE_OLE;
499cdf0e10cSrcweir                 }
500cdf0e10cSrcweir                 else if( cChar == '[' )
501cdf0e10cSrcweir                     eState = STATE_FILENAME;
502cdf0e10cSrcweir                 else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) )
503cdf0e10cSrcweir                     eState = STATE_ERROR;
504cdf0e10cSrcweir             break;
505cdf0e10cSrcweir 
506cdf0e10cSrcweir             case STATE_DDE_OLE:
507cdf0e10cSrcweir                 if( !lclAppendUrlChar( aTargetUrl, cChar, true ) )
508cdf0e10cSrcweir                     eState = STATE_ERROR;
509cdf0e10cSrcweir             break;
510cdf0e10cSrcweir 
511cdf0e10cSrcweir             case STATE_FILENAME:
512cdf0e10cSrcweir                 if( cChar == ']' )
513cdf0e10cSrcweir                     eState = STATE_SHEETNAME;
514cdf0e10cSrcweir                 else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) )
515cdf0e10cSrcweir                     eState = STATE_ERROR;
516cdf0e10cSrcweir             break;
517cdf0e10cSrcweir 
518cdf0e10cSrcweir             case STATE_SHEETNAME:
519cdf0e10cSrcweir                 if( !lclAppendUrlChar( aSheetName, cChar, false ) )
520cdf0e10cSrcweir                     eState = STATE_ERROR;
521cdf0e10cSrcweir             break;
522cdf0e10cSrcweir 
523cdf0e10cSrcweir             case STATE_UNSUPPORTED:
524cdf0e10cSrcweir                 pcChar = pcEnd - 1;
525cdf0e10cSrcweir             break;
526cdf0e10cSrcweir 
527cdf0e10cSrcweir             case STATE_ERROR:
528cdf0e10cSrcweir             break;
529cdf0e10cSrcweir         }
530cdf0e10cSrcweir     }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir     OSL_ENSURE( (eState != STATE_ERROR) && (pcChar == pcEnd),
533cdf0e10cSrcweir         OStringBuffer( "AddressConverter::parseBiffTargetUrl - parser error in target \"" ).
534cdf0e10cSrcweir         append( OUStringToOString( rBiffTargetUrl, RTL_TEXTENCODING_UTF8 ) ).append( '"' ).getStr() );
535cdf0e10cSrcweir     bool bParserOk = (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd);
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     if( bParserOk )
538cdf0e10cSrcweir     {
539cdf0e10cSrcweir         orTargetUrl = aTargetUrl.makeStringAndClear();
540cdf0e10cSrcweir         orSheetName = aSheetName.makeStringAndClear();
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir     else
543cdf0e10cSrcweir     {
544cdf0e10cSrcweir         orClassName = orTargetUrl = orSheetName = OUString();
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir 
547cdf0e10cSrcweir     return bParserOk ? eTargetType : BIFF_TARGETTYPE_UNKNOWN;
548cdf0e10cSrcweir }
549cdf0e10cSrcweir 
550cdf0e10cSrcweir // ----------------------------------------------------------------------------
551cdf0e10cSrcweir 
checkCol(sal_Int32 nCol,bool bTrackOverflow)552cdf0e10cSrcweir bool AddressConverter::checkCol( sal_Int32 nCol, bool bTrackOverflow )
553cdf0e10cSrcweir {
554cdf0e10cSrcweir     bool bValid = (0 <= nCol) && (nCol <= maMaxPos.Column);
555cdf0e10cSrcweir     if( !bValid && bTrackOverflow )
556cdf0e10cSrcweir         mbColOverflow = true;
557cdf0e10cSrcweir     return bValid;
558cdf0e10cSrcweir }
559cdf0e10cSrcweir 
checkRow(sal_Int32 nRow,bool bTrackOverflow)560cdf0e10cSrcweir bool AddressConverter::checkRow( sal_Int32 nRow, bool bTrackOverflow )
561cdf0e10cSrcweir {
562cdf0e10cSrcweir     bool bValid = (0 <= nRow) && (nRow <= maMaxPos.Row);
563cdf0e10cSrcweir     if( !bValid && bTrackOverflow )
564cdf0e10cSrcweir         mbRowOverflow = true;
565cdf0e10cSrcweir     return bValid;
566cdf0e10cSrcweir }
567cdf0e10cSrcweir 
checkTab(sal_Int16 nSheet,bool bTrackOverflow)568cdf0e10cSrcweir bool AddressConverter::checkTab( sal_Int16 nSheet, bool bTrackOverflow )
569cdf0e10cSrcweir {
570cdf0e10cSrcweir     bool bValid = (0 <= nSheet) && (nSheet <= maMaxPos.Sheet);
571cdf0e10cSrcweir     if( !bValid && bTrackOverflow )
572cdf0e10cSrcweir         mbTabOverflow |= (nSheet > maMaxPos.Sheet);  // do not warn for deleted refs (-1)
573cdf0e10cSrcweir     return bValid;
574cdf0e10cSrcweir }
575cdf0e10cSrcweir 
576cdf0e10cSrcweir // ----------------------------------------------------------------------------
577cdf0e10cSrcweir 
checkCellAddress(const CellAddress & rAddress,bool bTrackOverflow)578cdf0e10cSrcweir bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrackOverflow )
579cdf0e10cSrcweir {
580cdf0e10cSrcweir     return
581cdf0e10cSrcweir         checkTab( rAddress.Sheet, bTrackOverflow ) &&
582cdf0e10cSrcweir         checkCol( rAddress.Column, bTrackOverflow ) &&
583cdf0e10cSrcweir         checkRow( rAddress.Row, bTrackOverflow );
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
convertToCellAddressUnchecked(CellAddress & orAddress,const OUString & rString,sal_Int16 nSheet)586cdf0e10cSrcweir bool AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
587cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir     orAddress.Sheet = nSheet;
590cdf0e10cSrcweir     return parseOoxAddress2d( orAddress.Column, orAddress.Row, rString );
591cdf0e10cSrcweir }
592cdf0e10cSrcweir 
convertToCellAddress(CellAddress & orAddress,const OUString & rString,sal_Int16 nSheet,bool bTrackOverflow)593cdf0e10cSrcweir bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
594cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir     return
597cdf0e10cSrcweir         convertToCellAddressUnchecked( orAddress, rString, nSheet ) &&
598cdf0e10cSrcweir         checkCellAddress( orAddress, bTrackOverflow );
599cdf0e10cSrcweir }
600cdf0e10cSrcweir 
createValidCellAddress(const OUString & rString,sal_Int16 nSheet,bool bTrackOverflow)601cdf0e10cSrcweir CellAddress AddressConverter::createValidCellAddress(
602cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
603cdf0e10cSrcweir {
604cdf0e10cSrcweir     CellAddress aAddress;
605cdf0e10cSrcweir     if( !convertToCellAddress( aAddress, rString, nSheet, bTrackOverflow ) )
606cdf0e10cSrcweir     {
607cdf0e10cSrcweir         aAddress.Sheet  = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
608cdf0e10cSrcweir         aAddress.Column = ::std::min( aAddress.Column, maMaxPos.Column );
609cdf0e10cSrcweir         aAddress.Row    = ::std::min( aAddress.Row, maMaxPos.Row );
610cdf0e10cSrcweir     }
611cdf0e10cSrcweir     return aAddress;
612cdf0e10cSrcweir }
613cdf0e10cSrcweir 
convertToCellAddressUnchecked(CellAddress & orAddress,const BinAddress & rBinAddress,sal_Int16 nSheet)614cdf0e10cSrcweir void AddressConverter::convertToCellAddressUnchecked( CellAddress& orAddress,
615cdf0e10cSrcweir         const BinAddress& rBinAddress, sal_Int16 nSheet )
616cdf0e10cSrcweir {
617cdf0e10cSrcweir     orAddress.Sheet  = nSheet;
618cdf0e10cSrcweir     orAddress.Column = rBinAddress.mnCol;
619cdf0e10cSrcweir     orAddress.Row    = rBinAddress.mnRow;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir 
convertToCellAddress(CellAddress & orAddress,const BinAddress & rBinAddress,sal_Int16 nSheet,bool bTrackOverflow)622cdf0e10cSrcweir bool AddressConverter::convertToCellAddress( CellAddress& orAddress,
623cdf0e10cSrcweir         const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
624cdf0e10cSrcweir {
625cdf0e10cSrcweir     convertToCellAddressUnchecked( orAddress, rBinAddress, nSheet );
626cdf0e10cSrcweir     return checkCellAddress( orAddress, bTrackOverflow );
627cdf0e10cSrcweir }
628cdf0e10cSrcweir 
createValidCellAddress(const BinAddress & rBinAddress,sal_Int16 nSheet,bool bTrackOverflow)629cdf0e10cSrcweir CellAddress AddressConverter::createValidCellAddress(
630cdf0e10cSrcweir         const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow )
631cdf0e10cSrcweir {
632cdf0e10cSrcweir     CellAddress aAddress;
633cdf0e10cSrcweir     if( !convertToCellAddress( aAddress, rBinAddress, nSheet, bTrackOverflow ) )
634cdf0e10cSrcweir     {
635cdf0e10cSrcweir         aAddress.Sheet  = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet );
636cdf0e10cSrcweir         aAddress.Column = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnCol, 0, maMaxPos.Column );
637cdf0e10cSrcweir         aAddress.Row    = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnRow, 0, maMaxPos.Row );
638cdf0e10cSrcweir     }
639cdf0e10cSrcweir     return aAddress;
640cdf0e10cSrcweir }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir // ----------------------------------------------------------------------------
643cdf0e10cSrcweir 
checkCellRange(const CellRangeAddress & rRange,bool bAllowOverflow,bool bTrackOverflow)644cdf0e10cSrcweir bool AddressConverter::checkCellRange( const CellRangeAddress& rRange, bool bAllowOverflow, bool bTrackOverflow )
645cdf0e10cSrcweir {
646cdf0e10cSrcweir     return
647cdf0e10cSrcweir         (checkCol( rRange.EndColumn, bTrackOverflow ) || bAllowOverflow) &&     // bAllowOverflow after checkCol to track overflow!
648cdf0e10cSrcweir         (checkRow( rRange.EndRow, bTrackOverflow ) || bAllowOverflow) &&        // bAllowOverflow after checkRow to track overflow!
649cdf0e10cSrcweir         checkTab( rRange.Sheet, bTrackOverflow ) &&
650cdf0e10cSrcweir         checkCol( rRange.StartColumn, bTrackOverflow ) &&
651cdf0e10cSrcweir         checkRow( rRange.StartRow, bTrackOverflow );
652cdf0e10cSrcweir }
653cdf0e10cSrcweir 
validateCellRange(CellRangeAddress & orRange,bool bAllowOverflow,bool bTrackOverflow)654cdf0e10cSrcweir bool AddressConverter::validateCellRange( CellRangeAddress& orRange, bool bAllowOverflow, bool bTrackOverflow )
655cdf0e10cSrcweir {
656cdf0e10cSrcweir     if( orRange.StartColumn > orRange.EndColumn )
657cdf0e10cSrcweir         ::std::swap( orRange.StartColumn, orRange.EndColumn );
658cdf0e10cSrcweir     if( orRange.StartRow > orRange.EndRow )
659cdf0e10cSrcweir         ::std::swap( orRange.StartRow, orRange.EndRow );
660cdf0e10cSrcweir     if( !checkCellRange( orRange, bAllowOverflow, bTrackOverflow ) )
661cdf0e10cSrcweir         return false;
662cdf0e10cSrcweir     if( orRange.EndColumn > maMaxPos.Column )
663cdf0e10cSrcweir         orRange.EndColumn = maMaxPos.Column;
664cdf0e10cSrcweir     if( orRange.EndRow > maMaxPos.Row )
665cdf0e10cSrcweir         orRange.EndRow = maMaxPos.Row;
666cdf0e10cSrcweir     return true;
667cdf0e10cSrcweir }
668cdf0e10cSrcweir 
convertToCellRangeUnchecked(CellRangeAddress & orRange,const OUString & rString,sal_Int16 nSheet)669cdf0e10cSrcweir bool AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
670cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet )
671cdf0e10cSrcweir {
672cdf0e10cSrcweir     orRange.Sheet = nSheet;
673cdf0e10cSrcweir     return parseOoxRange2d( orRange.StartColumn, orRange.StartRow, orRange.EndColumn, orRange.EndRow, rString );
674cdf0e10cSrcweir }
675cdf0e10cSrcweir 
convertToCellRange(CellRangeAddress & orRange,const OUString & rString,sal_Int16 nSheet,bool bAllowOverflow,bool bTrackOverflow)676cdf0e10cSrcweir bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
677cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
678cdf0e10cSrcweir {
679cdf0e10cSrcweir     return
680cdf0e10cSrcweir         convertToCellRangeUnchecked( orRange, rString, nSheet ) &&
681cdf0e10cSrcweir         validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
682cdf0e10cSrcweir }
683cdf0e10cSrcweir 
convertToCellRangeUnchecked(CellRangeAddress & orRange,const BinRange & rBinRange,sal_Int16 nSheet)684cdf0e10cSrcweir void AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange,
685cdf0e10cSrcweir         const BinRange& rBinRange, sal_Int16 nSheet )
686cdf0e10cSrcweir {
687cdf0e10cSrcweir     orRange.Sheet       = nSheet;
688cdf0e10cSrcweir     orRange.StartColumn = rBinRange.maFirst.mnCol;
689cdf0e10cSrcweir     orRange.StartRow    = rBinRange.maFirst.mnRow;
690cdf0e10cSrcweir     orRange.EndColumn   = rBinRange.maLast.mnCol;
691cdf0e10cSrcweir     orRange.EndRow      = rBinRange.maLast.mnRow;
692cdf0e10cSrcweir }
693cdf0e10cSrcweir 
convertToCellRange(CellRangeAddress & orRange,const BinRange & rBinRange,sal_Int16 nSheet,bool bAllowOverflow,bool bTrackOverflow)694cdf0e10cSrcweir bool AddressConverter::convertToCellRange( CellRangeAddress& orRange,
695cdf0e10cSrcweir         const BinRange& rBinRange, sal_Int16 nSheet, bool bAllowOverflow, bool bTrackOverflow )
696cdf0e10cSrcweir {
697cdf0e10cSrcweir     convertToCellRangeUnchecked( orRange, rBinRange, nSheet );
698cdf0e10cSrcweir     return validateCellRange( orRange, bAllowOverflow, bTrackOverflow );
699cdf0e10cSrcweir }
700cdf0e10cSrcweir 
701cdf0e10cSrcweir // ----------------------------------------------------------------------------
702cdf0e10cSrcweir 
checkCellRangeList(const ApiCellRangeList & rRanges,bool bAllowOverflow,bool bTrackOverflow)703cdf0e10cSrcweir bool AddressConverter::checkCellRangeList( const ApiCellRangeList& rRanges, bool bAllowOverflow, bool bTrackOverflow )
704cdf0e10cSrcweir {
705cdf0e10cSrcweir     for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt )
706cdf0e10cSrcweir         if( !checkCellRange( *aIt, bAllowOverflow, bTrackOverflow ) )
707cdf0e10cSrcweir             return false;
708cdf0e10cSrcweir     return true;
709cdf0e10cSrcweir }
710cdf0e10cSrcweir 
validateCellRangeList(ApiCellRangeList & orRanges,bool bTrackOverflow)711cdf0e10cSrcweir void AddressConverter::validateCellRangeList( ApiCellRangeList& orRanges, bool bTrackOverflow )
712cdf0e10cSrcweir {
713cdf0e10cSrcweir     for( size_t nIndex = orRanges.size(); nIndex > 0; --nIndex )
714cdf0e10cSrcweir         if( !validateCellRange( orRanges[ nIndex - 1 ], true, bTrackOverflow ) )
715cdf0e10cSrcweir             orRanges.erase( orRanges.begin() + nIndex - 1 );
716cdf0e10cSrcweir }
717cdf0e10cSrcweir 
convertToCellRangeList(ApiCellRangeList & orRanges,const OUString & rString,sal_Int16 nSheet,bool bTrackOverflow)718cdf0e10cSrcweir void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
719cdf0e10cSrcweir         const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow )
720cdf0e10cSrcweir {
721cdf0e10cSrcweir     sal_Int32 nPos = 0;
722cdf0e10cSrcweir     sal_Int32 nLen = rString.getLength();
723cdf0e10cSrcweir     CellRangeAddress aRange;
724cdf0e10cSrcweir     while( (0 <= nPos) && (nPos < nLen) )
725cdf0e10cSrcweir     {
726cdf0e10cSrcweir         OUString aToken = rString.getToken( 0, ' ', nPos );
727cdf0e10cSrcweir         if( (aToken.getLength() > 0) && convertToCellRange( aRange, aToken, nSheet, true, bTrackOverflow ) )
728cdf0e10cSrcweir             orRanges.push_back( aRange );
729cdf0e10cSrcweir     }
730cdf0e10cSrcweir }
731cdf0e10cSrcweir 
convertToCellRangeList(ApiCellRangeList & orRanges,const BinRangeList & rBinRanges,sal_Int16 nSheet,bool bTrackOverflow)732cdf0e10cSrcweir void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges,
733cdf0e10cSrcweir         const BinRangeList& rBinRanges, sal_Int16 nSheet, bool bTrackOverflow )
734cdf0e10cSrcweir {
735cdf0e10cSrcweir     CellRangeAddress aRange;
736cdf0e10cSrcweir     for( BinRangeList::const_iterator aIt = rBinRanges.begin(), aEnd = rBinRanges.end(); aIt != aEnd; ++aIt )
737cdf0e10cSrcweir         if( convertToCellRange( aRange, *aIt, nSheet, true, bTrackOverflow ) )
738cdf0e10cSrcweir             orRanges.push_back( aRange );
739cdf0e10cSrcweir }
740cdf0e10cSrcweir 
741cdf0e10cSrcweir // private --------------------------------------------------------------------
742cdf0e10cSrcweir 
set(sal_Unicode cThisWorkbook,sal_Unicode cExternal,sal_Unicode cThisSheet,sal_Unicode cInternal,sal_Unicode cSameSheet)743cdf0e10cSrcweir void AddressConverter::ControlCharacters::set(
744cdf0e10cSrcweir         sal_Unicode cThisWorkbook, sal_Unicode cExternal,
745cdf0e10cSrcweir         sal_Unicode cThisSheet, sal_Unicode cInternal, sal_Unicode cSameSheet )
746cdf0e10cSrcweir {
747cdf0e10cSrcweir     mcThisWorkbook = cThisWorkbook;
748cdf0e10cSrcweir     mcExternal     = cExternal;
749cdf0e10cSrcweir     mcThisSheet    = cThisSheet;
750cdf0e10cSrcweir     mcInternal     = cInternal;
751cdf0e10cSrcweir     mcSameSheet    = cSameSheet;
752cdf0e10cSrcweir }
753cdf0e10cSrcweir 
initializeMaxPos(sal_Int16 nMaxXlsTab,sal_Int32 nMaxXlsCol,sal_Int32 nMaxXlsRow)754cdf0e10cSrcweir void AddressConverter::initializeMaxPos(
755cdf0e10cSrcweir         sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow )
756cdf0e10cSrcweir {
757cdf0e10cSrcweir     maMaxXlsPos.Sheet  = nMaxXlsTab;
758cdf0e10cSrcweir     maMaxXlsPos.Column = nMaxXlsCol;
759cdf0e10cSrcweir     maMaxXlsPos.Row    = nMaxXlsRow;
760cdf0e10cSrcweir 
761cdf0e10cSrcweir     // maximum cell position in Calc
762cdf0e10cSrcweir     try
763cdf0e10cSrcweir     {
764cdf0e10cSrcweir         Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW );
765cdf0e10cSrcweir         Reference< XCellRangeAddressable > xAddressable( xSheetsIA->getByIndex( 0 ), UNO_QUERY_THROW );
766cdf0e10cSrcweir         CellRangeAddress aRange = xAddressable->getRangeAddress();
767cdf0e10cSrcweir         maMaxApiPos = CellAddress( API_MAXTAB, aRange.EndColumn, aRange.EndRow );
768cdf0e10cSrcweir         maMaxPos = getBaseFilter().isImportFilter() ? maMaxApiPos : maMaxXlsPos;
769cdf0e10cSrcweir     }
770cdf0e10cSrcweir     catch( Exception& )
771cdf0e10cSrcweir     {
772cdf0e10cSrcweir         OSL_ENSURE( false, "AddressConverter::AddressConverter - cannot get sheet limits" );
773cdf0e10cSrcweir     }
774cdf0e10cSrcweir }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir // ============================================================================
777cdf0e10cSrcweir 
778cdf0e10cSrcweir } // namespace xls
779cdf0e10cSrcweir } // namespace oox
780