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