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"
28 // *** Implementation ***
30 XclImpName::TokenStrmData::TokenStrmData( XclImpStream
& rStrm
) :
31 mrStrm(rStrm
), mnStrmPos(0), mnStrmSize(0) {}
33 XclImpName::XclImpName( XclImpStream
& rStrm
, sal_uInt16 nXclNameIdx
) :
34 XclImpRoot( rStrm
.GetRoot() ),
36 mcBuiltIn( EXC_BUILTIN_UNKNOWN
),
38 meNameType( RT_NAME
),
39 mnXclTab( EXC_NAME_GLOBAL
),
40 mnNameIndex( nXclNameIdx
),
45 ExcelToSc
& rFmlaConv
= GetOldFmlaConverter();
47 // 1) *** read data from stream *** ---------------------------------------
49 sal_uInt16 nFlags
= 0, nFmlaSize
= 0, nExtSheet
= EXC_NAME_GLOBAL
;
50 sal_uInt8 nNameLen
= 0;
56 sal_uInt8 nFlagsBiff2
;
57 nFlagsBiff2
= rStrm
.ReaduInt8();
59 rStrm
.Ignore( 1 ); //nShortCut
60 nNameLen
= rStrm
.ReaduInt8();
61 nFmlaSize
= rStrm
.ReaduInt8();
62 ::set_flag( nFlags
, EXC_NAME_FUNC
, ::get_flag( nFlagsBiff2
, EXC_NAME2_FUNC
) );
69 nFlags
= rStrm
.ReaduInt16();
70 rStrm
.Ignore( 1 ); //nShortCut
71 nNameLen
= rStrm
.ReaduInt8();
72 nFmlaSize
= rStrm
.ReaduInt16();
79 nFlags
= rStrm
.ReaduInt16();
80 rStrm
.Ignore( 1 ); //nShortCut
81 nNameLen
= rStrm
.ReaduInt8();
82 nFmlaSize
= rStrm
.ReaduInt16();
83 nExtSheet
= rStrm
.ReaduInt16();
84 mnXclTab
= rStrm
.ReaduInt16();
89 default: DBG_ERROR_BIFF();
92 if( GetBiff() <= EXC_BIFF5
)
93 maXclName
= rStrm
.ReadRawByteString( nNameLen
);
95 maXclName
= rStrm
.ReadUniString( nNameLen
);
97 // 2) *** convert sheet index and name *** --------------------------------
100 bool bFunction
= ::get_flag( nFlags
, EXC_NAME_FUNC
);
101 mbVBName
= ::get_flag( nFlags
, EXC_NAME_VB
);
102 mbMacro
= ::get_flag( nFlags
, EXC_NAME_PROC
);
104 // get built-in name, or convert characters invalid in Calc
105 bool bBuiltIn
= ::get_flag( nFlags
, EXC_NAME_BUILTIN
);
107 // special case for BIFF5 filter range - name appears as plain text without built-in flag
108 if( (GetBiff() == EXC_BIFF5
) && (maXclName
== XclTools::GetXclBuiltInDefName(EXC_BUILTIN_FILTERDATABASE
)) )
111 maXclName
= OUStringLiteral1
<EXC_BUILTIN_FILTERDATABASE
>();
114 // convert Excel name to Calc name
118 maScName
= maXclName
;
123 if( !maXclName
.isEmpty() )
124 mcBuiltIn
= maXclName
[0];
125 if( mcBuiltIn
== '?' ) // NUL character is imported as '?'
127 maScName
= XclTools::GetBuiltInDefName( mcBuiltIn
);
132 maScName
= ScfTools::ConvertToScDefinedName( maXclName
);
135 // add index for local names
136 if( mnXclTab
!= EXC_NAME_GLOBAL
)
138 sal_uInt16 nUsedTab
= (GetBiff() == EXC_BIFF8
) ? mnXclTab
: nExtSheet
;
139 // TODO: may not work for BIFF5, handle skipped sheets (all BIFF)
140 mnScTab
= static_cast< SCTAB
>( nUsedTab
- 1 );
143 // 3) *** convert the name definition formula *** -------------------------
146 const ScTokenArray
* pTokArr
= 0; // pointer to token array, owned by rFmlaConv
148 if( ::get_flag( nFlags
, EXC_NAME_BIG
) )
150 // special, unsupported name
151 rFmlaConv
.GetDummy( pTokArr
);
155 SCsTAB
const nLocalTab
= (mnXclTab
== EXC_NAME_GLOBAL
) ? SCTAB_MAX
: (mnXclTab
- 1);
157 // --- print ranges or title ranges ---
158 rStrm
.PushPosition();
161 case EXC_BUILTIN_PRINTAREA
:
162 if( rFmlaConv
.Convert( GetPrintAreaBuffer(), rStrm
, nFmlaSize
, nLocalTab
, FT_RangeName
) == ConvOK
)
163 meNameType
|= RT_PRINTAREA
;
165 case EXC_BUILTIN_PRINTTITLES
:
166 if( rFmlaConv
.Convert( GetTitleAreaBuffer(), rStrm
, nFmlaSize
, nLocalTab
, FT_RangeName
) == ConvOK
)
167 meNameType
|= RT_COLHEADER
| RT_ROWHEADER
;
172 // --- name formula ---
173 // JEG : double check this. It is clearly false for normal names
174 // but some of the builtins (sheettitle?) might be able to handle arrays
175 rFmlaConv
.Convert( pTokArr
, rStrm
, nFmlaSize
, false, FT_RangeName
);
177 // --- auto or advanced filter ---
178 if( (GetBiff() == EXC_BIFF8
) && pTokArr
&& bBuiltIn
)
181 if (pTokArr
->IsReference(aRange
, ScAddress()))
185 case EXC_BUILTIN_FILTERDATABASE
:
186 GetFilterManager().Insert( &GetOldRoot(), aRange
);
188 case EXC_BUILTIN_CRITERIA
:
189 GetFilterManager().AddAdvancedRange( aRange
);
190 meNameType
|= RT_CRITERIA
;
192 case EXC_BUILTIN_EXTRACT
:
193 if (pTokArr
->IsValidReference(aRange
, ScAddress()))
194 GetFilterManager().AddExtractPos( aRange
);
200 else if( nFmlaSize
> 0 )
202 // Regular defined name. We need to convert the tokens after all the
203 // names have been registered (for cross-referenced names).
204 mpTokensData
.reset(new TokenStrmData(rStrm
));
205 mpTokensData
->mnStrmPos
= rStrm
.GetSvStreamPos();
206 rStrm
.StorePosition(mpTokensData
->maStrmPos
);
207 mpTokensData
->mnStrmSize
= nFmlaSize
;
210 if (pTokArr
&& !bFunction
&& !mbVBName
)
214 void XclImpName::ConvertTokens()
219 ExcelToSc
& rFmlaConv
= GetOldFmlaConverter();
221 const ScTokenArray
* pArray
= NULL
;
223 XclImpStreamPos aOldPos
;
224 XclImpStream
& rStrm
= mpTokensData
->mrStrm
;
225 rStrm
.StorePosition(aOldPos
);
226 rStrm
.RestorePosition(mpTokensData
->maStrmPos
);
227 rFmlaConv
.Convert(pArray
, rStrm
, mpTokensData
->mnStrmSize
, true, FT_RangeName
);
228 rStrm
.RestorePosition(aOldPos
);
233 mpTokensData
.reset();
236 void XclImpName::InsertName(const ScTokenArray
* pArray
)
238 // create the Calc name data
239 ScRangeData
* pData
= new ScRangeData(GetDocPtr(), maScName
, *pArray
, ScAddress(), meNameType
);
240 pData
->GuessPosition(); // calculate base position for relative refs
241 pData
->SetIndex( mnNameIndex
); // used as unique identifier in formulas
242 if (mnXclTab
== EXC_NAME_GLOBAL
)
244 if (!GetDoc().GetRangeName()->insert(pData
))
249 ScRangeName
* pLocalNames
= GetDoc().GetRangeName(mnScTab
);
252 if (!pLocalNames
->insert(pData
))
256 if (GetBiff() == EXC_BIFF8
&& pData
)
259 // discard deleted ranges ( for the moment at least )
260 if ( pData
->IsValidReference( aRange
) )
262 GetExtDocOptions().GetOrCreateTabSettings( mnXclTab
);
267 mpScData
= pData
; // cache for later use
270 XclImpNameManager::XclImpNameManager( const XclImpRoot
& rRoot
) :
275 void XclImpNameManager::ReadName( XclImpStream
& rStrm
)
277 sal_uLong nCount
= maNameList
.size();
278 if( nCount
< 0xFFFF )
279 maNameList
.push_back( new XclImpName( rStrm
, static_cast< sal_uInt16
>( nCount
+ 1 ) ) );
282 const XclImpName
* XclImpNameManager::FindName( const OUString
& rXclName
, SCTAB nScTab
) const
284 const XclImpName
* pGlobalName
= 0; // a found global name
285 const XclImpName
* pLocalName
= 0; // a found local name
286 for( XclImpNameList::const_iterator itName
= maNameList
.begin(); itName
!= maNameList
.end() && !pLocalName
; ++itName
)
288 if( itName
->GetXclName() == rXclName
)
290 if( itName
->GetScTab() == nScTab
)
291 pLocalName
= &(*itName
);
292 else if( itName
->IsGlobal() )
293 pGlobalName
= &(*itName
);
296 return pLocalName
? pLocalName
: pGlobalName
;
299 const XclImpName
* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx
) const
301 OSL_ENSURE( nXclNameIdx
> 0, "XclImpNameManager::GetName - index must be >0" );
302 return ( nXclNameIdx
<= 0 || nXclNameIdx
> maNameList
.size() ) ? NULL
: &(maNameList
.at( nXclNameIdx
- 1 ));
305 void XclImpNameManager::ConvertAllTokens()
307 XclImpNameList::iterator it
= maNameList
.begin(), itEnd
= maNameList
.end();
308 for (; it
!= itEnd
; ++it
)
312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */