Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / tokstack.cxx
blobde64bcef7a7560af2f09444768f80bb02672046b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <tokstack.hxx>
21 #include <scmatrix.hxx>
23 #include <svl/sharedstringpool.hxx>
24 #include <sal/log.hxx>
25 #include <osl/diagnose.h>
27 #include <algorithm>
28 #include <string.h>
30 const sal_uInt16 TokenPool::nScTokenOff = 8192;
32 TokenStack::TokenStack( )
33 : pStack( new TokenId[ nSize ] )
35 Reset();
38 TokenStack::~TokenStack()
42 // !ATTENTION!": to the outside the numbering starts with 1!
43 // !ATTENTION!": SC-Token are stored with an offset nScTokenOff
44 // -> to distinguish from other tokens
46 TokenPool::TokenPool( svl::SharedStringPool& rSPool ) :
47 mrStringPool(rSPool)
49 // pool for Id-sequences
50 nP_Id = 256;
51 pP_Id.reset( new sal_uInt16[ nP_Id ] );
53 // pool for Ids
54 nElement = 32;
55 pElement.reset( new sal_uInt16[ nElement ] );
56 pType.reset( new E_TYPE[ nElement ] );
57 pSize.reset( new sal_uInt16[ nElement ] );
58 nP_IdLast = 0;
60 nP_Matrix = 16;
61 ppP_Matrix.reset( new ScMatrix*[ nP_Matrix ] );
62 memset( ppP_Matrix.get(), 0, sizeof( ScMatrix* ) * nP_Matrix );
64 Reset();
67 TokenPool::~TokenPool()
69 ClearMatrix();
72 /** Returns the new number of elements, or 0 if overflow. */
73 static sal_uInt16 lcl_canGrow( sal_uInt16 nOld )
75 if (!nOld)
76 return 1;
77 if (nOld == SAL_MAX_UINT16)
78 return 0;
79 sal_uInt32 nNew = ::std::max( static_cast<sal_uInt32>(nOld) * 2,
80 static_cast<sal_uInt32>(nOld) + 1);
81 if (nNew > SAL_MAX_UINT16)
82 nNew = SAL_MAX_UINT16;
83 if (nNew - 1 < nOld)
84 nNew = 0;
85 return static_cast<sal_uInt16>(nNew);
88 bool TokenPool::GrowId()
90 sal_uInt16 nP_IdNew = lcl_canGrow( nP_Id);
91 if (!nP_IdNew)
92 return false;
94 sal_uInt16* pP_IdNew = new (::std::nothrow) sal_uInt16[ nP_IdNew ];
95 if (!pP_IdNew)
96 return false;
98 for( sal_uInt16 nL = 0 ; nL < nP_Id ; nL++ )
99 pP_IdNew[ nL ] = pP_Id[ nL ];
101 nP_Id = nP_IdNew;
103 pP_Id.reset( pP_IdNew );
104 return true;
107 bool TokenPool::CheckElementOrGrow()
109 // Last possible ID to be assigned somewhere is nElementCurrent+1
110 if (nElementCurrent + 1 == nScTokenOff - 1)
112 SAL_WARN("sc.filter","TokenPool::CheckElementOrGrow - last possible ID " << nElementCurrent+1);
113 return false;
116 if (nElementCurrent >= nElement)
117 return GrowElement();
119 return true;
122 bool TokenPool::GrowElement()
124 sal_uInt16 nElementNew = lcl_canGrow( nElement);
125 if (!nElementNew)
126 return false;
128 std::unique_ptr<sal_uInt16[]> pElementNew(new (::std::nothrow) sal_uInt16[ nElementNew ]);
129 std::unique_ptr<E_TYPE[]> pTypeNew(new (::std::nothrow) E_TYPE[ nElementNew ]);
130 std::unique_ptr<sal_uInt16[]> pSizeNew(new (::std::nothrow) sal_uInt16[ nElementNew ]);
131 if (!pElementNew || !pTypeNew || !pSizeNew)
133 return false;
136 for( sal_uInt16 nL = 0 ; nL < nElement ; nL++ )
138 pElementNew[ nL ] = pElement[ nL ];
139 pTypeNew[ nL ] = pType[ nL ];
140 pSizeNew[ nL ] = pSize[ nL ];
143 nElement = nElementNew;
145 pElement = std::move( pElementNew );
146 pType = std::move( pTypeNew );
147 pSize = std::move( pSizeNew );
148 return true;
151 bool TokenPool::GrowMatrix()
153 sal_uInt16 nNewSize = lcl_canGrow( nP_Matrix);
154 if (!nNewSize)
155 return false;
157 ScMatrix** ppNew = new (::std::nothrow) ScMatrix*[ nNewSize ];
158 if (!ppNew)
159 return false;
161 memset( ppNew, 0, sizeof( ScMatrix* ) * nNewSize );
162 for( sal_uInt16 nL = 0 ; nL < nP_Matrix ; nL++ )
163 ppNew[ nL ] = ppP_Matrix[ nL ];
165 ppP_Matrix.reset( ppNew );
166 nP_Matrix = nNewSize;
167 return true;
170 bool TokenPool::GetElement( const sal_uInt16 nId, ScTokenArray* pScToken )
172 if (nId >= nElementCurrent)
174 SAL_WARN("sc.filter","TokenPool::GetElement - Id too large, " << nId << " >= " << nElementCurrent);
175 return false;
178 bool bRet = true;
179 if( pType[ nId ] == T_Id )
180 bRet = GetElementRek( nId, pScToken );
181 else
183 switch( pType[ nId ] )
185 case T_Str:
187 sal_uInt16 n = pElement[ nId ];
188 auto* p = ppP_Str.getIfInRange( n );
189 if (p)
190 pScToken->AddString(mrStringPool.intern(**p));
191 else
192 bRet = false;
194 break;
195 case T_D:
197 sal_uInt16 n = pElement[ nId ];
198 if (n < pP_Dbl.m_writemark)
199 pScToken->AddDouble( pP_Dbl[ n ] );
200 else
201 bRet = false;
203 break;
204 case T_Err:
205 break;
206 /* TODO: in case we had FormulaTokenArray::AddError() */
207 #if 0
209 sal_uInt16 n = pElement[ nId ];
210 if (n < nP_Err)
211 pScToken->AddError( pP_Err[ n ] );
212 else
213 bRet = false;
215 #endif
216 case T_RefC:
218 sal_uInt16 n = pElement[ nId ];
219 auto p = ppP_RefTr.getIfInRange(n);
220 if (p)
221 pScToken->AddSingleReference( **p );
222 else
223 bRet = false;
225 break;
226 case T_RefA:
228 sal_uInt16 n = pElement[ nId ];
229 if (n < ppP_RefTr.m_writemark && ppP_RefTr[ n ] && n+1 < ppP_RefTr.m_writemark && ppP_RefTr[ n + 1 ])
231 ScComplexRefData aScComplexRefData;
232 aScComplexRefData.Ref1 = *ppP_RefTr[ n ];
233 aScComplexRefData.Ref2 = *ppP_RefTr[ n + 1 ];
234 pScToken->AddDoubleReference( aScComplexRefData );
236 else
237 bRet = false;
239 break;
240 case T_RN:
242 sal_uInt16 n = pElement[nId];
243 if (n < maRangeNames.size())
245 const RangeName& r = maRangeNames[n];
246 pScToken->AddRangeName(r.mnIndex, r.mnSheet);
249 break;
250 case T_Ext:
252 sal_uInt16 n = pElement[ nId ];
253 auto p = ppP_Ext.getIfInRange(n);
255 if( p )
257 if( (*p)->eId == ocEuroConvert )
258 pScToken->AddOpCode( (*p)->eId );
259 else
260 pScToken->AddExternal( (*p)->aText, (*p)->eId );
262 else
263 bRet = false;
265 break;
266 case T_Nlf:
268 sal_uInt16 n = pElement[ nId ];
269 auto p = ppP_Nlf.getIfInRange(n);
271 if( p )
272 pScToken->AddColRowName( **p );
273 else
274 bRet = false;
276 break;
277 case T_Matrix:
279 sal_uInt16 n = pElement[ nId ];
280 ScMatrix* p = ( n < nP_Matrix )? ppP_Matrix[ n ] : nullptr;
282 if( p )
283 pScToken->AddMatrix( p );
284 else
285 bRet = false;
287 break;
288 case T_ExtName:
290 sal_uInt16 n = pElement[nId];
291 if (n < maExtNames.size())
293 const ExtName& r = maExtNames[n];
294 pScToken->AddExternalName(r.mnFileId, mrStringPool.intern( r.maName));
296 else
297 bRet = false;
299 break;
300 case T_ExtRefC:
302 sal_uInt16 n = pElement[nId];
303 if (n < maExtCellRefs.size())
305 const ExtCellRef& r = maExtCellRefs[n];
306 pScToken->AddExternalSingleReference(r.mnFileId, mrStringPool.intern( r.maTabName), r.maRef);
308 else
309 bRet = false;
311 break;
312 case T_ExtRefA:
314 sal_uInt16 n = pElement[nId];
315 if (n < maExtAreaRefs.size())
317 const ExtAreaRef& r = maExtAreaRefs[n];
318 pScToken->AddExternalDoubleReference(r.mnFileId, mrStringPool.intern( r.maTabName), r.maRef);
320 else
321 bRet = false;
323 break;
324 default:
325 OSL_FAIL("-TokenPool::GetElement(): undefined state!?");
326 bRet = false;
329 return bRet;
332 bool TokenPool::GetElementRek( const sal_uInt16 nId, ScTokenArray* pScToken )
334 #ifdef DBG_UTIL
335 m_nRek++;
336 OSL_ENSURE(m_nRek <= nP_Id, "*TokenPool::GetElement(): recursion loops!?");
337 #endif
339 OSL_ENSURE( nId < nElementCurrent, "*TokenPool::GetElementRek(): nId >= nElementCurrent" );
341 if (nId >= nElementCurrent)
343 SAL_WARN("sc.filter", "*TokenPool::GetElementRek(): nId >= nElementCurrent");
344 #ifdef DBG_UTIL
345 m_nRek--;
346 #endif
347 return false;
350 if (pType[ nId ] != T_Id)
352 SAL_WARN("sc.filter", "-TokenPool::GetElementRek(): pType[ nId ] != T_Id");
353 #ifdef DBG_UTIL
354 m_nRek--;
355 #endif
356 return false;
359 bool bRet = true;
360 sal_uInt16 nCnt = pSize[ nId ];
361 sal_uInt16 nFirstId = pElement[ nId ];
362 if (nFirstId >= nP_Id)
364 SAL_WARN("sc.filter", "TokenPool::GetElementRek: nFirstId >= nP_Id");
365 nCnt = 0;
366 bRet = false;
368 sal_uInt16* pCurrent = nCnt ? &pP_Id[ nFirstId ] : nullptr;
369 if (nCnt > nP_Id - nFirstId)
371 SAL_WARN("sc.filter", "TokenPool::GetElementRek: nCnt > nP_Id - nFirstId");
372 nCnt = nP_Id - nFirstId;
373 bRet = false;
375 for( ; nCnt > 0 ; nCnt--, pCurrent++ )
377 assert(pCurrent);
378 if( *pCurrent < nScTokenOff )
379 {// recursion or not?
380 if (*pCurrent >= nElementCurrent)
382 SAL_WARN("sc.filter", "TokenPool::GetElementRek: *pCurrent >= nElementCurrent");
383 bRet = false;
385 else
387 if (pType[ *pCurrent ] == T_Id)
388 bRet = GetElementRek( *pCurrent, pScToken );
389 else
390 bRet = GetElement( *pCurrent, pScToken );
393 else // elementary SC_Token
394 pScToken->AddOpCode( static_cast<DefTokenId>( *pCurrent - nScTokenOff ) );
397 #ifdef DBG_UTIL
398 m_nRek--;
399 #endif
400 return bRet;
403 void TokenPool::operator >>( TokenId& rId )
405 rId = static_cast<TokenId>( nElementCurrent + 1 );
407 if (!CheckElementOrGrow())
408 return;
410 pElement[ nElementCurrent ] = nP_IdLast; // Start of Token-sequence
411 pType[ nElementCurrent ] = T_Id; // set Typeinfo
412 pSize[ nElementCurrent ] = nP_IdCurrent - nP_IdLast;
413 // write from nP_IdLast to nP_IdCurrent-1 -> length of the sequence
415 nElementCurrent++; // start value for next sequence
416 nP_IdLast = nP_IdCurrent;
419 TokenId TokenPool::Store( const double& rDouble )
421 if (!CheckElementOrGrow())
422 return static_cast<const TokenId>(nElementCurrent+1);
424 if( pP_Dbl.m_writemark >= pP_Dbl.m_capacity )
425 if (!pP_Dbl.Grow())
426 return static_cast<const TokenId>(nElementCurrent+1);
428 pElement[ nElementCurrent ] = pP_Dbl.m_writemark; // Index in Double-Array
429 pType[ nElementCurrent ] = T_D; // set Typeinfo Double
431 pP_Dbl[ pP_Dbl.m_writemark ] = rDouble;
433 pSize[ nElementCurrent ] = 1; // does not matter
435 nElementCurrent++;
436 pP_Dbl.m_writemark++;
438 return static_cast<const TokenId>(nElementCurrent); // return old value + 1!
441 TokenId TokenPool::Store( const sal_uInt16 nIndex )
443 return StoreName(nIndex, -1);
446 TokenId TokenPool::Store( const OUString& rString )
448 // mostly copied to Store( const sal_Char* ), to avoid a temporary string
449 if (!CheckElementOrGrow())
450 return static_cast<const TokenId>(nElementCurrent+1);
452 if( ppP_Str.m_writemark >= ppP_Str.m_capacity )
453 if (!ppP_Str.Grow())
454 return static_cast<const TokenId>(nElementCurrent+1);
456 pElement[ nElementCurrent ] = ppP_Str.m_writemark; // Index in String-Array
457 pType[ nElementCurrent ] = T_Str; // set Typeinfo String
459 // create String
460 if( !ppP_Str[ ppP_Str.m_writemark ] )
461 //...but only, if it does not exist already
462 ppP_Str[ ppP_Str.m_writemark ].reset( new OUString( rString ) );
463 else
464 //...copy otherwise
465 *ppP_Str[ ppP_Str.m_writemark ] = rString;
467 /* attention truncate to 16 bits */
468 pSize[ nElementCurrent ] = static_cast<sal_uInt16>(ppP_Str[ ppP_Str.m_writemark ]->getLength());
470 nElementCurrent++;
471 ppP_Str.m_writemark++;
473 return static_cast<const TokenId>(nElementCurrent); // return old value + 1!
476 TokenId TokenPool::Store( const ScSingleRefData& rTr )
478 if (!CheckElementOrGrow())
479 return static_cast<const TokenId>(nElementCurrent+1);
481 if( ppP_RefTr.m_writemark >= ppP_RefTr.m_capacity )
482 if (!ppP_RefTr.Grow())
483 return static_cast<const TokenId>(nElementCurrent+1);
485 pElement[ nElementCurrent ] = ppP_RefTr.m_writemark;
486 pType[ nElementCurrent ] = T_RefC; // set Typeinfo Cell-Ref
488 if( !ppP_RefTr[ ppP_RefTr.m_writemark ] )
489 ppP_RefTr[ ppP_RefTr.m_writemark ].reset( new ScSingleRefData( rTr ) );
490 else
491 *ppP_RefTr[ ppP_RefTr.m_writemark ] = rTr;
493 nElementCurrent++;
494 ppP_RefTr.m_writemark++;
496 return static_cast<const TokenId>(nElementCurrent); // return old value + 1!
499 TokenId TokenPool::Store( const ScComplexRefData& rTr )
501 if (!CheckElementOrGrow())
502 return static_cast<const TokenId>(nElementCurrent+1);
504 if( ppP_RefTr.m_writemark + 1 >= ppP_RefTr.m_capacity )
505 if (!ppP_RefTr.Grow(2))
506 return static_cast<const TokenId>(nElementCurrent+1);
508 pElement[ nElementCurrent ] = ppP_RefTr.m_writemark;
509 pType[ nElementCurrent ] = T_RefA; // setTypeinfo Area-Ref
511 if( !ppP_RefTr[ ppP_RefTr.m_writemark ] )
512 ppP_RefTr[ ppP_RefTr.m_writemark ].reset( new ScSingleRefData( rTr.Ref1 ) );
513 else
514 *ppP_RefTr[ ppP_RefTr.m_writemark ] = rTr.Ref1;
515 ppP_RefTr.m_writemark++;
517 if( !ppP_RefTr[ ppP_RefTr.m_writemark ] )
518 ppP_RefTr[ ppP_RefTr.m_writemark ].reset( new ScSingleRefData( rTr.Ref2 ) );
519 else
520 *ppP_RefTr[ ppP_RefTr.m_writemark ] = rTr.Ref2;
521 ppP_RefTr.m_writemark++;
523 nElementCurrent++;
525 return static_cast<const TokenId>(nElementCurrent); // return old value + 1!
528 TokenId TokenPool::Store( const DefTokenId e, const OUString& r )
530 if (!CheckElementOrGrow())
531 return static_cast<const TokenId>(nElementCurrent+1);
533 if( ppP_Ext.m_writemark >= ppP_Ext.m_capacity )
534 if (!ppP_Ext.Grow())
535 return static_cast<const TokenId>(nElementCurrent+1);
537 pElement[ nElementCurrent ] = ppP_Ext.m_writemark;
538 pType[ nElementCurrent ] = T_Ext; // set Typeinfo String
540 if( ppP_Ext[ ppP_Ext.m_writemark ] )
542 ppP_Ext[ ppP_Ext.m_writemark ]->eId = e;
543 ppP_Ext[ ppP_Ext.m_writemark ]->aText = r;
545 else
546 ppP_Ext[ ppP_Ext.m_writemark ].reset( new EXTCONT( e, r ) );
548 nElementCurrent++;
549 ppP_Ext.m_writemark++;
551 return static_cast<const TokenId>(nElementCurrent); // return old value + 1!
554 TokenId TokenPool::StoreNlf( const ScSingleRefData& rTr )
556 if (!CheckElementOrGrow())
557 return static_cast<const TokenId>(nElementCurrent+1);
559 if( ppP_Nlf.m_writemark >= ppP_Nlf.m_capacity )
560 if (!ppP_Nlf.Grow())
561 return static_cast<const TokenId>(nElementCurrent+1);
563 pElement[ nElementCurrent ] = ppP_Nlf.m_writemark;
564 pType[ nElementCurrent ] = T_Nlf;
566 if( ppP_Nlf[ ppP_Nlf.m_writemark ] )
568 *ppP_Nlf[ ppP_Nlf.m_writemark ] = rTr;
570 else
571 ppP_Nlf[ ppP_Nlf.m_writemark ].reset( new ScSingleRefData( rTr ) );
573 nElementCurrent++;
574 ppP_Nlf.m_writemark++;
576 return static_cast<const TokenId>(nElementCurrent);
579 TokenId TokenPool::StoreMatrix()
581 if (!CheckElementOrGrow())
582 return static_cast<const TokenId>(nElementCurrent+1);
584 if( nP_MatrixCurrent >= nP_Matrix )
585 if (!GrowMatrix())
586 return static_cast<const TokenId>(nElementCurrent+1);
588 pElement[ nElementCurrent ] = nP_MatrixCurrent;
589 pType[ nElementCurrent ] = T_Matrix;
591 ScMatrix* pM = new ScMatrix( 0, 0 );
592 pM->IncRef( );
593 ppP_Matrix[ nP_MatrixCurrent ] = pM;
595 nElementCurrent++;
596 nP_MatrixCurrent++;
598 return static_cast<const TokenId>(nElementCurrent);
601 TokenId TokenPool::StoreName( sal_uInt16 nIndex, sal_Int16 nSheet )
603 if (!CheckElementOrGrow())
604 return static_cast<const TokenId>(nElementCurrent+1);
606 pElement[nElementCurrent] = static_cast<sal_uInt16>(maRangeNames.size());
607 pType[nElementCurrent] = T_RN;
609 maRangeNames.emplace_back();
610 RangeName& r = maRangeNames.back();
611 r.mnIndex = nIndex;
612 r.mnSheet = nSheet;
614 ++nElementCurrent;
616 return static_cast<const TokenId>(nElementCurrent);
619 TokenId TokenPool::StoreExtName( sal_uInt16 nFileId, const OUString& rName )
621 if (!CheckElementOrGrow())
622 return static_cast<const TokenId>(nElementCurrent+1);
624 pElement[nElementCurrent] = static_cast<sal_uInt16>(maExtNames.size());
625 pType[nElementCurrent] = T_ExtName;
627 maExtNames.emplace_back();
628 ExtName& r = maExtNames.back();
629 r.mnFileId = nFileId;
630 r.maName = rName;
632 ++nElementCurrent;
634 return static_cast<const TokenId>(nElementCurrent);
637 TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
639 if (!CheckElementOrGrow())
640 return static_cast<const TokenId>(nElementCurrent+1);
642 pElement[nElementCurrent] = static_cast<sal_uInt16>(maExtCellRefs.size());
643 pType[nElementCurrent] = T_ExtRefC;
645 maExtCellRefs.emplace_back();
646 ExtCellRef& r = maExtCellRefs.back();
647 r.mnFileId = nFileId;
648 r.maTabName = rTabName;
649 r.maRef = rRef;
651 ++nElementCurrent;
653 return static_cast<const TokenId>(nElementCurrent);
656 TokenId TokenPool::StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
658 if (!CheckElementOrGrow())
659 return static_cast<const TokenId>(nElementCurrent+1);
661 pElement[nElementCurrent] = static_cast<sal_uInt16>(maExtAreaRefs.size());
662 pType[nElementCurrent] = T_ExtRefA;
664 maExtAreaRefs.emplace_back();
665 ExtAreaRef& r = maExtAreaRefs.back();
666 r.mnFileId = nFileId;
667 r.maTabName = rTabName;
668 r.maRef = rRef;
670 ++nElementCurrent;
672 return static_cast<const TokenId>(nElementCurrent);
675 void TokenPool::Reset()
677 nP_IdCurrent = nP_IdLast = nElementCurrent
678 = ppP_Str.m_writemark = pP_Dbl.m_writemark = pP_Err.m_writemark
679 = ppP_RefTr.m_writemark = ppP_Ext.m_writemark = ppP_Nlf.m_writemark = nP_MatrixCurrent = 0;
680 maRangeNames.clear();
681 maExtNames.clear();
682 maExtCellRefs.clear();
683 maExtAreaRefs.clear();
684 ClearMatrix();
687 bool TokenPool::IsSingleOp( const TokenId& rId, const DefTokenId eId ) const
689 sal_uInt16 nId = static_cast<sal_uInt16>(rId);
690 if( nId && nId <= nElementCurrent )
691 {// existent?
692 nId--;
693 if( T_Id == pType[ nId ] )
694 {// Token-Sequence?
695 if( pSize[ nId ] == 1 )
696 {// EXACTLY 1 Token
697 sal_uInt16 nPid = pElement[ nId ];
698 if (nPid < nP_Id)
700 sal_uInt16 nSecId = pP_Id[ nPid ];
701 if( nSecId >= nScTokenOff )
702 {// Default-Token?
703 return static_cast<DefTokenId>( nSecId - nScTokenOff ) == eId; // wanted?
710 return false;
713 const OUString* TokenPool::GetExternal( const TokenId& rId ) const
715 const OUString* p = nullptr;
716 sal_uInt16 n = static_cast<sal_uInt16>(rId);
717 if( n && n <= nElementCurrent )
719 n--;
720 if( pType[ n ] == T_Ext )
722 sal_uInt16 nExt = pElement[ n ];
723 if ( nExt < ppP_Ext.m_writemark && ppP_Ext[ nExt ] )
724 p = &ppP_Ext[ nExt ]->aText;
728 return p;
731 ScMatrix* TokenPool::GetMatrix( unsigned int n ) const
733 if( n < nP_MatrixCurrent )
734 return ppP_Matrix[ n ];
735 else
736 SAL_WARN("sc.filter", "GetMatrix: " << n << " >= " << nP_MatrixCurrent);
737 return nullptr;
740 void TokenPool::ClearMatrix()
742 for(sal_uInt16 n = 0 ; n < nP_Matrix ; n++ )
744 if( ppP_Matrix[ n ] )
746 ppP_Matrix[ n ]->DecRef( );
747 ppP_Matrix[n] = nullptr;
752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */