xref: /AOO41X/main/sc/source/filter/excel/namebuff.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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