1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "rangenam.hxx"
22 #include "xistream.hxx"
23 #include "excform.hxx"
24 #include "excimp8.hxx"
25 #include "scextopt.hxx"
26 #include "document.hxx"
27 #include <o3tl/make_unique.hxx>
29 // *** Implementation ***
31 XclImpName::TokenStrmData::TokenStrmData( XclImpStream
& rStrm
) :
32 mrStrm(rStrm
), mnStrmPos(0), mnStrmSize(0) {}
34 XclImpName::XclImpName( XclImpStream
& rStrm
, sal_uInt16 nXclNameIdx
) :
35 XclImpRoot( rStrm
.GetRoot() ),
37 mcBuiltIn( EXC_BUILTIN_UNKNOWN
),
39 meNameType( ScRangeData::Type::Name
),
40 mnXclTab( EXC_NAME_GLOBAL
),
41 mnNameIndex( nXclNameIdx
),
44 mpTokensData( nullptr )
46 ExcelToSc
& rFmlaConv
= GetOldFmlaConverter();
48 // 1) *** read data from stream *** ---------------------------------------
50 sal_uInt16 nFlags
= 0, nFmlaSize
= 0, nExtSheet
= EXC_NAME_GLOBAL
;
51 sal_uInt8 nNameLen
= 0;
57 sal_uInt8 nFlagsBiff2
;
58 nFlagsBiff2
= rStrm
.ReaduInt8();
60 rStrm
.Ignore( 1 ); //nShortCut
61 nNameLen
= rStrm
.ReaduInt8();
62 nFmlaSize
= rStrm
.ReaduInt8();
63 ::set_flag( nFlags
, EXC_NAME_FUNC
, ::get_flag( nFlagsBiff2
, EXC_NAME2_FUNC
) );
70 nFlags
= rStrm
.ReaduInt16();
71 rStrm
.Ignore( 1 ); //nShortCut
72 nNameLen
= rStrm
.ReaduInt8();
73 nFmlaSize
= rStrm
.ReaduInt16();
80 nFlags
= rStrm
.ReaduInt16();
81 rStrm
.Ignore( 1 ); //nShortCut
82 nNameLen
= rStrm
.ReaduInt8();
83 nFmlaSize
= rStrm
.ReaduInt16();
84 nExtSheet
= rStrm
.ReaduInt16();
85 mnXclTab
= rStrm
.ReaduInt16();
90 default: DBG_ERROR_BIFF();
93 if( GetBiff() <= EXC_BIFF5
)
94 maXclName
= rStrm
.ReadRawByteString( nNameLen
);
96 maXclName
= rStrm
.ReadUniString( nNameLen
);
98 // 2) *** convert sheet index and name *** --------------------------------
101 bool bFunction
= ::get_flag( nFlags
, EXC_NAME_FUNC
);
102 mbVBName
= ::get_flag( nFlags
, EXC_NAME_VB
);
103 mbMacro
= ::get_flag( nFlags
, EXC_NAME_PROC
);
105 // get built-in name, or convert characters invalid in Calc
106 bool bBuiltIn
= ::get_flag( nFlags
, EXC_NAME_BUILTIN
);
108 // special case for BIFF5 filter range - name appears as plain text without built-in flag
109 if( (GetBiff() == EXC_BIFF5
) && (maXclName
== XclTools::GetXclBuiltInDefName(EXC_BUILTIN_FILTERDATABASE
)) )
112 maXclName
= OUStringLiteral1
<EXC_BUILTIN_FILTERDATABASE
>();
115 // convert Excel name to Calc name
119 maScName
= maXclName
;
124 if( !maXclName
.isEmpty() )
125 mcBuiltIn
= maXclName
[0];
126 if( mcBuiltIn
== '?' ) // NUL character is imported as '?'
128 maScName
= XclTools::GetBuiltInDefName( mcBuiltIn
);
133 maScName
= ScfTools::ConvertToScDefinedName( maXclName
);
136 // add index for local names
137 if( mnXclTab
!= EXC_NAME_GLOBAL
)
139 sal_uInt16 nUsedTab
= (GetBiff() == EXC_BIFF8
) ? mnXclTab
: nExtSheet
;
140 // TODO: may not work for BIFF5, handle skipped sheets (all BIFF)
141 mnScTab
= static_cast< SCTAB
>( nUsedTab
- 1 );
144 // 3) *** convert the name definition formula *** -------------------------
147 const ScTokenArray
* pTokArr
= nullptr; // pointer to token array, owned by rFmlaConv
149 if( ::get_flag( nFlags
, EXC_NAME_BIG
) )
151 // special, unsupported name
152 rFmlaConv
.GetDummy( pTokArr
);
156 SCsTAB
const nLocalTab
= (mnXclTab
== EXC_NAME_GLOBAL
) ? SCTAB_MAX
: (mnXclTab
- 1);
158 // --- print ranges or title ranges ---
159 rStrm
.PushPosition();
162 case EXC_BUILTIN_PRINTAREA
:
163 if( rFmlaConv
.Convert( GetPrintAreaBuffer(), rStrm
, nFmlaSize
, nLocalTab
, FT_RangeName
) == ConvOK
)
164 meNameType
|= ScRangeData::Type::PrintArea
;
166 case EXC_BUILTIN_PRINTTITLES
:
167 if( rFmlaConv
.Convert( GetTitleAreaBuffer(), rStrm
, nFmlaSize
, nLocalTab
, FT_RangeName
) == ConvOK
)
168 meNameType
|= ScRangeData::Type::ColHeader
| ScRangeData::Type::RowHeader
;
173 // --- name formula ---
174 // JEG : double check this. It is clearly false for normal names
175 // but some of the builtins (sheettitle?) might be able to handle arrays
176 rFmlaConv
.Convert( pTokArr
, rStrm
, nFmlaSize
, false, FT_RangeName
);
178 // --- auto or advanced filter ---
179 if( (GetBiff() == EXC_BIFF8
) && pTokArr
&& bBuiltIn
)
182 if (pTokArr
->IsReference(aRange
, ScAddress()))
186 case EXC_BUILTIN_FILTERDATABASE
:
187 GetFilterManager().Insert( &GetOldRoot(), aRange
);
189 case EXC_BUILTIN_CRITERIA
:
190 GetFilterManager().AddAdvancedRange( aRange
);
191 meNameType
|= ScRangeData::Type::Criteria
;
193 case EXC_BUILTIN_EXTRACT
:
194 if (pTokArr
->IsValidReference(aRange
, ScAddress()))
195 GetFilterManager().AddExtractPos( aRange
);
201 else if( nFmlaSize
> 0 )
203 // Regular defined name. We need to convert the tokens after all the
204 // names have been registered (for cross-referenced names).
205 mpTokensData
.reset(new TokenStrmData(rStrm
));
206 mpTokensData
->mnStrmPos
= rStrm
.GetSvStreamPos();
207 rStrm
.StorePosition(mpTokensData
->maStrmPos
);
208 mpTokensData
->mnStrmSize
= nFmlaSize
;
211 if (pTokArr
&& !bFunction
&& !mbVBName
)
215 void XclImpName::ConvertTokens()
220 ExcelToSc
& rFmlaConv
= GetOldFmlaConverter();
222 const ScTokenArray
* pArray
= nullptr;
224 XclImpStreamPos aOldPos
;
225 XclImpStream
& rStrm
= mpTokensData
->mrStrm
;
226 rStrm
.StorePosition(aOldPos
);
227 rStrm
.RestorePosition(mpTokensData
->maStrmPos
);
228 rFmlaConv
.Convert(pArray
, rStrm
, mpTokensData
->mnStrmSize
, true, FT_RangeName
);
229 rStrm
.RestorePosition(aOldPos
);
234 mpTokensData
.reset();
237 void XclImpName::InsertName(const ScTokenArray
* pArray
)
239 // create the Calc name data
240 ScRangeData
* pData
= new ScRangeData(&GetDocRef(), maScName
, *pArray
, ScAddress(), meNameType
);
241 pData
->GuessPosition(); // calculate base position for relative refs
242 pData
->SetIndex( mnNameIndex
); // used as unique identifier in formulas
243 if (mnXclTab
== EXC_NAME_GLOBAL
)
245 if (!GetDoc().GetRangeName()->insert(pData
))
250 ScRangeName
* pLocalNames
= GetDoc().GetRangeName(mnScTab
);
253 if (!pLocalNames
->insert(pData
))
257 if (GetBiff() == EXC_BIFF8
&& pData
)
260 // discard deleted ranges ( for the moment at least )
261 if ( pData
->IsValidReference( aRange
) )
263 GetExtDocOptions().GetOrCreateTabSettings( mnXclTab
);
268 mpScData
= pData
; // cache for later use
271 XclImpNameManager::XclImpNameManager( const XclImpRoot
& rRoot
) :
276 void XclImpNameManager::ReadName( XclImpStream
& rStrm
)
278 sal_uLong nCount
= maNameList
.size();
279 if( nCount
< 0xFFFF )
280 maNameList
.push_back( o3tl::make_unique
<XclImpName
>( rStrm
, static_cast< sal_uInt16
>( nCount
+ 1 ) ) );
283 const XclImpName
* XclImpNameManager::FindName( const OUString
& rXclName
, SCTAB nScTab
) const
285 const XclImpName
* pGlobalName
= nullptr; // a found global name
286 const XclImpName
* pLocalName
= nullptr; // a found local name
287 for( XclImpNameList::const_iterator itName
= maNameList
.begin(); itName
!= maNameList
.end() && !pLocalName
; ++itName
)
289 if( (*itName
)->GetXclName() == rXclName
)
291 if( (*itName
)->GetScTab() == nScTab
)
292 pLocalName
= itName
->get();
293 else if( (*itName
)->IsGlobal() )
294 pGlobalName
= itName
->get();
297 return pLocalName
? pLocalName
: pGlobalName
;
300 const XclImpName
* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx
) const
302 OSL_ENSURE( nXclNameIdx
> 0, "XclImpNameManager::GetName - index must be >0" );
303 return ( nXclNameIdx
<= 0 || nXclNameIdx
> maNameList
.size() ) ? nullptr : maNameList
.at( nXclNameIdx
- 1 ).get();
306 void XclImpNameManager::ConvertAllTokens()
308 XclImpNameList::iterator it
= maNameList
.begin(), itEnd
= maNameList
.end();
309 for (; it
!= itEnd
; ++it
)
310 (*it
)->ConvertTokens();
313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */