1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 #include "namebuff.hxx"
28
29 #include <tools/urlobj.hxx>
30 #include <string.h>
31
32 #include "rangenam.hxx"
33 #include "document.hxx"
34 #include "compiler.hxx"
35 #include "scextopt.hxx"
36
37 #include "root.hxx"
38 #include "tokstack.hxx"
39 #include "xltools.hxx"
40 #include "xiroot.hxx"
41
42
MakeHashCode(const String & r)43 sal_uInt32 StringHashEntry::MakeHashCode( const String& r )
44 {
45 register sal_uInt32 n = 0;
46 const sal_Unicode* pAkt = r.GetBuffer();
47 register sal_Unicode cAkt = *pAkt;
48
49 while( cAkt )
50 {
51 n *= 70;
52 n += ( sal_uInt32 ) cAkt;
53 pAkt++;
54 cAkt = *pAkt;
55 }
56
57 return n;
58 }
59
60
61
62
~NameBuffer()63 NameBuffer::~NameBuffer()
64 {
65 register StringHashEntry* pDel = ( StringHashEntry* ) List::First();
66 while( pDel )
67 {
68 delete pDel;
69 pDel = ( StringHashEntry* ) List::Next();
70 }
71 }
72
73
74 //void NameBuffer::operator <<( const SpString &rNewString )
operator <<(const String & rNewString)75 void NameBuffer::operator <<( const String &rNewString )
76 {
77 DBG_ASSERT( Count() + nBase < 0xFFFF,
78 "*NameBuffer::GetLastIndex(): Ich hab' die Nase voll!" );
79
80 List::Insert( new StringHashEntry( rNewString ), LIST_APPEND );
81 }
82
83
84 #ifdef DBG_UTIL
85 sal_uInt16 nShrCnt;
86 #endif
87
88
operator ()(const ScAddress & addr) const89 size_t ShrfmlaBuffer::ScAddressHashFunc::operator() (const ScAddress &addr) const
90 {
91 // Use something simple, it is just a hash.
92 return static_cast< sal_uInt16 >( addr.Row() ) | (static_cast< sal_uInt8 >( addr.Col() ) << 16);
93 }
94
95 const size_t nBase = 16384; // Range~ und Shared~ Dingens mit jeweils der Haelfte Ids
ShrfmlaBuffer(RootData * pRD)96 ShrfmlaBuffer::ShrfmlaBuffer( RootData* pRD ) :
97 ExcRoot( pRD ),
98 mnCurrIdx (nBase)
99 {
100 #ifdef DBG_UTIL
101 nShrCnt = 0;
102 #endif
103 }
104
~ShrfmlaBuffer()105 ShrfmlaBuffer::~ShrfmlaBuffer()
106 {
107 }
108
Clear()109 void ShrfmlaBuffer::Clear()
110 {
111 index_hash.clear();
112 // do not clear index_list, index calculation depends on complete list size...
113 // do not change mnCurrIdx
114 }
115
Store(const ScRange & rRange,const ScTokenArray & rToken)116 void ShrfmlaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken )
117 {
118 String aName( CreateName( rRange.aStart ) );
119
120 DBG_ASSERT( mnCurrIdx <= 0xFFFF, "*ShrfmlaBuffer::Store(): Gleich wird mir schlecht...!" );
121
122 ScRangeData* pData = new ScRangeData( pExcRoot->pIR->GetDocPtr(), aName, rToken, rRange.aStart, RT_SHARED );
123 const ScAddress& rMaxPos = pExcRoot->pIR->GetMaxPos();
124 pData->SetMaxCol(rMaxPos.Col());
125 pData->SetMaxRow(rMaxPos.Row());
126 pData->SetIndex( static_cast< sal_uInt16 >( mnCurrIdx ) );
127 pExcRoot->pIR->GetNamedRanges().Insert( pData );
128 index_hash[rRange.aStart] = static_cast< sal_uInt16 >( mnCurrIdx );
129 index_list.push_front (rRange);
130 ++mnCurrIdx;
131 }
132
133
Find(const ScAddress & aAddr) const134 sal_uInt16 ShrfmlaBuffer::Find( const ScAddress & aAddr ) const
135 {
136 ShrfmlaHash::const_iterator hash = index_hash.find (aAddr);
137 if (hash != index_hash.end())
138 return hash->second;
139
140 // It was not hashed on the top left corner ? do a brute force search
141 unsigned int ind = nBase;
142 for (ShrfmlaList::const_iterator ptr = index_list.end(); ptr != index_list.begin() ; ind++)
143 if ((--ptr)->In (aAddr))
144 return static_cast< sal_uInt16 >( ind );
145 return static_cast< sal_uInt16 >( mnCurrIdx );
146 }
147
148
149 #define SHRFMLA_BASENAME "SHARED_FORMULA_"
150
CreateName(const ScRange & r)151 String ShrfmlaBuffer::CreateName( const ScRange& r )
152 {
153 String aName( RTL_CONSTASCII_USTRINGPARAM( SHRFMLA_BASENAME ) );
154 aName += String::CreateFromInt32( r.aStart.Col() );
155 aName.Append( '_' );
156 aName += String::CreateFromInt32( r.aStart.Row() );
157 aName.Append( '_' );
158 aName += String::CreateFromInt32( r.aEnd.Col() );
159 aName.Append( '_' );
160 aName += String::CreateFromInt32( r.aEnd.Row() );
161 aName.Append( '_' );
162 aName += String::CreateFromInt32( r.aStart.Tab() );
163
164 return aName;
165 }
166
167
~ExtSheetBuffer()168 ExtSheetBuffer::~ExtSheetBuffer()
169 {
170 Cont *pAkt = ( Cont * ) List::First();
171 while( pAkt )
172 {
173 delete pAkt;
174 pAkt = ( Cont * ) List::Next();
175 }
176 }
177
178
Add(const String & rFPAN,const String & rTN,const sal_Bool bSWB)179 sal_Int16 ExtSheetBuffer::Add( const String& rFPAN, const String& rTN, const sal_Bool bSWB )
180 {
181 List::Insert( new Cont( rFPAN, rTN, bSWB ), LIST_APPEND );
182 // return 1-based index of EXTERNSHEET
183 return static_cast< sal_Int16 >( List::Count() );
184 }
185
186
GetScTabIndex(sal_uInt16 nExcIndex,sal_uInt16 & rScIndex)187 sal_Bool ExtSheetBuffer::GetScTabIndex( sal_uInt16 nExcIndex, sal_uInt16& rScIndex )
188 {
189 DBG_ASSERT( nExcIndex,
190 "*ExtSheetBuffer::GetScTabIndex(): Sheet-Index == 0!" );
191
192 nExcIndex--;
193 Cont* pCur = ( Cont * ) List::GetObject( nExcIndex );
194 sal_uInt16& rTabNum = pCur->nTabNum;
195
196 if( pCur )
197 {
198 if( rTabNum < 0xFFFD )
199 {
200 rScIndex = rTabNum;
201 return sal_True;
202 }
203
204 if( rTabNum == 0xFFFF )
205 {// neue Tabelle erzeugen
206 SCTAB nNewTabNum;
207 if( pCur->bSWB )
208 {// Tabelle ist im selben Workbook!
209 if( pExcRoot->pIR->GetDoc().GetTable( pCur->aTab, nNewTabNum ) )
210 {
211 rScIndex = rTabNum = static_cast<sal_uInt16>(nNewTabNum);
212 return sal_True;
213 }
214 else
215 rTabNum = 0xFFFD;
216 }
217 else if( pExcRoot->pIR->GetDocShell() )
218 {// Tabelle ist 'echt' extern
219 if( pExcRoot->pIR->GetExtDocOptions().GetDocSettings().mnLinkCnt == 0 )
220 {
221 String aURL( ScGlobal::GetAbsDocName( pCur->aFile,
222 pExcRoot->pIR->GetDocShell() ) );
223 String aTabName( ScGlobal::GetDocTabName( aURL, pCur->aTab ) );
224 if( pExcRoot->pIR->GetDoc().LinkExternalTab( nNewTabNum, aTabName, aURL, pCur->aTab ) )
225 {
226 rScIndex = rTabNum = static_cast<sal_uInt16>(nNewTabNum);
227 return sal_True;
228 }
229 else
230 rTabNum = 0xFFFE; // Tabelle einmal nicht angelegt -> wird
231 // wohl auch nicht mehr gehen...
232 }
233 else
234 rTabNum = 0xFFFE;
235
236 }
237 }
238 }
239
240 return sal_False;
241 }
242
243
IsLink(const sal_uInt16 nExcIndex) const244 sal_Bool ExtSheetBuffer::IsLink( const sal_uInt16 nExcIndex ) const
245 {
246 DBG_ASSERT( nExcIndex > 0, "*ExtSheetBuffer::IsLink(): Index muss >0 sein!" );
247 Cont* pRet = ( Cont * ) List::GetObject( nExcIndex - 1 );
248
249 if( pRet )
250 return pRet->bLink;
251 else
252 return sal_False;
253 }
254
255
GetLink(const sal_uInt16 nExcIndex,String & rAppl,String & rDoc) const256 sal_Bool ExtSheetBuffer::GetLink( const sal_uInt16 nExcIndex, String& rAppl, String& rDoc ) const
257 {
258 DBG_ASSERT( nExcIndex > 0, "*ExtSheetBuffer::GetLink(): Index muss >0 sein!" );
259 Cont* pRet = ( Cont * ) List::GetObject( nExcIndex - 1 );
260
261 if( pRet )
262 {
263 rAppl = pRet->aFile;
264 rDoc = pRet->aTab;
265 return sal_True;
266 }
267 else
268 return sal_False;
269 }
270
271
Reset(void)272 void ExtSheetBuffer::Reset( void )
273 {
274 Cont *pAkt = ( Cont * ) List::First();
275 while( pAkt )
276 {
277 delete pAkt;
278 pAkt = ( Cont * ) List::Next();
279 }
280
281 List::Clear();
282 }
283
284
285
286
IsDDE(void) const287 sal_Bool ExtName::IsDDE( void ) const
288 {
289 return ( nFlags & 0x0001 ) != 0;
290 }
291
292
IsOLE(void) const293 sal_Bool ExtName::IsOLE( void ) const
294 {
295 return ( nFlags & 0x0002 ) != 0;
296 }
297
298
ExtNameBuff(const XclImpRoot & rRoot)299 ExtNameBuff::ExtNameBuff( const XclImpRoot& rRoot ) :
300 XclImpRoot( rRoot )
301 {
302 }
303
304
AddDDE(const String & rName,sal_Int16 nRefIdx)305 void ExtNameBuff::AddDDE( const String& rName, sal_Int16 nRefIdx )
306 {
307 ExtName aNew( rName, 0x0001 );
308 maExtNames[ nRefIdx ].push_back( aNew );
309 }
310
311
AddOLE(const String & rName,sal_Int16 nRefIdx,sal_uInt32 nStorageId)312 void ExtNameBuff::AddOLE( const String& rName, sal_Int16 nRefIdx, sal_uInt32 nStorageId )
313 {
314 ExtName aNew( rName, 0x0002 );
315 aNew.nStorageId = nStorageId;
316 maExtNames[ nRefIdx ].push_back( aNew );
317 }
318
319
AddName(const String & rName,sal_Int16 nRefIdx)320 void ExtNameBuff::AddName( const String& rName, sal_Int16 nRefIdx )
321 {
322 ExtName aNew( GetScAddInName( rName ), 0x0004 );
323 maExtNames[ nRefIdx ].push_back( aNew );
324 }
325
326
GetNameByIndex(sal_Int16 nRefIdx,sal_uInt16 nNameIdx) const327 const ExtName* ExtNameBuff::GetNameByIndex( sal_Int16 nRefIdx, sal_uInt16 nNameIdx ) const
328 {
329 DBG_ASSERT( nNameIdx > 0, "ExtNameBuff::GetNameByIndex() - invalid name index" );
330 ExtNameMap::const_iterator aIt = maExtNames.find( nRefIdx );
331 return ((aIt != maExtNames.end()) && (0 < nNameIdx) && (nNameIdx <= aIt->second.size())) ? &aIt->second[ nNameIdx - 1 ] : 0;
332 }
333
334
Reset(void)335 void ExtNameBuff::Reset( void )
336 {
337 maExtNames.clear();
338 }
339
340
341