1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <excform.hxx>
21 
22 #include <document.hxx>
23 #include <xltracer.hxx>
24 #include <xistream.hxx>
25 #include <xihelper.hxx>
26 #include <xilink.hxx>
27 #include <xiname.hxx>
28 
29 #include <externalrefmgr.hxx>
30 
31 #include <cstring>
32 
33 using ::std::vector;
34 
35 namespace {
36 
37 /**
38  * Extract a file path from OLE link path.  An OLE link path is expected to
39  * be in the following format:
40  *
41  * Excel.Sheet.8 \3 [file path]
42  */
extractFilePath(const OUString & rUrl,OUString & rPath)43 bool extractFilePath(const OUString& rUrl, OUString& rPath)
44 {
45     const char* prefix = "Excel.Sheet.8\3";
46     size_t nPrefixLen = ::std::strlen(prefix);
47 
48     sal_Int32 n = rUrl.getLength();
49     if (n <= static_cast<sal_Int32>(nPrefixLen))
50         // needs to have the specified prefix.
51         return false;
52 
53     OUStringBuffer aBuf;
54     const sal_Unicode* p = rUrl.getStr();
55     for (size_t i = 0; i < static_cast<size_t>(n); ++i, ++p)
56     {
57         if (i < nPrefixLen)
58         {
59             sal_Unicode pc = static_cast<sal_Unicode>(*prefix++);
60             if (pc != *p)
61                 return false;
62 
63             continue;
64         }
65         aBuf.append(*p);
66     }
67 
68     rPath = aBuf.makeStringAndClear();
69     return true;
70 }
71 
72 }
73 
ExternalTabInfo()74 ExcelToSc8::ExternalTabInfo::ExternalTabInfo() :
75     mnFileId(0), mbExternal(false)
76 {
77 }
78 
ExcelToSc8(XclImpRoot & rRoot)79 ExcelToSc8::ExcelToSc8( XclImpRoot& rRoot ) :
80     ExcelToSc( rRoot ),
81     rLinkMan( rRoot.GetLinkManager() )
82 {
83 }
84 
~ExcelToSc8()85 ExcelToSc8::~ExcelToSc8()
86 {
87 }
88 
GetExternalFileIdFromXti(sal_uInt16 nIxti,sal_uInt16 & rFileId) const89 bool ExcelToSc8::GetExternalFileIdFromXti( sal_uInt16 nIxti, sal_uInt16& rFileId ) const
90 {
91     const OUString* pFileUrl = rLinkMan.GetSupbookUrl(nIxti);
92     if (!pFileUrl || pFileUrl->isEmpty() || !GetDocShell())
93         return false;
94 
95     OUString aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell());
96     ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
97     rFileId = pRefMgr->getExternalFileId(aFileUrl);
98 
99     return true;
100 }
101 
Read3DTabReference(sal_uInt16 nIxti,SCTAB & rFirstTab,SCTAB & rLastTab,ExternalTabInfo & rExtInfo)102 bool ExcelToSc8::Read3DTabReference( sal_uInt16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo )
103 {
104     rFirstTab = rLastTab = 0;
105     rExtInfo.mbExternal = !rLinkMan.IsSelfRef(nIxti);
106     bool bSuccess = rLinkMan.GetScTabRange(rFirstTab, rLastTab, nIxti);
107     if (!bSuccess)
108         return false;
109 
110     if (!rExtInfo.mbExternal)
111         // This is internal reference.  Stop here.
112         return true;
113 
114     rExtInfo.maTabName = rLinkMan.GetSupbookTabName(nIxti, rFirstTab);
115     return GetExternalFileIdFromXti(nIxti, rExtInfo.mnFileId);
116 }
117 
HandleOleLink(sal_uInt16 nXtiIndex,const XclImpExtName & rExtName,ExternalTabInfo & rExtInfo)118 bool ExcelToSc8::HandleOleLink(sal_uInt16 nXtiIndex, const XclImpExtName& rExtName, ExternalTabInfo& rExtInfo)
119 {
120     const OUString* pUrl = rLinkMan.GetSupbookUrl(nXtiIndex);
121     if (!pUrl)
122         return false;
123 
124     OUString aPath;
125     if (!extractFilePath(*pUrl, aPath))
126         // file path extraction failed.
127         return false;
128 
129     OUString aFileUrl = ScGlobal::GetAbsDocName(aPath, GetDocShell());
130     return rExtName.CreateOleData(GetDoc(), aFileUrl, rExtInfo.mnFileId, rExtInfo.maTabName, rExtInfo.maRange);
131 }
132 
133 // if bAllowArrays is false stream seeks to first byte after <nFormulaLen>
134 // otherwise it will seek to the first byte past additional content after <nFormulaLen>
Convert(std::unique_ptr<ScTokenArray> & rpTokArray,XclImpStream & aIn,std::size_t nFormulaLen,bool bAllowArrays,const FORMULA_TYPE eFT)135 ConvErr ExcelToSc8::Convert( std::unique_ptr<ScTokenArray>& rpTokArray, XclImpStream& aIn, std::size_t nFormulaLen, bool bAllowArrays, const FORMULA_TYPE eFT )
136 {
137     bool                    bError = false;
138     bool                    bArrayFormula = false;
139     TokenId                 nBuf0;
140     const bool              bCondFormat = eFT == FT_CondFormat;
141     const bool              bRangeName = eFT == FT_RangeName;
142     const bool              bRangeNameOrCond = bRangeName || bCondFormat;
143     const bool              bSharedFormula = eFT == FT_SharedFormula;
144     const bool              bRNorSF = bRangeNameOrCond || bSharedFormula;
145 
146     ScSingleRefData         aSRD;
147     ScComplexRefData        aCRD;
148     ExtensionTypeVec        aExtensions;
149 
150     if( nFormulaLen == 0 )
151     {
152         aPool.Store( "-/-" );
153         aPool >> aStack;
154         rpTokArray = aPool.GetTokenArray( aStack.Get());
155         return ConvErr::OK;
156     }
157 
158     std::size_t nEndPos = aIn.GetRecPos() + nFormulaLen;
159 
160     while( (aIn.GetRecPos() < nEndPos) && !bError )
161     {
162         sal_uInt8 nOp = aIn.ReaduInt8();
163 
164         // always reset flags
165         aSRD.InitFlags();
166         aCRD.InitFlags();
167 
168         switch( nOp )   //                                  book page:
169         {           //                                      SDK4 SDK5
170             case 0x01: // Array Formula                         [325    ]
171                        // Array Formula or Shared Formula       [    277]
172             case 0x02: // Data Table                            [325 277]
173                 aIn.Ignore( 4 );
174 
175                 bArrayFormula = true;
176                 break;
177             case 0x03: // Addition                              [312 264]
178                 aStack >> nBuf0;
179                 aPool <<  aStack << ocAdd << nBuf0;
180                 aPool >> aStack;
181                 break;
182             case 0x04: // Subtraction                           [313 264]
183                 // SECOND-TOP minus TOP
184                 aStack >> nBuf0;
185                 aPool << aStack << ocSub << nBuf0;
186                 aPool >> aStack;
187                 break;
188             case 0x05: // Multiplication                        [313 264]
189                 aStack >> nBuf0;
190                 aPool << aStack << ocMul << nBuf0;
191                 aPool >> aStack;
192                 break;
193             case 0x06: // Division                              [313 264]
194                 // divide TOP by SECOND-TOP
195                 aStack >> nBuf0;
196                 aPool << aStack << ocDiv << nBuf0;
197                 aPool >> aStack;
198                 break;
199             case 0x07: // Exponentiation                        [313 265]
200                 // raise SECOND-TOP to power of TOP
201                 aStack >> nBuf0;
202                 aPool << aStack << ocPow << nBuf0;
203                 aPool >> aStack;
204                 break;
205             case 0x08: // Concatenation                         [313 265]
206                 // append TOP to SECOND-TOP
207                 aStack >> nBuf0;
208                 aPool << aStack << ocAmpersand << nBuf0;
209                 aPool >> aStack;
210                 break;
211             case 0x09: // Less Than                             [313 265]
212                 // SECOND-TOP < TOP
213                 aStack >> nBuf0;
214                 aPool << aStack << ocLess << nBuf0;
215                 aPool >> aStack;
216                 break;
217             case 0x0A: // Less Than or Equal                    [313 265]
218                 // SECOND-TOP <= TOP
219                 aStack >> nBuf0;
220                 aPool << aStack << ocLessEqual << nBuf0;
221                 aPool >> aStack;
222                 break;
223             case 0x0B: // Equal                                 [313 265]
224                 // SECOND-TOP == TOP
225                 aStack >> nBuf0;
226                 aPool << aStack << ocEqual << nBuf0;
227                 aPool >> aStack;
228                 break;
229             case 0x0C: // Greater Than or Equal                 [313 265]
230                 // SECOND-TOP >= TOP
231                 aStack >> nBuf0;
232                 aPool << aStack << ocGreaterEqual << nBuf0;
233                 aPool >> aStack;
234                 break;
235             case 0x0D: // Greater Than                          [313 265]
236                 // SECOND-TOP > TOP
237                 aStack >> nBuf0;
238                 aPool << aStack << ocGreater << nBuf0;
239                 aPool >> aStack;
240                 break;
241             case 0x0E: // Not Equal                             [313 265]
242                 // SECOND-TOP != TOP
243                 aStack >> nBuf0;
244                 aPool << aStack << ocNotEqual << nBuf0;
245                 aPool >> aStack;
246                 break;
247             case 0x0F: // Intersection                          [314 265]
248                 aStack >> nBuf0;
249                 aPool << aStack << ocIntersect << nBuf0;
250                 aPool >> aStack;
251                 break;
252             case 0x10: // Union                                 [314 265]
253                 // ocSep instead of 'ocUnion'
254                 aStack >> nBuf0;
255                 aPool << aStack << ocSep << nBuf0;
256                     // doesn't fit exactly, but is more Excel-like
257                 aPool >> aStack;
258                 break;
259             case 0x11: // Range                                 [314 265]
260                 aStack >> nBuf0;
261                 aPool << aStack << ocRange << nBuf0;
262                 aPool >> aStack;
263                 break;
264             case 0x12: // Unary Plus                            [312 264]
265                 aPool << ocAdd << aStack;
266                 aPool >> aStack;
267                 break;
268             case 0x13: // Unary Minus                           [312 264]
269                 aPool << ocNegSub << aStack;
270                 aPool >> aStack;
271                 break;
272             case 0x14: // Percent Sign                          [312 264]
273                 aPool << aStack << ocPercentSign;
274                 aPool >> aStack;
275                 break;
276             case 0x15: // Parenthesis                           [326 278]
277                 aPool << ocOpen << aStack << ocClose;
278                 aPool >> aStack;
279                 break;
280             case 0x16: // Missing Argument                      [314 266]
281                 aPool << ocMissing;
282                 aPool >> aStack;
283                 GetTracer().TraceFormulaMissingArg();
284                 break;
285             case 0x17: // String Constant                       [314 266]
286             {
287                 sal_uInt8 nLen = aIn.ReaduInt8();        // Why?
288                 OUString aString = aIn.ReadUniString( nLen );            // reads Grbit even if nLen==0
289 
290                 aStack << aPool.Store( aString );
291                 break;
292             }
293             case 0x18:                                          // natural language formula
294                 {
295                 sal_uInt8   nEptg;
296                 sal_uInt16  nCol, nRow;
297                 nEptg = aIn.ReaduInt8();
298                 switch( nEptg )
299                 {                           //  name        size    ext     type
300                     case 0x01:              //  Lel         4       -       err
301                         aIn.Ignore( 4 );
302                         aPool << ocBad;
303                         aPool >> aStack;
304                     break;
305                     case 0x02:              //  Rw          4       -       ref
306                     case 0x03:              //  Col         4       -       ref
307                     case 0x06:              //  RwV         4       -       val
308                     case 0x07:              //  ColV        4       -       val
309                     {
310                         nRow = aIn.ReaduInt16();
311                         nCol = aIn.ReaduInt16();
312                         ScAddress aAddr(static_cast<SCCOL>(nCol & 0xFF), static_cast<SCROW>(nRow), aEingPos.Tab());
313                         aSRD.InitAddress(aAddr);
314 
315                         if( nEptg == 0x02 || nEptg == 0x06 )
316                             aSRD.SetRowRel(true);
317                         else
318                             aSRD.SetColRel(true);
319 
320                         aSRD.SetAddress(aAddr, aEingPos);
321 
322                         aStack << aPool.StoreNlf( aSRD );
323 
324                         break;
325                     }
326                     case 0x0A:              //  Radical     13      -       ref
327                     {
328                         nRow = aIn.ReaduInt16();
329                         nCol = aIn.ReaduInt16();
330                         aIn.Ignore( 9 );
331                         ScAddress aAddr(static_cast<SCCOL>(nCol & 0xFF), static_cast<SCROW>(nRow), aEingPos.Tab());
332                         aSRD.InitAddress(aAddr);
333                         aSRD.SetColRel(true);
334                         aSRD.SetAddress(aAddr, aEingPos);
335 
336                         aStack << aPool.StoreNlf( aSRD );
337 
338                         break;
339                     }
340                     case 0x0B:              //  RadicalS    13      x       ref
341                         aIn.Ignore( 13 );
342                         aExtensions.push_back( EXTENSION_NLR );
343                         aPool << ocBad;
344                         aPool >> aStack;
345                         break;
346                     case 0x0C:              //  RwS         4       x       ref
347                     case 0x0D:              //  ColS        4       x       ref
348                     case 0x0E:              //  RwSV        4       x       val
349                     case 0x0F:              //  ColSV       4       x       val
350                         aIn.Ignore( 4 );
351                         aExtensions.push_back( EXTENSION_NLR );
352                         aPool << ocBad;
353                         aPool >> aStack;
354                         break;
355                     case 0x10:              //  RadicalLel  4       -       err
356                     case 0x1D:              //  SxName      4       -       val
357                         aIn.Ignore( 4 );
358                         aPool << ocBad;
359                         aPool >> aStack;
360                         break;
361                     default:
362                         aPool << ocBad;
363                         aPool >> aStack;
364                 }
365                 }
366                 break;
367             case 0x19: // Special Attribute                     [327 279]
368             {
369                 sal_uInt16 nData(0), nFactor(0);
370 
371                 sal_uInt8 nOpt = aIn.ReaduInt8();
372                 nData = aIn.ReaduInt16();
373                 nFactor = 2;
374 
375                 if( nOpt & 0x04 )
376                 {
377                     // nFactor -> skip bytes or words    AttrChoose
378                     nData++;
379                     aIn.Ignore(static_cast<std::size_t>(nData) * nFactor);
380                 }
381                 else if( nOpt & 0x10 )                      // AttrSum
382                     DoMulArgs( ocSum, 1 );
383                 break;
384             }
385             case 0x1C: // Error Value                           [314 266]
386             {
387                 sal_uInt8 nByte = aIn.ReaduInt8();
388 
389                 DefTokenId          eOc;
390                 switch( nByte )
391                 {
392                     case EXC_ERR_NULL:
393                     case EXC_ERR_DIV0:
394                     case EXC_ERR_VALUE:
395                     case EXC_ERR_REF:
396                     case EXC_ERR_NAME:
397                     case EXC_ERR_NUM:   eOc = ocStop;       break;
398                     case EXC_ERR_NA:    eOc = ocNotAvail;   break;
399                     default:            eOc = ocNoName;
400                 }
401                 aPool << eOc;
402                 if( eOc != ocStop )
403                     aPool << ocOpen << ocClose;
404                 aPool >> aStack;
405 
406                 break;
407             }
408             case 0x1D: // Boolean                               [315 266]
409             {
410                 sal_uInt8 nByte = aIn.ReaduInt8();
411                 if( nByte == 0 )
412                     aPool << ocFalse << ocOpen << ocClose;
413                 else
414                     aPool << ocTrue << ocOpen << ocClose;
415                 aPool >> aStack;
416                 break;
417             }
418             case 0x1E: // Integer                               [315 266]
419             {
420                 sal_uInt16 nUINT16 = aIn.ReaduInt16();
421                 aStack << aPool.Store( static_cast<double>(nUINT16) );
422                 break;
423             }
424             case 0x1F: // Number                                [315 266]
425             {
426                 double fDouble = aIn.ReadDouble();
427                 aStack << aPool.Store( fDouble );
428                 break;
429             }
430             case 0x40:
431             case 0x60:
432             case 0x20: // Array Constant                        [317 268]
433             {
434                 aIn.Ignore( 7 );
435                 if( bAllowArrays )
436                 {
437                     aStack << aPool.StoreMatrix();
438                     aExtensions.push_back( EXTENSION_ARRAY );
439                 }
440                 else
441                 {
442                     aPool << ocBad;
443                     aPool >> aStack;
444                 }
445                 break;
446             }
447             case 0x41:
448             case 0x61:
449             case 0x21: // Function, Fixed Number of Arguments   [333 282]
450             {
451                 sal_uInt16 nXclFunc;
452                 nXclFunc = aIn.ReaduInt16();
453                 if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
454                     DoMulArgs( pFuncInfo->meOpCode, pFuncInfo->mnMaxParamCount );
455                 else
456                     DoMulArgs( ocNoName, 0 );
457                 break;
458             }
459             case 0x42:
460             case 0x62:
461             case 0x22: // Function, Variable Number of Arg.     [333 283]
462             {
463                 sal_uInt16 nXclFunc;
464                 sal_uInt8 nParamCount;
465                 nParamCount = aIn.ReaduInt8();
466                 nXclFunc = aIn.ReaduInt16();
467                 nParamCount &= 0x7F;
468                 if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
469                     DoMulArgs( pFuncInfo->meOpCode, nParamCount );
470                 else
471                     DoMulArgs( ocNoName, 0 );
472                 break;
473             }
474             case 0x43:
475             case 0x63:
476             case 0x23: // Name                                  [318 269]
477             {
478                 sal_uInt16 nUINT16 = aIn.ReaduInt16();
479                 aIn.Ignore( 2 );
480                 const XclImpName* pName = GetNameManager().GetName( nUINT16 );
481                 if (pName)
482                 {
483                     if (pName->IsMacro())
484                         // user-defined macro name.
485                         aStack << aPool.Store(ocMacro, pName->GetXclName());
486                     else
487                         aStack << aPool.StoreName(nUINT16, pName->IsGlobal() ? -1 : pName->GetScTab());
488                 }
489                 break;
490             }
491             case 0x44:
492             case 0x64:
493             case 0x24: // Cell Reference                        [319 270]
494             case 0x4A:
495             case 0x6A:
496             case 0x2A: // Deleted Cell Reference                [323 273]
497             {
498                 sal_uInt16          nCol, nRow;
499 
500                 nRow = aIn.ReaduInt16();
501                 nCol = aIn.ReaduInt16();
502 
503                 aSRD.SetRelTab(0);
504                 aSRD.SetFlag3D( bRangeName );
505 
506                 ExcRelToScRel8( nRow, nCol, aSRD, bRangeNameOrCond );
507 
508                 switch ( nOp )
509                 {
510                     case 0x4A:
511                     case 0x6A:
512                     case 0x2A: // Deleted Cell Reference        [323 273]
513                         // no information which part is deleted, set both
514                         aSRD.SetColDeleted( true );
515                         aSRD.SetRowDeleted( true );
516                 }
517 
518                 aStack << aPool.Store( aSRD );
519                 break;
520             }
521             case 0x45:
522             case 0x65:
523             case 0x25: // Area Reference                        [320 270]
524             case 0x4B:
525             case 0x6B:
526             case 0x2B: // Deleted Area Reference                [323 273]
527             {
528                 sal_uInt16          nRowFirst, nRowLast;
529                 sal_uInt16          nColFirst, nColLast;
530                 ScSingleRefData &rSRef1 = aCRD.Ref1;
531                 ScSingleRefData &rSRef2 = aCRD.Ref2;
532 
533                 nRowFirst = aIn.ReaduInt16();
534                 nRowLast = aIn.ReaduInt16();
535                 nColFirst = aIn.ReaduInt16();
536                 nColLast = aIn.ReaduInt16();
537 
538                 rSRef1.SetRelTab(0);
539                 rSRef2.SetRelTab(0);
540                 rSRef1.SetFlag3D( bRangeName );
541                 rSRef2.SetFlag3D( bRangeName );
542 
543                 ExcRelToScRel8( nRowFirst, nColFirst, aCRD.Ref1, bRangeNameOrCond );
544                 ExcRelToScRel8( nRowLast, nColLast, aCRD.Ref2, bRangeNameOrCond );
545 
546                 if( IsComplColRange( nColFirst, nColLast ) )
547                     SetComplCol( aCRD );
548                 else if( IsComplRowRange( nRowFirst, nRowLast ) )
549                     SetComplRow( aCRD );
550 
551                 switch ( nOp )
552                 {
553                     case 0x4B:
554                     case 0x6B:
555                     case 0x2B: // Deleted Area Reference        [323 273]
556                         // no information which part is deleted, set all
557                         rSRef1.SetColDeleted( true );
558                         rSRef1.SetRowDeleted( true );
559                         rSRef2.SetColDeleted( true );
560                         rSRef2.SetRowDeleted( true );
561                 }
562 
563                 aStack << aPool.Store( aCRD );
564                 break;
565             }
566             case 0x46:
567             case 0x66:
568             case 0x26: // Constant Reference Subexpression      [321 271]
569                 aExtensions.push_back( EXTENSION_MEMAREA );
570                 aIn.Ignore( 6 );       // There isn't any more
571                 break;
572             case 0x47:
573             case 0x67:
574             case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
575                 aIn.Ignore( 6 );   // There isn't any more
576                 break;
577             case 0x48:
578             case 0x68:
579             case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
580                 aIn.Ignore( 6 );   // There isn't any more
581                 break;
582             case 0x49:
583             case 0x69:
584             case 0x29: // Variable Reference Subexpression      [331 281]
585                 aIn.Ignore( 2 );   // There isn't any more
586                 break;
587             case 0x4C:
588             case 0x6C:
589             case 0x2C: // Cell Reference Within a Name          [323    ]
590                        // Cell Reference Within a Shared Formula[    273]
591             {
592                 sal_uInt16      nRow, nCol;
593 
594                 nRow = aIn.ReaduInt16();
595                 nCol = aIn.ReaduInt16();
596 
597                 aSRD.SetRelTab(0);
598                 aSRD.SetFlag3D( bRangeName );
599 
600                 ExcRelToScRel8( nRow, nCol, aSRD, bRNorSF );
601 
602                 aStack << aPool.Store( aSRD );
603                 break;
604             }
605             case 0x4D:
606             case 0x6D:
607             case 0x2D: // Area Reference Within a Name          [324    ]
608             {      // Area Reference Within a Shared Formula[    274]
609                 sal_uInt16                  nRowFirst, nRowLast;
610                 sal_uInt16                  nColFirst, nColLast;
611 
612                 aCRD.Ref1.SetRelTab(0);
613                 aCRD.Ref2.SetRelTab(0);
614                 aCRD.Ref1.SetFlag3D( bRangeName );
615                 aCRD.Ref2.SetFlag3D( bRangeName );
616 
617                 nRowFirst = aIn.ReaduInt16();
618                 nRowLast = aIn.ReaduInt16();
619                 nColFirst = aIn.ReaduInt16();
620                 nColLast = aIn.ReaduInt16();
621 
622                 ExcRelToScRel8( nRowFirst, nColFirst, aCRD.Ref1, bRNorSF );
623                 ExcRelToScRel8( nRowLast, nColLast, aCRD.Ref2, bRNorSF );
624 
625                 bool bColRel = aCRD.Ref1.IsColRel() || aCRD.Ref2.IsColRel();
626                 bool bRowRel = aCRD.Ref1.IsRowRel() || aCRD.Ref2.IsRowRel();
627 
628                 if( !bColRel && IsComplColRange( nColFirst, nColLast ) )
629                     SetComplCol( aCRD );
630                 else if( !bRowRel && IsComplRowRange( nRowFirst, nRowLast ) )
631                     SetComplRow( aCRD );
632 
633                 aStack << aPool.Store( aCRD );
634                 break;
635             }
636             case 0x4E:
637             case 0x6E:
638             case 0x2E: // Reference Subexpression Within a Name [332 282]
639                 aIn.Ignore( 2 );   // There isn't any more
640                 break;
641             case 0x4F:
642             case 0x6F:
643             case 0x2F: // Incomplete Reference Subexpression... [332 282]
644                 aIn.Ignore( 2 );   // There isn't any more
645                 break;
646             case 0x58:
647             case 0x78:
648             case 0x38: // Command-Equivalent Function           [333    ]
649             {
650                 OUString aString = "COMM_EQU_FUNC";
651                 sal_uInt8 nByte = aIn.ReaduInt8();
652                 aString += OUString::number( nByte );
653                 nByte = aIn.ReaduInt8();
654                 aStack << aPool.Store( aString );
655                 DoMulArgs( ocPush, nByte + 1 );
656                 break;
657             }
658             case 0x59:
659             case 0x79:
660             case 0x39: // Name or External Name                 [    275]
661             {
662                 sal_uInt16 nXtiIndex, nNameIdx;
663                 nXtiIndex = aIn.ReaduInt16();
664                 nNameIdx = aIn.ReaduInt16();
665                 aIn.Ignore( 2 );
666 
667                 if( rLinkMan.IsSelfRef( nXtiIndex ) )
668                 {
669                     // internal defined name with explicit sheet, i.e.: =Sheet1!AnyName
670                     const XclImpName* pName = GetNameManager().GetName( nNameIdx );
671                     if (pName)
672                     {
673                         if (pName->GetScRangeData())
674                             aStack << aPool.StoreName( nNameIdx, pName->IsGlobal() ? -1 : pName->GetScTab());
675                         else
676                             aStack << aPool.Store(ocMacro, pName->GetXclName());
677                     }
678                 }
679                 else if( const XclImpExtName* pExtName = rLinkMan.GetExternName( nXtiIndex, nNameIdx ) )
680                 {
681                     switch( pExtName->GetType() )
682                     {
683                         case xlExtName:
684                         {
685                             /* FIXME: enable this code for #i4385# once
686                              * external name reference can be stored in ODF,
687                              * which remains to be done for #i3740#. Until then
688                              * create a #NAME? token. */
689 #if 1
690                             sal_uInt16 nFileId;
691                             if (!GetExternalFileIdFromXti(nXtiIndex, nFileId) || !pExtName->HasFormulaTokens())
692                             {
693                                 aStack << aPool.Store(ocNoName, pExtName->GetName());
694                                 break;
695                             }
696 
697                             aStack << aPool.StoreExtName(nFileId, pExtName->GetName());
698                             pExtName->CreateExtNameData(GetDoc(), nFileId);
699 #else
700                             aStack << aPool.Store( ocNoName, pExtName->GetName() );
701 #endif
702                         }
703                         break;
704 
705                         case xlExtAddIn:
706                         {
707                             aStack << aPool.Store( ocExternal, pExtName->GetName() );
708                         }
709                         break;
710 
711                         case xlExtDDE:
712                         {
713                             OUString aApplic, aTopic;
714                             if( rLinkMan.GetLinkData( aApplic, aTopic, nXtiIndex ) )
715                             {
716                                 TokenId nPar1 = aPool.Store( aApplic );
717                                 TokenId nPar2 = aPool.Store( aTopic );
718                                 nBuf0 = aPool.Store( pExtName->GetName() );
719                                 aPool   << ocDde << ocOpen << nPar1 << ocSep << nPar2 << ocSep
720                                         << nBuf0 << ocClose;
721                                 aPool >> aStack;
722                                 pExtName->CreateDdeData( GetDoc(), aApplic, aTopic );
723                                 GetDoc().SetLinkFormulaNeedingCheck(true);
724                             }
725                         }
726                         break;
727 
728                         case xlExtEuroConvert:
729                             {
730                                 aStack << aPool.Store( ocEuroConvert, OUString() );
731                             }
732                         break;
733                         case xlExtOLE:
734                         {
735                             ExternalTabInfo aExtInfo;
736                             if (HandleOleLink(nXtiIndex, *pExtName, aExtInfo))
737                             {
738                                 if (aExtInfo.maRange.aStart == aExtInfo.maRange.aEnd)
739                                 {
740                                     // single cell
741                                     aSRD.InitAddress(aExtInfo.maRange.aStart);
742                                     aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aSRD);
743                                 }
744                                 else
745                                 {
746                                     // range
747                                     aCRD.InitRange(aExtInfo.maRange);
748                                     aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
749                                 }
750                             }
751                             else
752                                 aStack << aPool.Store(ocNoName, pExtName->GetName());
753                         }
754                         break;
755                         default:
756                         {
757                             aPool << ocBad;
758                             aPool >> aStack;
759                         }
760                     }
761                 }
762                 else
763                 {
764                     aPool << ocBad;
765                     aPool >> aStack;
766                 }
767                 break;
768             }
769             case 0x5A:
770             case 0x7A:
771             case 0x3A: // 3-D Cell Reference                    [    275]
772             case 0x5C:
773             case 0x7C:
774             case 0x3C: // Deleted 3-D Cell Reference            [    277]
775             {
776                 sal_uInt16 nIxti, nRw, nGrbitCol;
777                 SCTAB nTabFirst, nTabLast;
778 
779                 nIxti = aIn.ReaduInt16();
780                 nRw = aIn.ReaduInt16();
781                 nGrbitCol = aIn.ReaduInt16();
782 
783                 ExternalTabInfo aExtInfo;
784                 if (!Read3DTabReference(nIxti, nTabFirst, nTabLast, aExtInfo))
785                 {
786                     aPool << ocBad;
787                     aPool >> aStack;
788                     break;
789                 }
790 
791                 aSRD.SetAbsTab(nTabFirst);
792                 aSRD.SetFlag3D(true);
793 
794                 ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeNameOrCond );
795 
796                 switch ( nOp )
797                 {
798                     case 0x5C:
799                     case 0x7C:
800                     case 0x3C: // Deleted 3-D Cell Reference    [    277]
801                         // no information which part is deleted, set both
802                         aSRD.SetColDeleted( true );
803                         aSRD.SetRowDeleted( true );
804                 }
805 
806                 if (aExtInfo.mbExternal)
807                 {
808                     // nTabFirst and nTabLast are the indices of the referenced
809                     // sheets in the SUPBOOK record, hence do not represent
810                     // the actual indices of the original sheets since the
811                     // SUPBOOK record only stores referenced sheets and skips
812                     // the ones that are not referenced.
813 
814                     if (nTabLast != nTabFirst)
815                     {
816                         aCRD.Ref1 = aCRD.Ref2 = aSRD;
817                         aCRD.Ref2.SetAbsTab(nTabLast);
818                         aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
819                     }
820                     else
821                         aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aSRD);
822                 }
823                 else
824                 {
825                     if ( !ValidTab(nTabFirst))
826                         aSRD.SetTabDeleted( true );
827 
828                     if( nTabLast != nTabFirst )
829                     {
830                         aCRD.Ref1 = aCRD.Ref2 = aSRD;
831                         aCRD.Ref2.SetAbsTab(nTabLast);
832                         aCRD.Ref2.SetTabDeleted( !ValidTab(nTabLast) );
833                         aStack << aPool.Store( aCRD );
834                     }
835                     else
836                         aStack << aPool.Store( aSRD );
837                 }
838                 break;
839             }
840             case 0x5B:
841             case 0x7B:
842             case 0x3B: // 3-D Area Reference                    [    276]
843             case 0x5D:
844             case 0x7D:
845             case 0x3D: // Deleted 3-D Area Reference            [    277]
846             {
847                 sal_uInt16 nIxti, nRw1, nGrbitCol1, nRw2, nGrbitCol2;
848                 SCTAB nTabFirst, nTabLast;
849                 nIxti = aIn.ReaduInt16();
850                 nRw1 = aIn.ReaduInt16();
851                 nRw2 = aIn.ReaduInt16();
852                 nGrbitCol1 = aIn.ReaduInt16();
853                 nGrbitCol2 = aIn.ReaduInt16();
854 
855                 ExternalTabInfo aExtInfo;
856                 if (!Read3DTabReference(nIxti, nTabFirst, nTabLast, aExtInfo))
857                 {
858                     aPool << ocBad;
859                     aPool >> aStack;
860                     break;
861                 }
862                 ScSingleRefData &rR1 = aCRD.Ref1;
863                 ScSingleRefData &rR2 = aCRD.Ref2;
864 
865                 rR1.SetAbsTab(nTabFirst);
866                 rR2.SetAbsTab(nTabLast);
867                 rR1.SetFlag3D(true);
868                 rR2.SetFlag3D( nTabFirst != nTabLast );
869 
870                 ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeNameOrCond );
871                 ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeNameOrCond );
872 
873                 if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
874                     SetComplCol( aCRD );
875                 else if( IsComplRowRange( nRw1, nRw2 ) )
876                     SetComplRow( aCRD );
877 
878                 switch ( nOp )
879                 {
880                     case 0x5D:
881                     case 0x7D:
882                     case 0x3D: // Deleted 3-D Area Reference    [    277]
883                         // no information which part is deleted, set all
884                         rR1.SetColDeleted( true );
885                         rR1.SetRowDeleted( true );
886                         rR2.SetColDeleted( true );
887                         rR2.SetRowDeleted( true );
888                 }
889 
890                 if (aExtInfo.mbExternal)
891                 {
892                     aStack << aPool.StoreExtRef(aExtInfo.mnFileId, aExtInfo.maTabName, aCRD);
893                 }
894                 else
895                 {
896                     if ( !ValidTab(nTabFirst) )
897                         rR1.SetTabDeleted( true );
898                     if ( !ValidTab(nTabLast) )
899                         rR2.SetTabDeleted( true );
900 
901                     aStack << aPool.Store( aCRD );
902                 }
903                 break;
904             }
905             default:
906                 bError = true;
907         }
908         bError |= !aIn.IsValid();
909     }
910 
911     ConvErr eRet;
912 
913     if( bError )
914     {
915         aPool << ocBad;
916         aPool >> aStack;
917         rpTokArray = aPool.GetTokenArray( aStack.Get());
918         eRet = ConvErr::Ni;
919     }
920     else if( aIn.GetRecPos() != nEndPos )
921     {
922         aPool << ocBad;
923         aPool >> aStack;
924         rpTokArray = aPool.GetTokenArray( aStack.Get());
925         eRet = ConvErr::Count;
926     }
927     else if( bArrayFormula )
928     {
929         rpTokArray = nullptr;
930         eRet = ConvErr::OK;
931     }
932     else
933     {
934         rpTokArray = aPool.GetTokenArray( aStack.Get());
935         eRet = ConvErr::OK;
936     }
937 
938     aIn.Seek( nEndPos );
939 
940     if( eRet == ConvErr::OK)
941         ReadExtensions( aExtensions, aIn );
942 
943     return eRet;
944 }
945 
946 // stream seeks to first byte after <nFormulaLen>
Convert(ScRangeListTabs & rRangeList,XclImpStream & aIn,std::size_t nFormulaLen,SCTAB nTab,const FORMULA_TYPE eFT)947 ConvErr ExcelToSc8::Convert( ScRangeListTabs& rRangeList, XclImpStream& aIn, std::size_t nFormulaLen,
948                               SCTAB nTab, const FORMULA_TYPE eFT )
949 {
950     sal_uInt8                   nOp, nLen;
951     bool                    bError = false;
952     const bool              bCondFormat = eFT == FT_CondFormat;
953     const bool              bRangeName = eFT == FT_RangeName || bCondFormat;
954     const bool              bSharedFormula = eFT == FT_SharedFormula;
955     const bool              bRNorSF = bRangeName || bSharedFormula;
956 
957     ScSingleRefData         aSRD;
958     ScComplexRefData            aCRD;
959 
960     if( nFormulaLen == 0 )
961         return ConvErr::OK;
962 
963     std::size_t nEndPos = aIn.GetRecPos() + nFormulaLen;
964 
965     while( (aIn.GetRecPos() < nEndPos) && !bError )
966     {
967         nOp = aIn.ReaduInt8();
968 
969         // always reset flags
970         aSRD.InitFlags();
971         aCRD.InitFlags();
972 
973         switch( nOp )   //                              book page:
974         {           //                                      SDK4 SDK5
975             case 0x01: // Array Formula                         [325    ]
976                        // Array Formula or Shared Formula       [    277]
977                 aIn.Ignore( 4 );
978                 break;
979             case 0x02: // Data Table                            [325 277]
980                 aIn.Ignore( 4 );
981                 break;
982             case 0x03: // Addition                              [312 264]
983             case 0x04: // Subtraction                           [313 264]
984             case 0x05: // Multiplication                        [313 264]
985             case 0x06: // Division                              [313 264]
986             case 0x07: // Exponetiation                         [313 265]
987             case 0x08: // Concatenation                         [313 265]
988             case 0x09: // Less Than                             [313 265]
989             case 0x0A: // Less Than or Equal                    [313 265]
990             case 0x0B: // Equal                                 [313 265]
991             case 0x0C: // Greater Than or Equal                 [313 265]
992             case 0x0D: // Greater Than                          [313 265]
993             case 0x0E: // Not Equal                             [313 265]
994             case 0x0F: // Intersection                          [314 265]
995             case 0x10: // Union                                 [314 265]
996             case 0x11: // Range                                 [314 265]
997             case 0x12: // Unary Plus                            [312 264]
998             case 0x13: // Unary Minus                           [312 264]
999             case 0x14: // Percent Sign                          [312 264]
1000             case 0x15: // Parenthesis                           [326 278]
1001             case 0x16: // Missing Argument                      [314 266]
1002                 break;
1003             case 0x17: // String Constant                       [314 266]
1004                 nLen = aIn.ReaduInt8();        // Why?
1005 
1006                 aIn.IgnoreUniString( nLen );        // reads Grbit even if nLen==0
1007                 break;
1008             case 0x19: // Special Attribute                     [327 279]
1009             {
1010                 sal_uInt16 nData(0), nFactor(0);
1011 
1012                 sal_uInt8 nOpt = aIn.ReaduInt8();
1013                 nData = aIn.ReaduInt16();
1014                 nFactor = 2;
1015 
1016                 if( nOpt & 0x04 )
1017                 {
1018                     // nFactor -> skip bytes or words    AttrChoose
1019                     ++nData;
1020                     aIn.Ignore(static_cast<std::size_t>(nData) * nFactor);
1021                 }
1022             }
1023                 break;
1024             case 0x1C: // Error Value                           [314 266]
1025             case 0x1D: // Boolean                               [315 266]
1026                 aIn.Ignore( 1 );
1027                 break;
1028             case 0x1E: // Integer                               [315 266]
1029                 aIn.Ignore( 2 );
1030                 break;
1031             case 0x1F: // Number                                [315 266]
1032                 aIn.Ignore( 8 );
1033                 break;
1034             case 0x40:
1035             case 0x60:
1036             case 0x20: // Array Constant                        [317 268]
1037                 aIn.Ignore( 7 );
1038                 break;
1039             case 0x41:
1040             case 0x61:
1041             case 0x21: // Function, Fixed Number of Arguments   [333 282]
1042                 aIn.Ignore( 2 );
1043                 break;
1044             case 0x42:
1045             case 0x62:
1046             case 0x22: // Function, Variable Number of Arg.     [333 283]
1047                 aIn.Ignore( 3 );
1048                 break;
1049             case 0x43:
1050             case 0x63:
1051             case 0x23: // Name                                  [318 269]
1052                 aIn.Ignore( 4 );
1053                 break;
1054             case 0x44:
1055             case 0x64:
1056             case 0x24: // Cell Reference                        [319 270]
1057             {
1058                 sal_uInt16          nCol, nRow;
1059 
1060                 nRow = aIn.ReaduInt16();
1061                 nCol = aIn.ReaduInt16();
1062 
1063                 aSRD.SetRelTab(0);
1064                 aSRD.SetFlag3D( bRangeName && !bCondFormat );
1065 
1066                 ExcRelToScRel8( nRow, nCol, aSRD, bRangeName );
1067 
1068                 rRangeList.Append(aSRD.toAbs(aEingPos), nTab);
1069             }
1070                 break;
1071             case 0x45:
1072             case 0x65:
1073             case 0x25: // Area Reference                        [320 270]
1074             {
1075                 sal_uInt16          nRowFirst, nRowLast;
1076                 sal_uInt16          nColFirst, nColLast;
1077                 ScSingleRefData &rSRef1 = aCRD.Ref1;
1078                 ScSingleRefData &rSRef2 = aCRD.Ref2;
1079 
1080                 nRowFirst = aIn.ReaduInt16();
1081                 nRowLast = aIn.ReaduInt16();
1082                 nColFirst = aIn.ReaduInt16();
1083                 nColLast = aIn.ReaduInt16();
1084 
1085                 rSRef1.SetRelTab(0);
1086                 rSRef2.SetRelTab(0);
1087                 rSRef1.SetFlag3D( bRangeName && !bCondFormat );
1088                 rSRef2.SetFlag3D( bRangeName && !bCondFormat );
1089 
1090                 ExcRelToScRel8( nRowFirst, nColFirst, aCRD.Ref1, bRangeName );
1091                 ExcRelToScRel8( nRowLast, nColLast, aCRD.Ref2, bRangeName );
1092 
1093                 if( IsComplColRange( nColFirst, nColLast ) )
1094                     SetComplCol( aCRD );
1095                 else if( IsComplRowRange( nRowFirst, nRowLast ) )
1096                     SetComplRow( aCRD );
1097 
1098                 rRangeList.Append(aCRD.toAbs(aEingPos), nTab);
1099             }
1100                 break;
1101             case 0x46:
1102             case 0x66:
1103             case 0x26: // Constant Reference Subexpression      [321 271]
1104             case 0x47:
1105             case 0x67:
1106             case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
1107             case 0x48:
1108             case 0x68:
1109             case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
1110                 aIn.Ignore( 6 );   // There isn't any more
1111                 break;
1112             case 0x49:
1113             case 0x69:
1114             case 0x29: // Variable Reference Subexpression      [331 281]
1115                 aIn.Ignore( 2 );   // There isn't any more
1116                 break;
1117             case 0x4A:
1118             case 0x6A:
1119             case 0x2A: // Deleted Cell Reference                [323 273]
1120                 aIn.Ignore( 3 );
1121                 break;
1122             case 0x4B:
1123             case 0x6B:
1124             case 0x2B: // Deleted Area Reference                [323 273]
1125                 aIn.Ignore( 6 );
1126                 break;
1127             case 0x4C:
1128             case 0x6C:
1129             case 0x2C: // Cell Reference Within a Name          [323    ]
1130                        // Cell Reference Within a Shared Formula[    273]
1131             {
1132                 sal_uInt16      nRow, nCol;
1133 
1134                 nRow = aIn.ReaduInt16();
1135                 nCol = aIn.ReaduInt16();
1136 
1137                 aSRD.SetRelTab(0);
1138                 aSRD.SetFlag3D( bRangeName );
1139 
1140                 ExcRelToScRel8( nRow, nCol, aSRD, bRNorSF );
1141 
1142                 rRangeList.Append(aSRD.toAbs(aEingPos), nTab);
1143             }
1144                 break;
1145             case 0x4D:
1146             case 0x6D:
1147             case 0x2D: // Area Reference Within a Name          [324    ]
1148             {      // Area Reference Within a Shared Formula[    274]
1149                 sal_uInt16                  nRowFirst, nRowLast;
1150                 sal_uInt16                  nColFirst, nColLast;
1151 
1152                 aCRD.Ref1.SetRelTab(0);
1153                 aCRD.Ref2.SetRelTab(0);
1154                 aCRD.Ref1.SetFlag3D( bRangeName );
1155                 aCRD.Ref2.SetFlag3D( bRangeName );
1156 
1157                 nRowFirst = aIn.ReaduInt16();
1158                 nRowLast = aIn.ReaduInt16();
1159                 nColFirst = aIn.ReaduInt16(  );
1160                 nColLast = aIn.ReaduInt16();
1161 
1162                 ExcRelToScRel8( nRowFirst, nColFirst, aCRD.Ref1, bRNorSF );
1163                 ExcRelToScRel8( nRowLast, nColLast, aCRD.Ref2, bRNorSF );
1164 
1165                 if( IsComplColRange( nColFirst, nColLast ) )
1166                     SetComplCol( aCRD );
1167                 else if( IsComplRowRange( nRowFirst, nRowLast ) )
1168                     SetComplRow( aCRD );
1169 
1170                 rRangeList.Append(aCRD.toAbs(aEingPos), nTab);
1171             }
1172                 break;
1173             case 0x4E:
1174             case 0x6E:
1175             case 0x2E: // Reference Subexpression Within a Name [332 282]
1176             case 0x4F:
1177             case 0x6F:
1178             case 0x2F: // Incomplete Reference Subexpression... [332 282]
1179             case 0x58:
1180             case 0x78:
1181             case 0x38: // Command-Equivalent Function           [333    ]
1182                 aIn.Ignore( 2 );
1183                 break;
1184             case 0x59:
1185             case 0x79:
1186             case 0x39: // Name or External Name                 [    275]
1187                 aIn.Ignore( 24 );
1188                 break;
1189             case 0x5A:
1190             case 0x7A:
1191             case 0x3A: // 3-D Cell Reference                    [    275]
1192             {
1193                 sal_uInt16          nIxti, nRw, nGrbitCol;
1194 
1195                 nIxti = aIn.ReaduInt16();
1196                 nRw = aIn.ReaduInt16();
1197                 nGrbitCol = aIn.ReaduInt16();
1198 
1199                 SCTAB nFirstScTab, nLastScTab;
1200                 if( rLinkMan.GetScTabRange( nFirstScTab, nLastScTab, nIxti ) )
1201                 {
1202                     aSRD.SetAbsTab(nFirstScTab);
1203                     aSRD.SetFlag3D(true);
1204 
1205                     ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeName );
1206 
1207                     if( nFirstScTab != nLastScTab )
1208                     {
1209                         aCRD.Ref1 = aSRD;
1210                         aCRD.Ref2 = aSRD;
1211                         aCRD.Ref2.SetAbsTab(nLastScTab);
1212                         rRangeList.Append(aCRD.toAbs(aEingPos), nTab);
1213                     }
1214                     else
1215                         rRangeList.Append(aSRD.toAbs(aEingPos), nTab);
1216                 }
1217             }
1218                 break;
1219             case 0x5B:
1220             case 0x7B:
1221             case 0x3B: // 3-D Area Reference                    [    276]
1222             {
1223                 sal_uInt16          nIxti, nRw1, nGrbitCol1, nRw2, nGrbitCol2;
1224 
1225                 nIxti = aIn.ReaduInt16();
1226                 nRw1 = aIn.ReaduInt16();
1227                 nRw2 = aIn.ReaduInt16();
1228                 nGrbitCol1 = aIn.ReaduInt16();
1229                 nGrbitCol2 = aIn.ReaduInt16();
1230 
1231                 SCTAB nFirstScTab, nLastScTab;
1232                 if( rLinkMan.GetScTabRange( nFirstScTab, nLastScTab, nIxti ) )
1233                 {
1234                     ScSingleRefData &rR1 = aCRD.Ref1;
1235                     ScSingleRefData &rR2 = aCRD.Ref2;
1236 
1237                     rR1.SetAbsTab(nFirstScTab);
1238                     rR2.SetAbsTab(nLastScTab);
1239                     rR1.SetFlag3D(true);
1240                     rR2.SetFlag3D( nFirstScTab != nLastScTab );
1241 
1242                     ExcRelToScRel8( nRw1, nGrbitCol1, aCRD.Ref1, bRangeName );
1243                     ExcRelToScRel8( nRw2, nGrbitCol2, aCRD.Ref2, bRangeName );
1244 
1245                     if( IsComplColRange( nGrbitCol1, nGrbitCol2 ) )
1246                         SetComplCol( aCRD );
1247                     else if( IsComplRowRange( nRw1, nRw2 ) )
1248                         SetComplRow( aCRD );
1249 
1250                     rRangeList.Append(aCRD.toAbs(aEingPos), nTab);
1251                 }
1252             }
1253                 break;
1254             case 0x5C:
1255             case 0x7C:
1256             case 0x3C: // Deleted 3-D Cell Reference            [    277]
1257                 aIn.Ignore( 6 );
1258                 break;
1259             case 0x5D:
1260             case 0x7D:
1261             case 0x3D: // Deleted 3-D Area Reference            [    277]
1262                 aIn.Ignore( 10 );
1263                 break;
1264             default:
1265                 bError = true;
1266         }
1267         bError |= !aIn.IsValid();
1268     }
1269 
1270     ConvErr eRet;
1271 
1272     if( bError )
1273         eRet = ConvErr::Ni;
1274     else if( aIn.GetRecPos() != nEndPos )
1275         eRet = ConvErr::Count;
1276     else
1277         eRet = ConvErr::OK;
1278 
1279     aIn.Seek( nEndPos );
1280     return eRet;
1281 }
1282 
ConvertExternName(std::unique_ptr<ScTokenArray> & rpArray,XclImpStream & rStrm,std::size_t nFormulaLen,const OUString & rUrl,const vector<OUString> & rTabNames)1283 void ExcelToSc8::ConvertExternName( std::unique_ptr<ScTokenArray>& rpArray, XclImpStream& rStrm, std::size_t nFormulaLen,
1284                                        const OUString& rUrl, const vector<OUString>& rTabNames )
1285 {
1286     if( !GetDocShell() )
1287         return;
1288 
1289     OUString aFileUrl = ScGlobal::GetAbsDocName(rUrl, GetDocShell());
1290 
1291     sal_uInt8               nOp, nByte;
1292     bool                    bError = false;
1293 
1294     ScSingleRefData           aSRD;
1295     ScComplexRefData            aCRD;
1296 
1297     if (nFormulaLen == 0)
1298     {
1299         aPool.Store("-/-");
1300         aPool >> aStack;
1301         rpArray = aPool.GetTokenArray( aStack.Get());
1302         return;
1303     }
1304 
1305     ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1306     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFileUrl);
1307     sal_uInt16 nTabCount = static_cast< sal_uInt16 >( rTabNames.size() );
1308 
1309     std::size_t nEndPos = rStrm.GetRecPos() + nFormulaLen;
1310 
1311     while( (rStrm.GetRecPos() < nEndPos) && !bError )
1312     {
1313         nOp = rStrm.ReaduInt8();
1314 
1315         // always reset flags
1316         aSRD.InitFlags();
1317         aCRD.InitFlags();
1318 
1319         switch( nOp )
1320         {
1321             case 0x1C: // Error Value
1322             {
1323                 nByte = rStrm.ReaduInt8();
1324                 DefTokenId eOc;
1325                 switch( nByte )
1326                 {
1327                     case EXC_ERR_NULL:
1328                     case EXC_ERR_DIV0:
1329                     case EXC_ERR_VALUE:
1330                     case EXC_ERR_REF:
1331                     case EXC_ERR_NAME:
1332                     case EXC_ERR_NUM:   eOc = ocStop;       break;
1333                     case EXC_ERR_NA:    eOc = ocNotAvail;   break;
1334                     default:            eOc = ocNoName;
1335                 }
1336                 aPool << eOc;
1337                 if( eOc != ocStop )
1338                     aPool << ocOpen << ocClose;
1339                 aPool >> aStack;
1340             }
1341             break;
1342             case 0x3A:
1343             {
1344                 // cell reference in external range name
1345                 sal_uInt16 nExtTab1, nExtTab2, nRow, nGrbitCol;
1346                 nExtTab1 = rStrm.ReaduInt16();
1347                 nExtTab2 = rStrm.ReaduInt16();
1348                 nRow = rStrm.ReaduInt16();
1349                 nGrbitCol = rStrm.ReaduInt16();
1350                 if (nExtTab1 >= nTabCount || nExtTab2 >= nTabCount)
1351                 {
1352                     bError = true;
1353                     break;
1354                 }
1355 
1356                 aSRD.SetAbsTab(nExtTab1);
1357                 aSRD.SetFlag3D(true);
1358                 ExcRelToScRel8(nRow, nGrbitCol, aSRD, true);
1359                 aCRD.Ref1 = aCRD.Ref2 = aSRD;
1360                 OUString aTabName = rTabNames[nExtTab1];
1361 
1362                 if (nExtTab1 == nExtTab2)
1363                 {
1364                     // single cell reference
1365                     aStack << aPool.StoreExtRef(nFileId, aTabName, aSRD);
1366                 }
1367                 else
1368                 {
1369                     // area reference
1370                     aCRD.Ref2.SetAbsTab(nExtTab2);
1371                     aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
1372                 }
1373             }
1374             break;
1375             case 0x3B:
1376             {
1377                 // area reference
1378                 sal_uInt16 nExtTab1, nExtTab2, nRow1, nRow2, nGrbitCol1, nGrbitCol2;
1379                 nExtTab1 = rStrm.ReaduInt16();
1380                 nExtTab2 = rStrm.ReaduInt16();
1381                 nRow1 = rStrm.ReaduInt16();
1382                 nRow2 = rStrm.ReaduInt16();
1383                 nGrbitCol1 = rStrm.ReaduInt16();
1384                 nGrbitCol2 = rStrm.ReaduInt16();
1385 
1386                 if (nExtTab1 >= nTabCount || nExtTab2 >= nTabCount)
1387                 {
1388                     bError = true;
1389                     break;
1390                 }
1391 
1392                 ScSingleRefData& rR1 = aCRD.Ref1;
1393                 ScSingleRefData& rR2 = aCRD.Ref2;
1394 
1395                 rR1.SetAbsTab(nExtTab1);
1396                 rR1.SetFlag3D(true);
1397                 ExcRelToScRel8(nRow1, nGrbitCol1, rR1, true);
1398 
1399                 rR2.SetAbsTab(nExtTab2);
1400                 rR2.SetFlag3D(true);
1401                 ExcRelToScRel8(nRow2, nGrbitCol2, rR2, true);
1402 
1403                 OUString aTabName = rTabNames[nExtTab1];
1404                 aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
1405             }
1406             break;
1407             default:
1408                 bError = true;
1409         }
1410         bError |= !rStrm.IsValid();
1411     }
1412 
1413     if( bError )
1414     {
1415         aPool << ocBad;
1416         aPool >> aStack;
1417         rpArray = aPool.GetTokenArray( aStack.Get());
1418     }
1419     else if( rStrm.GetRecPos() != nEndPos )
1420     {
1421         aPool << ocBad;
1422         aPool >> aStack;
1423         rpArray = aPool.GetTokenArray( aStack.Get());
1424     }
1425     else
1426     {
1427         rpArray = aPool.GetTokenArray( aStack.Get());
1428     }
1429 
1430     rStrm.Seek(nEndPos);
1431 }
1432 
ExcRelToScRel8(sal_uInt16 nRow,sal_uInt16 nC,ScSingleRefData & rSRD,const bool bName)1433 void ExcelToSc8::ExcRelToScRel8( sal_uInt16 nRow, sal_uInt16 nC, ScSingleRefData &rSRD, const bool bName )
1434 {
1435     const bool bColRel = ( nC & 0x4000 ) != 0;
1436     const bool bRowRel = ( nC & 0x8000 ) != 0;
1437     const sal_uInt8 nCol = static_cast<sal_uInt8>(nC);
1438 
1439     if( bName )
1440     {
1441         // C O L
1442         if( bColRel )
1443         {
1444             SCCOL nRelCol = static_cast<sal_Int8>(nC);
1445             sal_Int16 nDiff = aEingPos.Col() + nRelCol;
1446             if ( nDiff < 0)
1447             {
1448                 // relative column references wrap around
1449                 nRelCol = static_cast<sal_Int16>(256 + static_cast<int>(nRelCol));
1450             }
1451             rSRD.SetRelCol(nRelCol);
1452         }
1453         else
1454             rSRD.SetAbsCol(static_cast<SCCOL>(nCol));
1455 
1456         // R O W
1457         if( bRowRel )
1458         {
1459             SCROW nRelRow = static_cast<sal_Int16>(nRow);
1460             sal_Int32 nDiff = aEingPos.Row() + nRelRow;
1461             if (nDiff < 0)
1462             {
1463                 // relative row references wrap around
1464                 nRelRow = 65536 + nRelRow;
1465             }
1466             rSRD.SetRelRow(nRelRow);
1467         }
1468         else
1469             rSRD.SetAbsRow(std::min( static_cast<SCROW>(nRow), GetDoc().MaxRow()));
1470     }
1471     else
1472     {
1473         // C O L
1474         if ( bColRel )
1475             rSRD.SetRelCol(static_cast<SCCOL>(nCol) - aEingPos.Col());
1476         else
1477             rSRD.SetAbsCol(nCol);
1478 
1479         // R O W
1480         if ( bRowRel )
1481             rSRD.SetRelRow(static_cast<SCROW>(nRow) - aEingPos.Row());
1482         else
1483             rSRD.SetAbsRow(nRow);
1484     }
1485 }
1486 
1487 // stream seeks to first byte after <nLen>
GetAbsRefs(ScRangeList & r,XclImpStream & aIn,std::size_t nLen)1488 void ExcelToSc8::GetAbsRefs( ScRangeList& r, XclImpStream& aIn, std::size_t nLen )
1489 {
1490     sal_uInt8                   nOp;
1491     sal_uInt16                  nRow1, nRow2, nCol1, nCol2;
1492     SCTAB                                   nTab1, nTab2;
1493     sal_uInt16                  nIxti;
1494 
1495     std::size_t nSeek;
1496 
1497     std::size_t nEndPos = aIn.GetRecPos() + nLen;
1498 
1499     while( aIn.IsValid() && (aIn.GetRecPos() < nEndPos) )
1500     {
1501         nOp = aIn.ReaduInt8();
1502         nSeek = 0;
1503 
1504         switch( nOp )
1505         {
1506             case 0x44:
1507             case 0x64:
1508             case 0x24: // Cell Reference                        [319 270]
1509             case 0x4C:
1510             case 0x6C:
1511             case 0x2C: // Cell Reference Within a Name          [323    ]
1512                        // Cell Reference Within a Shared Formula[    273]
1513                 nRow1 = aIn.ReaduInt16();
1514                 nCol1 = aIn.ReaduInt16();
1515 
1516                 nRow2 = nRow1;
1517                 nCol2 = nCol1;
1518                 nTab1 = nTab2 = GetCurrScTab();
1519                 goto _common;
1520             case 0x45:
1521             case 0x65:
1522             case 0x25: // Area Reference                        [320 270]
1523             case 0x4D:
1524             case 0x6D:
1525             case 0x2D: // Area Reference Within a Name          [324    ]
1526                        // Area Reference Within a Shared Formula[    274]
1527                 nRow1 = aIn.ReaduInt16();
1528                 nRow2 = aIn.ReaduInt16();
1529                 nCol1 = aIn.ReaduInt16();
1530                 nCol2 = aIn.ReaduInt16();
1531 
1532                 nTab1 = nTab2 = GetCurrScTab();
1533                 goto _common;
1534             case 0x5A:
1535             case 0x7A:
1536             case 0x3A: // 3-D Cell Reference                    [    275]
1537                 nIxti = aIn.ReaduInt16();
1538                 nRow1 = aIn.ReaduInt16();
1539                 nCol1 = aIn.ReaduInt16();
1540 
1541                 nRow2 = nRow1;
1542                 nCol2 = nCol1;
1543 
1544                 goto _3d_common;
1545             case 0x5B:
1546             case 0x7B:
1547             case 0x3B: // 3-D Area Reference                    [    276]
1548                 nIxti = aIn.ReaduInt16();
1549                 nRow1 = aIn.ReaduInt16();
1550                 nRow2 = aIn.ReaduInt16();
1551                 nCol1 = aIn.ReaduInt16();
1552                 nCol2 = aIn.ReaduInt16();
1553 
1554     _3d_common:
1555                 // skip references to deleted sheets
1556                 if( !rLinkMan.GetScTabRange( nTab1, nTab2, nIxti ) || !ValidTab( nTab1 ) || !ValidTab( nTab2 ) )
1557                     break;
1558 
1559                 goto _common;
1560     _common:
1561                 // do not check abs/rel flags, linked controls have set them!
1562                 {
1563                     ScRange aScRange;
1564                     nCol1 &= 0x3FFF;
1565                     nCol2 &= 0x3FFF;
1566                     if( GetAddressConverter().ConvertRange( aScRange, XclRange( nCol1, nRow1, nCol2, nRow2 ), nTab1, nTab2, true ) )
1567                         r.push_back( aScRange );
1568                 }
1569                 break;
1570             case 0x1C: // Error Value                           [314 266]
1571             case 0x1D: // Boolean                               [315 266]
1572                 nSeek = 1;
1573                 break;
1574             case 0x1E: // Integer                               [315 266]
1575             case 0x41:
1576             case 0x61:
1577             case 0x21: // Function, Fixed Number of Arguments   [333 282]
1578             case 0x49:
1579             case 0x69:
1580             case 0x29: // Variable Reference Subexpression      [331 281]
1581             case 0x4E:
1582             case 0x6E:
1583             case 0x2E: // Reference Subexpression Within a Name [332 282]
1584             case 0x4F:
1585             case 0x6F:
1586             case 0x2F: // Incomplete Reference Subexpression... [332 282]
1587             case 0x58:
1588             case 0x78:
1589             case 0x38: // Command-Equivalent Function           [333    ]
1590                 nSeek = 2;
1591                 break;
1592             case 0x42:
1593             case 0x62:
1594             case 0x22: // Function, Variable Number of Arg.     [333 283]
1595                 nSeek = 3;
1596                 break;
1597             case 0x01: // Array Formula                         [325    ]
1598             case 0x02: // Data Table                            [325 277]
1599             case 0x43:
1600             case 0x63:
1601             case 0x23: // Name                                  [318 269]
1602             case 0x4A:
1603             case 0x6A:
1604             case 0x2A: // Deleted Cell Reference                [323 273]
1605                 nSeek = 4;
1606                 break;
1607             case 0x46:
1608             case 0x66:
1609             case 0x26: // Constant Reference Subexpression      [321 271]
1610             case 0x47:
1611             case 0x67:
1612             case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
1613             case 0x48:
1614             case 0x68:
1615             case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
1616             case 0x5C:
1617             case 0x7C:
1618             case 0x3C: // Deleted 3-D Cell Reference            [    277]
1619             case 0x59:
1620             case 0x79:
1621             case 0x39: // Name or External Name                 [    275]
1622                 nSeek = 6;
1623                 break;
1624             case 0x40:
1625             case 0x60:
1626             case 0x20: // Array Constant                        [317 268]
1627                 nSeek = 7;
1628                 break;
1629             case 0x1F: // Number                                [315 266]
1630             case 0x4B:
1631             case 0x6B:
1632             case 0x2B: // Deleted Area Reference                [323 273]
1633                 nSeek = 8;
1634                 break;
1635             case 0x5D:
1636             case 0x7D:
1637             case 0x3D: // Deleted 3-D Area Reference            [    277]
1638                 nSeek = 10;
1639                 break;
1640             case 0x17: // String Constant                       [314 266]
1641             {
1642                 sal_uInt8 nStrLen;
1643                 nStrLen = aIn.ReaduInt8();
1644                 aIn.IgnoreUniString( nStrLen );     // reads Grbit even if nLen==0
1645                 nSeek = 0;
1646             }
1647                 break;
1648             case 0x19: // Special Attribute                     [327 279]
1649             {
1650                 sal_uInt16  nData;
1651                 sal_uInt8   nOpt;
1652                 nOpt = aIn.ReaduInt8();
1653                 nData = aIn.ReaduInt16();
1654                 if( nOpt & 0x04 )
1655                 {// nFactor -> skip bytes or words    AttrChoose
1656                     nData++;
1657                     nSeek = nData * 2;
1658             }
1659             }
1660                 break;
1661         }
1662 
1663         aIn.Ignore( nSeek );
1664     }
1665     aIn.Seek( nEndPos );
1666 }
1667 
1668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1669