xref: /trunk/main/oox/source/dump/xlsbdumper.cxx (revision ca5ec200)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/dump/xlsbdumper.hxx"
25 
26 #include <com/sun/star/io/XTextInputStream.hpp>
27 #include "oox/core/filterbase.hxx"
28 #include "oox/dump/biffdumper.hxx"
29 #include "oox/dump/oledumper.hxx"
30 #include "oox/dump/pptxdumper.hxx"
31 #include "oox/helper/zipstorage.hxx"
32 #include "oox/ole/olestorage.hxx"
33 #include "oox/xls/biffhelper.hxx"
34 #include "oox/xls/formulabase.hxx"
35 #include "oox/xls/richstring.hxx"
36 
37 #if OOX_INCLUDE_DUMPER
38 
39 namespace oox {
40 namespace dump {
41 namespace xlsb {
42 
43 // ============================================================================
44 
45 using namespace ::com::sun::star::io;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::util;
49 using namespace ::oox::xls;
50 
51 using ::comphelper::MediaDescriptor;
52 using ::oox::core::FilterBase;
53 using ::rtl::OUString;
54 using ::rtl::OUStringBuffer;
55 
56 // ============================================================================
57 
58 namespace {
59 
60 const sal_uInt8 BIFF12_STRINGFLAG_FONTS         = 0x01;
61 const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS     = 0x02;
62 
63 const sal_uInt16 BIFF12_OLEOBJECT_LINKED        = 0x0001;
64 
65 } // namespace
66 
67 // ============================================================================
68 
RecordObjectBase()69 RecordObjectBase::RecordObjectBase()
70 {
71 }
72 
~RecordObjectBase()73 RecordObjectBase::~RecordObjectBase()
74 {
75 }
76 
construct(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,const OUString & rSysFileName)77 void RecordObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
78 {
79     mxBiffStrm.reset( new SequenceInputStream( getRecordDataSequence() ) );
80     SequenceRecordObjectBase::construct( rParent, rxStrm, rSysFileName, mxBiffStrm, "RECORD-NAMES", "SIMPLE-RECORDS" );
81     if( SequenceRecordObjectBase::implIsValid() )
82         mxErrCodes = cfg().getNameList( "ERRORCODES" );
83 }
84 
construct(const RecordObjectBase & rParent)85 void RecordObjectBase::construct( const RecordObjectBase& rParent )
86 {
87     *this = rParent;
88 }
89 
implReadRecordHeader(BinaryInputStream & rBaseStrm,sal_Int64 & ornRecId,sal_Int64 & ornRecSize)90 bool RecordObjectBase::implReadRecordHeader( BinaryInputStream& rBaseStrm, sal_Int64& ornRecId, sal_Int64& ornRecSize )
91 {
92     sal_Int32 nRecId = 0, nRecSize = 0;
93     bool bValid = readCompressedInt( rBaseStrm, nRecId ) && (nRecId >= 0) && readCompressedInt( rBaseStrm, nRecSize ) && (nRecSize >= 0);
94     ornRecId = nRecId;
95     ornRecSize = nRecSize;
96     return bValid;
97 }
98 
getErrorName(sal_uInt8 nErrCode) const99 OUString RecordObjectBase::getErrorName( sal_uInt8 nErrCode ) const
100 {
101     return cfg().getName( mxErrCodes, nErrCode );
102 }
103 
104 // ------------------------------------------------------------------------
105 
readAddress(Address & orAddress)106 void RecordObjectBase::readAddress( Address& orAddress )
107 {
108     *mxStrm >> orAddress.mnRow >> orAddress.mnCol;
109 }
110 
readRange(Range & orRange)111 void RecordObjectBase::readRange( Range& orRange )
112 {
113     *mxStrm >> orRange.maFirst.mnRow >> orRange.maLast.mnRow >> orRange.maFirst.mnCol >> orRange.maLast.mnCol;
114 }
115 
readRangeList(RangeList & orRanges)116 void RecordObjectBase::readRangeList( RangeList& orRanges )
117 {
118     sal_Int32 nCount;
119     *mxStrm >> nCount;
120     if( nCount >= 0 )
121     {
122         orRanges.resize( getLimitedValue< size_t, sal_Int32 >( nCount, 0, SAL_MAX_UINT16 ) );
123         for( RangeList::iterator aIt = orRanges.begin(), aEnd = orRanges.end(); !mxStrm->isEof() && (aIt != aEnd); ++aIt )
124             readRange( *aIt );
125     }
126     else
127         orRanges.clear();
128 }
129 
130 // ----------------------------------------------------------------------------
131 
writeBooleanItem(const String & rName,sal_uInt8 nBool)132 void RecordObjectBase::writeBooleanItem( const String& rName, sal_uInt8 nBool )
133 {
134     writeDecItem( rName, nBool, "BOOLEAN" );
135 }
136 
writeErrorCodeItem(const String & rName,sal_uInt8 nErrCode)137 void RecordObjectBase::writeErrorCodeItem( const String& rName, sal_uInt8 nErrCode )
138 {
139     writeHexItem( rName, nErrCode, mxErrCodes );
140 }
141 
writeFontPortions(const FontPortionModelList & rPortions)142 void RecordObjectBase::writeFontPortions( const FontPortionModelList& rPortions )
143 {
144     if( !rPortions.empty() )
145     {
146         writeDecItem( "font-count", static_cast< sal_uInt32 >( rPortions.size() ) );
147         IndentGuard aIndGuard( mxOut );
148         TableGuard aTabGuard( mxOut, 14 );
149         for( FontPortionModelList::const_iterator aIt = rPortions.begin(), aEnd = rPortions.end(); aIt != aEnd; ++aIt )
150         {
151             MultiItemsGuard aMultiGuard( mxOut );
152             writeDecItem( "char-pos", aIt->mnPos );
153             writeDecItem( "font-id", aIt->mnFontId, "FONTNAMES" );
154         }
155     }
156 }
157 
writePhoneticPortions(const PhoneticPortionModelList & rPortions)158 void RecordObjectBase::writePhoneticPortions( const PhoneticPortionModelList& rPortions )
159 {
160     if( !rPortions.empty() )
161     {
162         writeDecItem( "portion-count", static_cast< sal_uInt32 >( rPortions.size() ) );
163         IndentGuard aIndGuard( mxOut );
164         TableGuard aTabGuard( mxOut, 14, 21 );
165         for( PhoneticPortionModelList::const_iterator aIt = rPortions.begin(), aEnd = rPortions.end(); aIt != aEnd; ++aIt )
166         {
167             MultiItemsGuard aMultiGuard( mxOut );
168             writeDecItem( "char-pos", aIt->mnPos );
169             writeDecItem( "base-text-start", aIt->mnBasePos );
170             writeDecItem( "base-text-length", aIt->mnBaseLen );
171         }
172     }
173 }
174 
175 // ----------------------------------------------------------------------------
176 
dumpBoolean(const String & rName)177 sal_uInt8 RecordObjectBase::dumpBoolean( const String& rName )
178 {
179     sal_uInt8 nBool;
180     *mxStrm >> nBool;
181     writeBooleanItem( rName( "boolean" ), nBool );
182     return nBool;
183 }
184 
dumpErrorCode(const String & rName)185 sal_uInt8 RecordObjectBase::dumpErrorCode( const String& rName )
186 {
187     sal_uInt8 nErrCode;
188     *mxStrm >> nErrCode;
189     writeErrorCodeItem( rName( "error-code" ), nErrCode );
190     return nErrCode;
191 }
192 
dumpString(const String & rName,bool bRich,bool b32BitLen)193 OUString RecordObjectBase::dumpString( const String& rName, bool bRich, bool b32BitLen )
194 {
195     sal_uInt8 nFlags = bRich ? dumpHex< sal_uInt8 >( "flags", "STRING-FLAGS" ) : 0;
196 
197     OUString aString = BiffHelper::readString( *mxBiffStrm, b32BitLen );
198     writeStringItem( rName( "text" ), aString );
199 
200     // --- formatting ---
201     if( getFlag( nFlags, BIFF12_STRINGFLAG_FONTS ) )
202     {
203         IndentGuard aIndGuard( mxOut );
204         FontPortionModelList aPortions;
205         aPortions.importPortions( *mxBiffStrm );
206         writeFontPortions( aPortions );
207     }
208 
209     // --- phonetic text ---
210     if( getFlag( nFlags, BIFF12_STRINGFLAG_PHONETICS ) )
211     {
212         IndentGuard aIndGuard( mxOut );
213         dumpString( "phonetic-text" );
214         PhoneticPortionModelList aPortions;
215         aPortions.importPortions( *mxBiffStrm );
216         writePhoneticPortions( aPortions );
217         dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" );
218         dumpHex< sal_uInt16 >( "flags", "PHONETIC-FLAGS" );
219     }
220 
221     return aString;
222 }
223 
dumpColor(const String & rName)224 void RecordObjectBase::dumpColor( const String& rName )
225 {
226     MultiItemsGuard aMultiGuard( mxOut );
227     writeEmptyItem( rName( "color" ) );
228     switch( extractValue< sal_uInt8 >( dumpDec< sal_uInt8 >( "flags", "COLOR-FLAGS" ), 1, 7 ) )
229     {
230         case 0:     dumpUnused( 1 );                                    break;
231         case 1:     dumpDec< sal_uInt8 >( "index", "PALETTE-COLORS" );  break;
232         case 2:     dumpUnused( 1 );                                    break;
233         case 3:     dumpDec< sal_uInt8 >( "theme-id" );                 break;
234         default:    dumpUnknown( 1 );
235     }
236     dumpDec< sal_Int16 >( "tint", "CONV-TINT" );
237     dumpColorABGR();
238 }
239 
dumpPivotDateTime(const String & rName)240 DateTime RecordObjectBase::dumpPivotDateTime( const String& rName )
241 {
242     DateTime aDateTime;
243     aDateTime.Year = mxStrm->readuInt16();
244     aDateTime.Month = mxStrm->readuInt16();
245     aDateTime.Day = mxStrm->readuInt8();
246     aDateTime.Hours = mxStrm->readuInt8();
247     aDateTime.Minutes = mxStrm->readuInt8();
248     aDateTime.Seconds = mxStrm->readuInt8();
249     writeDateTimeItem( rName, aDateTime );
250     return aDateTime;
251 }
252 
dumpColIndex(const String & rName)253 sal_Int32 RecordObjectBase::dumpColIndex( const String& rName )
254 {
255     sal_Int32 nCol;
256     *mxStrm >> nCol;
257     writeColIndexItem( rName( "col-idx" ), nCol );
258     return nCol;
259 }
260 
dumpRowIndex(const String & rName)261 sal_Int32 RecordObjectBase::dumpRowIndex( const String& rName )
262 {
263     sal_Int32 nRow;
264     *mxStrm >> nRow;
265     writeRowIndexItem( rName( "row-idx" ), nRow );
266     return nRow;
267 }
268 
dumpColRange(const String & rName)269 sal_Int32 RecordObjectBase::dumpColRange( const String& rName )
270 {
271     sal_Int32 nCol1, nCol2;
272     *mxStrm >> nCol1 >> nCol2;
273     writeColRangeItem( rName( "col-range" ), nCol1, nCol2 );
274     return nCol2 - nCol1 + 1;
275 }
276 
dumpRowRange(const String & rName)277 sal_Int32 RecordObjectBase::dumpRowRange( const String& rName )
278 {
279     sal_Int32 nRow1, nRow2;
280     *mxStrm >> nRow1 >> nRow2;
281     writeRowRangeItem( rName( "row-range" ), nRow1, nRow2 );
282     return nRow2 - nRow1 + 1;
283 }
284 
dumpAddress(const String & rName)285 Address RecordObjectBase::dumpAddress( const String& rName )
286 {
287     Address aPos;
288     readAddress( aPos );
289     writeAddressItem( rName( "addr" ), aPos );
290     return aPos;
291 }
292 
dumpRange(const String & rName)293 Range RecordObjectBase::dumpRange( const String& rName )
294 {
295     Range aRange;
296     readRange( aRange );
297     writeRangeItem( rName( "range" ), aRange );
298     return aRange;
299 }
300 
dumpRangeList(const String & rName)301 void RecordObjectBase::dumpRangeList( const String& rName )
302 {
303     RangeList aRanges;
304     readRangeList( aRanges );
305     writeRangeListItem( rName( "range-list" ), aRanges );
306 }
307 
308 // private --------------------------------------------------------------------
309 
readCompressedInt(BinaryInputStream & rStrm,sal_Int32 & ornValue)310 bool RecordObjectBase::readCompressedInt( BinaryInputStream& rStrm, sal_Int32& ornValue )
311 {
312     ornValue = 0;
313     sal_uInt8 nByte;
314     rStrm >> nByte;
315     ornValue = nByte & 0x7F;
316     if( (nByte & 0x80) != 0 )
317     {
318         rStrm >> nByte;
319         ornValue |= sal_Int32( nByte & 0x7F ) << 7;
320         if( (nByte & 0x80) != 0 )
321         {
322             rStrm >> nByte;
323             ornValue |= sal_Int32( nByte & 0x7F ) << 14;
324             if( (nByte & 0x80) != 0 )
325             {
326                 rStrm >> nByte;
327                 ornValue |= sal_Int32( nByte & 0x7F ) << 21;
328             }
329         }
330     }
331     return !rStrm.isEof();
332 }
333 
334 // ============================================================================
335 
FormulaObject(const RecordObjectBase & rParent)336 FormulaObject::FormulaObject( const RecordObjectBase& rParent ) :
337     mnSize( 0 )
338 {
339     RecordObjectBase::construct( rParent );
340     constructFmlaObj();
341 }
342 
~FormulaObject()343 FormulaObject::~FormulaObject()
344 {
345 }
346 
dumpCellFormula(const String & rName)347 void FormulaObject::dumpCellFormula( const String& rName )
348 {
349     dumpFormula( rName, false );
350 }
351 
dumpNameFormula(const String & rName)352 void FormulaObject::dumpNameFormula( const String& rName )
353 {
354     dumpFormula( rName, true );
355 }
356 
implDump()357 void FormulaObject::implDump()
358 {
359     {
360         MultiItemsGuard aMultiGuard( mxOut );
361         writeEmptyItem( maName );
362         writeDecItem( "formula-size", mnSize );
363     }
364     if( mnSize < 0 ) return;
365 
366     sal_Int64 nStartPos = mxStrm->tell();
367     sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, mxStrm->size() );
368 
369     bool bValid = mxTokens.get();
370     mxStack.reset( new FormulaStack );
371     maAddData.clear();
372     IndentGuard aIndGuard( mxOut );
373     {
374         TableGuard aTabGuard( mxOut, 8, 18 );
375         while( bValid && (mxStrm->tell() < nEndPos) )
376         {
377             MultiItemsGuard aMultiGuard( mxOut );
378             writeHexItem( EMPTY_STRING, static_cast< sal_uInt16 >( mxStrm->tell() - nStartPos ) );
379             sal_uInt8 nTokenId = dumpHex< sal_uInt8 >( EMPTY_STRING, mxTokens );
380             bValid = mxTokens->hasName( nTokenId );
381             if( bValid )
382             {
383                 sal_uInt8 nTokClass = nTokenId & BIFF_TOKCLASS_MASK;
384                 sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK;
385                 if( nTokClass == BIFF_TOKCLASS_NONE )
386                 {
387                     switch( nBaseId )
388                     {
389                         case BIFF_TOKID_EXP:        dumpExpToken( "EXP" );          break;
390                         case BIFF_TOKID_ADD:        dumpBinaryOpToken( "+" );       break;
391                         case BIFF_TOKID_SUB:        dumpBinaryOpToken( "-" );       break;
392                         case BIFF_TOKID_MUL:        dumpBinaryOpToken( "*" );       break;
393                         case BIFF_TOKID_DIV:        dumpBinaryOpToken( "/" );       break;
394                         case BIFF_TOKID_POWER:      dumpBinaryOpToken( "^" );       break;
395                         case BIFF_TOKID_CONCAT:     dumpBinaryOpToken( "&" );       break;
396                         case BIFF_TOKID_LT:         dumpBinaryOpToken( "<" );       break;
397                         case BIFF_TOKID_LE:         dumpBinaryOpToken( "<=" );      break;
398                         case BIFF_TOKID_EQ:         dumpBinaryOpToken( "=" );       break;
399                         case BIFF_TOKID_GE:         dumpBinaryOpToken( ">=" );      break;
400                         case BIFF_TOKID_GT:         dumpBinaryOpToken( "<" );       break;
401                         case BIFF_TOKID_NE:         dumpBinaryOpToken( "<>" );      break;
402                         case BIFF_TOKID_ISECT:      dumpBinaryOpToken( " " );       break;
403                         case BIFF_TOKID_LIST:       dumpBinaryOpToken( "," );       break;
404                         case BIFF_TOKID_RANGE:      dumpBinaryOpToken( ":" );       break;
405                         case BIFF_TOKID_UPLUS:      dumpUnaryOpToken( "+", "" );    break;
406                         case BIFF_TOKID_UMINUS:     dumpUnaryOpToken( "-", "" );    break;
407                         case BIFF_TOKID_PERCENT:    dumpUnaryOpToken( "", "%" );    break;
408                         case BIFF_TOKID_PAREN:      dumpUnaryOpToken( "(", ")" );   break;
409                         case BIFF_TOKID_MISSARG:    dumpMissArgToken();             break;
410                         case BIFF_TOKID_STR:        dumpStringToken();              break;
411                         case BIFF_TOKID_NLR:        bValid = dumpTableToken();      break;
412                         case BIFF_TOKID_ATTR:       bValid = dumpAttrToken();       break;
413                         case BIFF_TOKID_ERR:        dumpErrorToken();               break;
414                         case BIFF_TOKID_BOOL:       dumpBoolToken();                break;
415                         case BIFF_TOKID_INT:        dumpIntToken();                 break;
416                         case BIFF_TOKID_NUM:        dumpDoubleToken();              break;
417                         default:                    bValid = false;
418                     }
419                 }
420                 else
421                 {
422                     OUString aTokClass = cfg().getName( mxClasses, nTokClass );
423                     switch( nBaseId )
424                     {
425                         case BIFF_TOKID_ARRAY:      dumpArrayToken( aTokClass );                break;
426                         case BIFF_TOKID_FUNC:       dumpFuncToken( aTokClass );                 break;
427                         case BIFF_TOKID_FUNCVAR:    dumpFuncVarToken( aTokClass );              break;
428                         case BIFF_TOKID_NAME:       dumpNameToken( aTokClass );                 break;
429                         case BIFF_TOKID_REF:        dumpRefToken( aTokClass, false );           break;
430                         case BIFF_TOKID_AREA:       dumpAreaToken( aTokClass, false );          break;
431                         case BIFF_TOKID_MEMAREA:    dumpMemAreaToken( aTokClass, true );        break;
432                         case BIFF_TOKID_MEMERR:     dumpMemAreaToken( aTokClass, false );       break;
433                         case BIFF_TOKID_MEMNOMEM:   dumpMemAreaToken( aTokClass, false );       break;
434                         case BIFF_TOKID_MEMFUNC:    dumpMemFuncToken( aTokClass );              break;
435                         case BIFF_TOKID_REFERR:     dumpRefErrToken( aTokClass, false );        break;
436                         case BIFF_TOKID_AREAERR:    dumpRefErrToken( aTokClass, true );         break;
437                         case BIFF_TOKID_REFN:       dumpRefToken( aTokClass, true );            break;
438                         case BIFF_TOKID_AREAN:      dumpAreaToken( aTokClass, true );           break;
439                         case BIFF_TOKID_MEMAREAN:   dumpMemFuncToken( aTokClass );              break;
440                         case BIFF_TOKID_MEMNOMEMN:  dumpMemFuncToken( aTokClass );              break;
441                         case BIFF_TOKID_NAMEX:      dumpNameXToken( aTokClass );                break;
442                         case BIFF_TOKID_REF3D:      dumpRef3dToken( aTokClass, mbNameMode );    break;
443                         case BIFF_TOKID_AREA3D:     dumpArea3dToken( aTokClass, mbNameMode );   break;
444                         case BIFF_TOKID_REFERR3D:   dumpRefErr3dToken( aTokClass, false );      break;
445                         case BIFF_TOKID_AREAERR3D:  dumpRefErr3dToken( aTokClass, true );       break;
446                         default:                    bValid = false;
447                     }
448                 }
449             }
450         }
451     }
452 
453     if( nEndPos == mxStrm->tell() )
454     {
455         dumpAddTokenData();
456         if( mnSize > 0 )
457         {
458             writeInfoItem( "formula", mxStack->getFormulaString() );
459             writeInfoItem( "classes", mxStack->getClassesString() );
460         }
461     }
462     else
463     {
464         dumpBinary( OOX_DUMP_ERRASCII( "formula-error" ), static_cast< sal_Int32 >( nEndPos - mxStrm->tell() ), false );
465         sal_Int32 nAddDataSize = dumpDec< sal_Int32 >( "add-data-size" );
466         dumpBinary( "add-data", nAddDataSize, false );
467     }
468 
469     mnSize = 0;
470 }
471 
dumpFormula(const String & rName,bool bNameMode)472 void FormulaObject::dumpFormula( const String& rName, bool bNameMode )
473 {
474     maName = rName( "formula" );
475     *mxStrm >> mnSize;
476     mbNameMode = bNameMode;
477     dump();
478 }
479 
480 // private --------------------------------------------------------------------
481 
constructFmlaObj()482 void FormulaObject::constructFmlaObj()
483 {
484     if( RecordObjectBase::implIsValid() )
485     {
486         mxFuncProv.reset( new FunctionProvider( FILTER_OOXML, BIFF_UNKNOWN, true ) );
487 
488         Config& rCfg = cfg();
489         mxClasses   = rCfg.getNameList( "TOKENCLASSES" );
490         mxRelFlags  = rCfg.getNameList( "REFRELFLAGS" );
491         mxAttrTypes = rCfg.getNameList( "ATTRTYPES" );
492         mxSpTypes   = rCfg.getNameList( "ATTRSPACETYPES" );
493 
494         // create classified token names
495         mxTokens = rCfg.createNameList< ConstList >( "TOKENS" );
496         mxTokens->includeList( rCfg.getNameList( "BASETOKENS" ) );
497 
498         NameListRef xClassTokens = rCfg.getNameList( "CLASSTOKENS" );
499         if( mxClasses.get() && xClassTokens.get() )
500             for( NameListBase::const_iterator aCIt = mxClasses->begin(), aCEnd = mxClasses->end(); aCIt != aCEnd; ++aCIt )
501                 for( NameListBase::const_iterator aTIt = xClassTokens->begin(), aTEnd = xClassTokens->end(); aTIt != aTEnd; ++aTIt )
502                     mxTokens->setName( aCIt->first | aTIt->first, aTIt->second + aCIt->second );
503 
504         mnColCount = 16384;
505         mnRowCount = 1024 * 1024;
506     }
507 }
508 
509 // ----------------------------------------------------------------------------
510 
511 namespace {
512 
lclCreateName(const OUString & rRef,sal_Int32 nNameId)513 OUString lclCreateName( const OUString& rRef, sal_Int32 nNameId )
514 {
515     OUStringBuffer aName( rRef );
516     StringHelper::appendIndexedText( aName, CREATE_OUSTRING( "NAME" ), nNameId );
517     return aName.makeStringAndClear();
518 }
519 
520 } // namespace
521 
522 // ----------------------------------------------------------------------------
523 
createTokenAddress(sal_Int32 nCol,sal_Int32 nRow,bool bRelC,bool bRelR,bool bNameMode) const524 TokenAddress FormulaObject::createTokenAddress( sal_Int32 nCol, sal_Int32 nRow, bool bRelC, bool bRelR, bool bNameMode ) const
525 {
526     TokenAddress aPos;
527     aPos.mnCol = nCol;
528     if( bRelC && bNameMode && (nCol >= mnColCount / 2) ) aPos.mnCol -= mnColCount;
529     aPos.mbRelCol = bRelC;
530     aPos.mnRow = nRow;
531     if( bRelR && bNameMode && (nRow >= mnRowCount / 2) ) aPos.mnRow -= mnRowCount;
532     aPos.mbRelRow = bRelR;
533     return aPos;
534 }
535 
createRef(const OUString & rData) const536 OUString FormulaObject::createRef( const OUString& rData ) const
537 {
538     return maRefPrefix + rData;
539 }
540 
createName(sal_Int32 nNameId) const541 OUString FormulaObject::createName( sal_Int32 nNameId ) const
542 {
543     return lclCreateName( maRefPrefix, nNameId );
544 }
545 
createPlaceHolder(size_t nIdx) const546 OUString FormulaObject::createPlaceHolder( size_t nIdx ) const
547 {
548     OUStringBuffer aStr;
549     StringHelper::appendDec( aStr, static_cast< sal_uInt32 >( nIdx ) );
550     StringHelper::enclose( aStr, OOX_DUMP_PLACEHOLDER );
551     return aStr.makeStringAndClear();
552 }
553 
createPlaceHolder() const554 OUString FormulaObject::createPlaceHolder() const
555 {
556     return createPlaceHolder( maAddData.size() );
557 }
558 
writeFuncIdItem(sal_uInt16 nFuncId,const FunctionInfo ** oppFuncInfo)559 OUString FormulaObject::writeFuncIdItem( sal_uInt16 nFuncId, const FunctionInfo** oppFuncInfo )
560 {
561     ItemGuard aItem( mxOut, "func-id" );
562     writeHexItem( EMPTY_STRING, nFuncId, "FUNCID" );
563     OUStringBuffer aBuffer;
564     const FunctionInfo* pFuncInfo = mxFuncProv->getFuncInfoFromBiff12FuncId( nFuncId );
565     if( pFuncInfo )
566         aBuffer.append( pFuncInfo->maOoxFuncName );
567     else
568     {
569         bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD );
570         aBuffer.appendAscii( bCmd ? "CMD" : "FUNC" );
571         StringHelper::appendIndex( aBuffer, nFuncId & BIFF_TOK_FUNCVAR_FUNCIDMASK );
572     }
573     OUString aFuncName = aBuffer.makeStringAndClear();
574     aItem.cont();
575     mxOut->writeChar( OOX_DUMP_STRQUOTE );
576     mxOut->writeString( aFuncName );
577     mxOut->writeChar( OOX_DUMP_STRQUOTE );
578     if( oppFuncInfo ) *oppFuncInfo = pFuncInfo;
579     return aFuncName;
580 }
581 
dumpTokenCol(const String & rName,bool & rbRelC,bool & rbRelR)582 sal_Int32 FormulaObject::dumpTokenCol( const String& rName, bool& rbRelC, bool& rbRelR )
583 {
584     sal_uInt16 nCol = dumpHex< sal_uInt16 >( rName, mxRelFlags );
585     rbRelC = getFlag( nCol, BIFF12_TOK_REF_COLREL );
586     rbRelR = getFlag( nCol, BIFF12_TOK_REF_ROWREL );
587     nCol &= BIFF12_TOK_REF_COLMASK;
588     return nCol;
589 }
590 
dumpTokenRow(const String & rName)591 sal_Int32 FormulaObject::dumpTokenRow( const String& rName )
592 {
593     return dumpDec< sal_Int32 >( rName );
594 }
595 
dumpTokenAddress(bool bNameMode)596 TokenAddress FormulaObject::dumpTokenAddress( bool bNameMode )
597 {
598     bool bRelC = false;
599     bool bRelR = false;
600     sal_Int32 nRow = dumpTokenRow( "row" );
601     sal_Int32 nCol = dumpTokenCol( "col", bRelC, bRelR );
602     return createTokenAddress( nCol, nRow, bRelC, bRelR, bNameMode );
603 }
604 
dumpTokenRange(bool bNameMode)605 TokenRange FormulaObject::dumpTokenRange( bool bNameMode )
606 {
607     bool bRelC1 = false;
608     bool bRelR1 = false;
609     bool bRelC2 = false;
610     bool bRelR2 = false;
611     sal_Int32 nRow1 = dumpTokenRow( "row1" );
612     sal_Int32 nRow2 = dumpTokenRow( "row2" );
613     sal_Int32 nCol1 = dumpTokenCol( "col1", bRelC1, bRelR1 );
614     sal_Int32 nCol2 = dumpTokenCol( "col2", bRelC2, bRelR2 );
615     TokenRange aRange;
616     aRange.maFirst = createTokenAddress( nCol1, nRow1, bRelC1, bRelR1, bNameMode );
617     aRange.maLast  = createTokenAddress( nCol2, nRow2, bRelC2, bRelR2, bNameMode );
618     return aRange;
619 }
620 
readTokenRefId()621 sal_Int16 FormulaObject::readTokenRefId()
622 {
623     return dumpDec< sal_Int16 >( "ref-id" );
624 }
625 
dumpTokenRefId()626 OUString FormulaObject::dumpTokenRefId()
627 {
628     OUStringBuffer aRef( CREATE_OUSTRING( "REF" ) );
629     StringHelper::appendIndex( aRef, readTokenRefId() );
630     aRef.append( OOX_DUMP_TABSEP );
631     return aRef.makeStringAndClear();
632 }
633 
dumpIntToken()634 void FormulaObject::dumpIntToken()
635 {
636     dumpDec< sal_uInt16 >( "value" );
637     mxStack->pushOperand( mxOut->getLastItemValue() );
638 }
639 
dumpDoubleToken()640 void FormulaObject::dumpDoubleToken()
641 {
642     dumpDec< double >( "value" );
643     mxStack->pushOperand( mxOut->getLastItemValue() );
644 }
645 
dumpStringToken()646 void FormulaObject::dumpStringToken()
647 {
648     OUStringBuffer aBuffer( dumpString( "value", false, false ) );
649     StringHelper::enclose( aBuffer, OOX_DUMP_FMLASTRQUOTE );
650     mxStack->pushOperand( aBuffer.makeStringAndClear() );
651 }
652 
dumpBoolToken()653 void FormulaObject::dumpBoolToken()
654 {
655     dumpBoolean( "value" );
656     mxStack->pushOperand( mxOut->getLastItemValue() );
657 }
658 
dumpErrorToken()659 void FormulaObject::dumpErrorToken()
660 {
661     dumpErrorCode( "value" );
662     mxStack->pushOperand( mxOut->getLastItemValue() );
663 }
664 
dumpMissArgToken()665 void FormulaObject::dumpMissArgToken()
666 {
667     mxStack->pushOperand( OUString( OOX_DUMP_EMPTYVALUE ) );
668 }
669 
dumpArrayToken(const OUString & rTokClass)670 void FormulaObject::dumpArrayToken( const OUString& rTokClass )
671 {
672     dumpUnused( 14 );
673     mxStack->pushOperand( createPlaceHolder(), rTokClass );
674     maAddData.push_back( ADDDATA_ARRAY );
675 }
676 
dumpNameToken(const OUString & rTokClass)677 void FormulaObject::dumpNameToken( const OUString& rTokClass )
678 {
679     sal_Int32 nNameId = dumpDec< sal_Int32 >( "name-id" );
680     mxStack->pushOperand( createName( nNameId ), rTokClass );
681 }
682 
dumpNameXToken(const OUString & rTokClass)683 void FormulaObject::dumpNameXToken( const OUString& rTokClass )
684 {
685     OUString aRef = dumpTokenRefId();
686     sal_Int32 nNameId = dumpDec< sal_Int32 >( "name-id" );
687     mxStack->pushOperand( lclCreateName( aRef, nNameId ), rTokClass );
688 }
689 
dumpRefToken(const OUString & rTokClass,bool bNameMode)690 void FormulaObject::dumpRefToken( const OUString& rTokClass, bool bNameMode )
691 {
692     TokenAddress aPos = dumpTokenAddress( bNameMode );
693     writeTokenAddressItem( "addr", aPos, bNameMode );
694     mxStack->pushOperand( createRef( mxOut->getLastItemValue() ), rTokClass );
695 }
696 
dumpAreaToken(const OUString & rTokClass,bool bNameMode)697 void FormulaObject::dumpAreaToken( const OUString& rTokClass, bool bNameMode )
698 {
699     TokenRange aRange = dumpTokenRange( bNameMode );
700     writeTokenRangeItem( "range", aRange, bNameMode );
701     mxStack->pushOperand( createRef( mxOut->getLastItemValue() ), rTokClass );
702 }
703 
dumpRefErrToken(const OUString & rTokClass,bool bArea)704 void FormulaObject::dumpRefErrToken( const OUString& rTokClass, bool bArea )
705 {
706     dumpUnused( 4 * (bArea ? 2 : 1) );
707     mxStack->pushOperand( createRef( getErrorName( BIFF_ERR_REF ) ), rTokClass );
708 }
709 
dumpRef3dToken(const OUString & rTokClass,bool bNameMode)710 void FormulaObject::dumpRef3dToken( const OUString& rTokClass, bool bNameMode )
711 {
712     OUString aRef = dumpTokenRefId();
713     TokenAddress aPos = dumpTokenAddress( bNameMode );
714     writeTokenAddress3dItem( "addr", aRef, aPos, bNameMode );
715     mxStack->pushOperand( mxOut->getLastItemValue(), rTokClass );
716 }
717 
dumpArea3dToken(const OUString & rTokClass,bool bNameMode)718 void FormulaObject::dumpArea3dToken( const OUString& rTokClass, bool bNameMode )
719 {
720     OUString aRef = dumpTokenRefId();
721     TokenRange aRange = dumpTokenRange( bNameMode );
722     writeTokenRange3dItem( "range", aRef, aRange, bNameMode );
723     mxStack->pushOperand( mxOut->getLastItemValue(), rTokClass );
724 }
725 
dumpRefErr3dToken(const OUString & rTokClass,bool bArea)726 void FormulaObject::dumpRefErr3dToken( const OUString& rTokClass, bool bArea )
727 {
728     OUString aRef = dumpTokenRefId();
729     dumpUnused( 4 * (bArea ? 2 : 1) );
730     mxStack->pushOperand( aRef + getErrorName( BIFF_ERR_REF ), rTokClass );
731 }
732 
dumpMemFuncToken(const OUString &)733 void FormulaObject::dumpMemFuncToken( const OUString& /*rTokClass*/ )
734 {
735     dumpDec< sal_uInt16 >( "size" );
736 }
737 
dumpMemAreaToken(const OUString & rTokClass,bool bAddData)738 void FormulaObject::dumpMemAreaToken( const OUString& rTokClass, bool bAddData )
739 {
740     dumpUnused( 4 );
741     dumpMemFuncToken( rTokClass );
742     if( bAddData )
743         maAddData.push_back( ADDDATA_MEMAREA );
744 }
745 
dumpExpToken(const String & rName)746 void FormulaObject::dumpExpToken( const String& rName )
747 {
748     Address aPos;
749     dumpRowIndex( "base-row" );
750     OUStringBuffer aOp( rName );
751     StringHelper::appendIndex( aOp, createPlaceHolder() + mxOut->getLastItemValue() );
752     mxStack->pushOperand( aOp.makeStringAndClear() );
753     maAddData.push_back( ADDDATA_EXP );
754 }
755 
dumpUnaryOpToken(const String & rLOp,const String & rROp)756 void FormulaObject::dumpUnaryOpToken( const String& rLOp, const String& rROp )
757 {
758     mxStack->pushUnaryOp( rLOp, rROp );
759 }
760 
dumpBinaryOpToken(const String & rOp)761 void FormulaObject::dumpBinaryOpToken( const String& rOp )
762 {
763     mxStack->pushBinaryOp( rOp );
764 }
765 
dumpFuncToken(const OUString & rTokClass)766 void FormulaObject::dumpFuncToken( const OUString& rTokClass )
767 {
768     sal_uInt16 nFuncId;
769     *mxStrm >> nFuncId;
770     const FunctionInfo* pFuncInfo = 0;
771     OUString aFuncName = writeFuncIdItem( nFuncId, &pFuncInfo );
772     if( pFuncInfo && (pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount) )
773         mxStack->pushFuncOp( aFuncName, rTokClass, pFuncInfo->mnMinParamCount );
774     else
775         mxStack->setError();
776 }
777 
dumpFuncVarToken(const OUString & rTokClass)778 void FormulaObject::dumpFuncVarToken( const OUString& rTokClass )
779 {
780     sal_uInt8 nParamCount;
781     sal_uInt16 nFuncId;
782     *mxStrm >> nParamCount >> nFuncId;
783     bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD );
784     if( bCmd )
785         writeHexItem( "param-count", nParamCount, "PARAMCOUNT-CMD" );
786     else
787         writeDecItem( "param-count", nParamCount );
788     OUString aFuncName = writeFuncIdItem( nFuncId );
789     if( bCmd && getFlag( nParamCount, BIFF_TOK_FUNCVAR_CMDPROMPT ) )
790     {
791         aFuncName += OUString( OOX_DUMP_CMDPROMPT );
792         nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK;
793     }
794     mxStack->pushFuncOp( aFuncName, rTokClass, nParamCount );
795 }
796 
dumpTableToken()797 bool FormulaObject::dumpTableToken()
798 {
799     dumpUnused( 3 );
800     sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "TABLEFLAGS" );
801     sal_uInt16 nTabId = dumpDec< sal_uInt16 >( "table-id" );
802     dumpUnused( 2 );
803     {
804         sal_uInt16 nCol1, nCol2;
805         *mxStrm >> nCol1 >> nCol2;
806         ItemGuard aItem( mxOut, "cols" );
807         mxOut->writeDec( nCol1 );
808         if( nCol1 != nCol2 )
809         {
810             mxOut->writeChar( OOX_DUMP_RANGESEP );
811             mxOut->writeDec( nCol2 );
812         }
813     }
814     OUStringBuffer aColRange;
815     StringHelper::appendIndex( aColRange, mxOut->getLastItemValue() );
816     OUStringBuffer aParams;
817     size_t nParams = 0;
818     if( getFlag( nFlags, BIFF12_TOK_TABLE_ALL ) && ++nParams )
819         StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#All]" ) );
820     if( getFlag( nFlags, BIFF12_TOK_TABLE_HEADERS ) && ++nParams )
821         StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Headers]" ) );
822     if( getFlag( nFlags, BIFF12_TOK_TABLE_DATA ) && ++nParams )
823         StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Data]" ) );
824     if( getFlag( nFlags, BIFF12_TOK_TABLE_TOTALS ) && ++nParams )
825         StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Totals]" ) );
826     if( getFlag( nFlags, BIFF12_TOK_TABLE_THISROW ) && ++nParams )
827         StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#This Row]" ) );
828     if( (getFlag( nFlags, BIFF12_TOK_TABLE_COLUMN ) || getFlag( nFlags, BIFF12_TOK_TABLE_COLRANGE )) && ++nParams )
829         StringHelper::appendToken( aParams, aColRange.makeStringAndClear() );
830     OUStringBuffer aOp;
831     StringHelper::appendIndexedText( aOp, CREATE_OUSTRING( "TABLE" ), nTabId );
832     if( nParams > 1 )
833         StringHelper::appendIndex( aOp, aParams.makeStringAndClear() );
834     else if( nParams == 1 )
835         aOp.append( aParams.makeStringAndClear() );
836     mxStack->pushOperand( aOp.makeStringAndClear() );
837     return true;
838 }
839 
dumpAttrToken()840 bool FormulaObject::dumpAttrToken()
841 {
842     bool bValid = true;
843     sal_uInt8 nType = dumpHex< sal_uInt8 >( "type", mxAttrTypes );
844     switch( nType )
845     {
846         case BIFF_TOK_ATTR_VOLATILE:
847             dumpUnused( 2 );
848         break;
849         case BIFF_TOK_ATTR_IF:
850             dumpDec< sal_uInt16 >( "skip" );
851         break;
852         case BIFF_TOK_ATTR_CHOOSE:
853         {
854             sal_uInt16 nCount = dumpDec< sal_uInt16 >( "choices" );
855             mxOut->resetItemIndex();
856             for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
857                 dumpDec< sal_uInt16 >( "#skip" );
858             dumpDec< sal_uInt16 >( "skip-err" );
859         }
860         break;
861         case BIFF_TOK_ATTR_SKIP:
862             dumpDec< sal_uInt16 >( "skip" );
863         break;
864         case BIFF_TOK_ATTR_SUM:
865             dumpUnused( 2 );
866             mxStack->pushFuncOp( CREATE_OUSTRING( "SUM" ), OUString( OOX_DUMP_BASECLASS ), 1 );
867         break;
868         case BIFF_TOK_ATTR_ASSIGN:
869             dumpUnused( 2 );
870         break;
871         case BIFF_TOK_ATTR_SPACE:
872         case BIFF_TOK_ATTR_SPACE | BIFF_TOK_ATTR_VOLATILE:
873             dumpDec< sal_uInt8 >( "char-type", mxSpTypes );
874             dumpDec< sal_uInt8 >( "char-count" );
875         break;
876         case BIFF_TOK_ATTR_IFERROR:
877             dumpDec< sal_uInt16 >( "skip" );
878         break;
879         default:
880             bValid = false;
881     }
882     return bValid;
883 }
884 
dumpAddTokenData()885 void FormulaObject::dumpAddTokenData()
886 {
887     mxOut->resetItemIndex();
888     sal_Int32 nAddDataSize = (mxStrm->size() - mxStrm->tell() >= 4) ? dumpDec< sal_Int32 >( "add-data-size" ) : 0;
889     sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nAddDataSize, mxStrm->size() );
890     for( AddDataTypeVec::const_iterator aIt = maAddData.begin(), aEnd = maAddData.end(); (aIt != aEnd) && !mxStrm->isEof() && (mxStrm->tell() < nEndPos); ++aIt )
891     {
892         AddDataType eType = *aIt;
893 
894         {
895             ItemGuard aItem( mxOut, "#add-data" );
896             switch( eType )
897             {
898                 case ADDDATA_EXP:       mxOut->writeAscii( "tExp" );      break;
899                 case ADDDATA_ARRAY:     mxOut->writeAscii( "tArray" );    break;
900                 case ADDDATA_MEMAREA:   mxOut->writeAscii( "tMemArea" );  break;
901             }
902         }
903 
904         size_t nIdx = aIt - maAddData.begin();
905         IndentGuard aIndGuard( mxOut );
906         switch( eType )
907         {
908             case ADDDATA_EXP:       dumpAddDataExp( nIdx );     break;
909             case ADDDATA_ARRAY:     dumpAddDataArray( nIdx );   break;
910             case ADDDATA_MEMAREA:   dumpAddDataMemArea( nIdx ); break;
911             default:;
912         }
913     }
914 }
915 
dumpAddDataExp(size_t nIdx)916 void FormulaObject::dumpAddDataExp( size_t nIdx )
917 {
918     dumpColIndex( "base-col" );
919     mxStack->replaceOnTop( createPlaceHolder( nIdx ), mxOut->getLastItemValue() );
920 }
921 
dumpAddDataArray(size_t nIdx)922 void FormulaObject::dumpAddDataArray( size_t nIdx )
923 {
924     sal_Int32 nCols, nRows;
925     dumpaddDataArrayHeader( nCols, nRows );
926 
927     OUStringBuffer aOp;
928     TableGuard aTabGuard( mxOut, 17 );
929     for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
930     {
931         OUStringBuffer aArrayLine;
932         for( sal_Int32 nCol = 0; nCol < nCols; ++nCol )
933             StringHelper::appendToken( aArrayLine, dumpaddDataArrayValue(), OOX_DUMP_LISTSEP );
934         StringHelper::appendToken( aOp, aArrayLine.makeStringAndClear(), OOX_DUMP_ARRAYSEP );
935     }
936     StringHelper::enclose( aOp, '{', '}' );
937     mxStack->replaceOnTop( createPlaceHolder( nIdx ), aOp.makeStringAndClear() );
938 }
939 
dumpAddDataMemArea(size_t)940 void FormulaObject::dumpAddDataMemArea( size_t /*nIdx*/ )
941 {
942     dumpRangeList();
943 }
944 
dumpaddDataArrayHeader(sal_Int32 & rnCols,sal_Int32 & rnRows)945 void FormulaObject::dumpaddDataArrayHeader( sal_Int32& rnCols, sal_Int32& rnRows )
946 {
947     MultiItemsGuard aMultiGuard( mxOut );
948     rnRows = dumpDec< sal_Int32 >( "height" );
949     rnCols = dumpDec< sal_Int32 >( "width" );
950     ItemGuard aItem( mxOut, "size" );
951     mxOut->writeDec( rnCols );
952     mxOut->writeChar( 'x' );
953     mxOut->writeDec( rnRows );
954     aItem.cont();
955     mxOut->writeDec( rnCols * rnRows );
956 }
957 
dumpaddDataArrayValue()958 OUString FormulaObject::dumpaddDataArrayValue()
959 {
960     MultiItemsGuard aMultiGuard( mxOut );
961     OUStringBuffer aValue;
962     switch( dumpDec< sal_uInt8 >( "type", "ARRAYVALUE-TYPE" ) )
963     {
964         case BIFF_TOK_ARRAY_DOUBLE:
965             dumpDec< double >( "value" );
966             aValue.append( mxOut->getLastItemValue() );
967         break;
968         case BIFF_TOK_ARRAY_STRING:
969             aValue.append( dumpString( "value", false, false ) );
970             StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE );
971         break;
972         case BIFF_TOK_ARRAY_BOOL:
973             dumpBoolean( "value" );
974             aValue.append( mxOut->getLastItemValue() );
975         break;
976         case BIFF_TOK_ARRAY_ERROR:
977             dumpErrorCode( "value" );
978             aValue.append( mxOut->getLastItemValue() );
979             dumpUnused( 3 );
980         break;
981     }
982     return aValue.makeStringAndClear();
983 }
984 
985 // ============================================================================
986 
RecordStreamObject(ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,const OUString & rSysFileName)987 RecordStreamObject::RecordStreamObject( ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
988 {
989     RecordObjectBase::construct( rParent, rxStrm, rSysFileName );
990     if( RecordObjectBase::implIsValid() )
991         mxFmlaObj.reset( new FormulaObject( *this ) );
992 }
993 
implIsValid() const994 bool RecordStreamObject::implIsValid() const
995 {
996     return isValid( mxFmlaObj ) && RecordObjectBase::implIsValid();
997 }
998 
implDumpRecordBody()999 void RecordStreamObject::implDumpRecordBody()
1000 {
1001     switch( getRecId() )
1002     {
1003         case BIFF12_ID_ARRAY:
1004             dumpRange( "array-range" );
1005             dumpHex< sal_uInt8 >( "flags", "ARRAY-FLAGS" );
1006             mxFmlaObj->dumpCellFormula();
1007         break;
1008 
1009         case BIFF12_ID_AUTOFILTER:
1010             dumpRange( "filter-range" );
1011         break;
1012 
1013         case BIFF12_ID_BINARYINDEXBLOCK:
1014             dumpRowRange( "row-range" );
1015             dumpUnknown( 12 );
1016         break;
1017 
1018         case BIFF12_ID_BINARYINDEXROWS:
1019         {
1020             sal_uInt32 nUsedRows = dumpBin< sal_uInt32 >( "used-rows" );
1021             dumpDec< sal_Int64 >( "stream-offset" );
1022             for( ; nUsedRows > 0; nUsedRows >>= 1 )
1023                 if( (nUsedRows & 1) != 0 )
1024                     dumpBin< sal_uInt16 >( "used-columns" );
1025         }
1026         break;
1027 
1028         case BIFF12_ID_BORDER:
1029             dumpHex< sal_uInt8 >( "flags", "BORDER-FLAGS" );
1030             dumpDec< sal_uInt16 >( "top-style", "BORDERSTYLES" );
1031             dumpColor( "top-color" );
1032             dumpDec< sal_uInt16 >( "bottom-style", "BORDERSTYLES" );
1033             dumpColor( "bottom-color" );
1034             dumpDec< sal_uInt16 >( "left-style", "BORDERSTYLES" );
1035             dumpColor( "left-color" );
1036             dumpDec< sal_uInt16 >( "right-style", "BORDERSTYLES" );
1037             dumpColor( "right-color" );
1038             dumpDec< sal_uInt16 >( "diag-style", "BORDERSTYLES" );
1039             dumpColor( "diag-color" );
1040         break;
1041 
1042         case BIFF12_ID_BRK:
1043             dumpDec< sal_Int32 >( "id" );
1044             dumpDec< sal_Int32 >( "min" );
1045             dumpDec< sal_Int32 >( "max" );
1046             dumpDec< sal_Int32 >( "manual-break", "BOOLEAN" );
1047             dumpDec< sal_Int32 >( "pivot-break", "BOOLEAN" );
1048         break;
1049 
1050         case BIFF12_ID_CALCPR:
1051             dumpDec< sal_Int32 >( "calc-id" );
1052             dumpDec< sal_Int32 >( "calc-mode", "CALCPR-CALCMODE" );
1053             dumpDec< sal_Int32 >( "iteration-count" );
1054             dumpDec< double >( "iteration-delta" );
1055             dumpDec< sal_Int32 >( "processor-count" );
1056             dumpHex< sal_uInt16 >( "flags", "CALCPR-FLAGS" );
1057         break;
1058 
1059         case BIFF12_ID_CELL_BLANK:
1060             dumpCellHeader( true );
1061         break;
1062 
1063         case BIFF12_ID_CELL_BOOL:
1064             dumpCellHeader( true );
1065             dumpBoolean();
1066         break;
1067 
1068         case BIFF12_ID_CELL_DOUBLE:
1069             dumpCellHeader( true );
1070             dumpDec< double >( "value" );
1071         break;
1072 
1073         case BIFF12_ID_CELL_ERROR:
1074             dumpCellHeader( true );
1075             dumpErrorCode();
1076         break;
1077 
1078         case BIFF12_ID_CELL_RK:
1079             dumpCellHeader( true );
1080             dumpRk( "value" );
1081         break;
1082 
1083         case BIFF12_ID_CELL_RSTRING:
1084             dumpCellHeader( true );
1085             dumpString( "value", true );
1086         break;
1087 
1088         case BIFF12_ID_CELL_SI:
1089             dumpCellHeader( true );
1090             dumpDec< sal_Int32 >( "string-id" );
1091         break;
1092 
1093         case BIFF12_ID_CELL_STRING:
1094             dumpCellHeader( true );
1095             dumpString( "value" );
1096         break;
1097 
1098         case BIFF12_ID_CELLSTYLE:
1099             dumpDec< sal_Int32 >( "xf-id" );
1100             dumpHex< sal_uInt16 >( "flags", "CELLSTYLE-FLAGS" );
1101             dumpDec< sal_uInt8 >( "builtin-id", "CELLSTYLE-BUILTIN" );
1102             dumpDec< sal_uInt8 >( "outline-level" );
1103             dumpString( "name" );
1104         break;
1105 
1106         case BIFF12_ID_CFCOLOR:
1107             dumpColor();
1108         break;
1109 
1110         case BIFF12_ID_CFRULE:
1111         {
1112             // type/subtype/operator is a mess...
1113             dumpDec< sal_Int32 >( "type", "CFRULE-TYPE" );
1114             sal_Int32 nSubType = dumpDec< sal_Int32 >( "sub-type", "CFRULE-SUBTYPE" );
1115             dumpDec< sal_Int32 >( "dxf-id" );
1116             dumpDec< sal_Int32 >( "priority" );
1117             switch( nSubType )
1118             {
1119                 case 0:     dumpDec< sal_Int32 >( "operator", "CFRULE-CELL-OPERATOR" ); break;
1120                 case 5:     dumpDec< sal_Int32 >( "rank" );                             break;
1121                 case 8:     dumpDec< sal_Int32 >( "operator", "CFRULE-TEXT-OPERATOR" ); break;
1122                 case 15:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1123                 case 16:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1124                 case 17:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1125                 case 18:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1126                 case 19:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1127                 case 20:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1128                 case 21:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1129                 case 22:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1130                 case 23:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1131                 case 24:    dumpDec< sal_Int32 >( "operator", "CFRULE-DATE-OPERATOR" ); break;
1132                 case 25:    dumpDec< sal_Int32 >( "std-dev" );                          break;
1133                 case 26:    dumpDec< sal_Int32 >( "std-dev" );                          break;
1134                 case 29:    dumpDec< sal_Int32 >( "std-dev" );                          break;
1135                 case 30:    dumpDec< sal_Int32 >( "std-dev" );                          break;
1136                 default:    dumpDec< sal_Int32 >( "operator", "CFRULE-OTHER-OPERATOR" );
1137             }
1138             dumpUnknown( 8 );
1139             dumpHex< sal_uInt16 >( "flags", "CFRULE-FLAGS" );
1140             // for no obvious reason the formula sizes occur twice
1141             dumpDec< sal_Int32 >( "formula1-size" );
1142             dumpDec< sal_Int32 >( "formula2-size" );
1143             dumpDec< sal_Int32 >( "formula3-size" );
1144             dumpString( "text" );
1145             if( mxStrm->getRemaining() >= 8 )
1146                 mxFmlaObj->dumpNameFormula( "formula1" );
1147             if( mxStrm->getRemaining() >= 8 )
1148                 mxFmlaObj->dumpNameFormula( "formula2" );
1149             if( mxStrm->getRemaining() >= 8 )
1150                 mxFmlaObj->dumpNameFormula( "formula3" );
1151         }
1152         break;
1153 
1154         case BIFF12_ID_CHARTPAGESETUP:
1155             dumpDec< sal_Int32 >( "paper-size", "PAGESETUP-PAPERSIZE" );
1156             dumpDec< sal_Int32 >( "horizontal-res", "PAGESETUP-DPI" );
1157             dumpDec< sal_Int32 >( "vertical-res", "PAGESETUP-DPI" );
1158             dumpDec< sal_Int32 >( "copies" );
1159             dumpDec< sal_uInt16 >( "first-page" );
1160             dumpHex< sal_uInt16 >( "flags", "CHARTPAGESETUP-FLAGS" );
1161             dumpString( "printer-settings-rel-id" );
1162         break;
1163 
1164         case BIFF12_ID_CHARTPROTECTION:
1165             dumpHex< sal_uInt16 >( "password-hash" );
1166             // no flags field for the boolean flags?!?
1167             dumpDec< sal_Int32 >( "content-locked", "BOOLEAN" );
1168             dumpDec< sal_Int32 >( "objects-locked", "BOOLEAN" );
1169         break;
1170 
1171         case BIFF12_ID_CHARTSHEETPR:
1172             dumpHex< sal_uInt16 >( "flags", "CHARTSHEETPR-FLAGS" );
1173             dumpColor( "tab-color" );
1174             dumpString( "codename" );
1175         break;
1176 
1177         case BIFF12_ID_CHARTSHEETVIEW:
1178             dumpHex< sal_uInt16 >( "flags", "CHARTSHEETVIEW-FLAGS" );
1179             dumpDec< sal_Int32 >( "zoom-scale", "CONV-PERCENT" );
1180             dumpDec< sal_Int32 >( "workbookview-id" );
1181         break;
1182 
1183         case BIFF12_ID_COL:
1184             dumpColRange();
1185             dumpDec< sal_Int32 >( "col-width", "CONV-COLWIDTH" );
1186             dumpDec< sal_Int32 >( "custom-xf-id" );
1187             dumpHex< sal_uInt16 >( "flags", "COL-FLAGS" );
1188         break;
1189 
1190         case BIFF12_ID_COLBREAKS:
1191             dumpDec< sal_Int32 >( "count" );
1192             dumpDec< sal_Int32 >( "manual-count" );
1193         break;
1194 
1195         case BIFF12_ID_COLOR:
1196             dumpColor();
1197         break;
1198 
1199         case BIFF12_ID_COMMENT:
1200             dumpDec< sal_Int32 >( "author-id" );
1201             dumpRange( "ref" );
1202             dumpGuid();
1203         break;
1204 
1205         case BIFF12_ID_COMMENTAUTHOR:
1206             dumpString( "author" );
1207         break;
1208 
1209         case BIFF12_ID_COMMENTTEXT:
1210             dumpString( "text", true );
1211         break;
1212 
1213         case BIFF12_ID_CONDFORMATTING:
1214             dumpDec< sal_Int32 >( "cfrule-count" );
1215             dumpDec< sal_Int32 >( "pivot-table", "BOOLEAN" );
1216             dumpRangeList();
1217         break;
1218 
1219         case BIFF12_ID_CONNECTION:
1220         {
1221             dumpDec< sal_uInt8 >( "refreshed-version" );
1222             dumpDec< sal_uInt8 >( "min-refresh-version" );
1223             dumpDec< sal_uInt8 >( "save-password", "CONNECTION-SAVEPASSWORD" );
1224             dumpUnused( 1 );
1225             dumpDec< sal_uInt16 >( "refresh-interval", "CONNECTION-INTERVAL" );
1226             dumpHex< sal_uInt16 >( "flags", "CONNECTION-FLAGS" );
1227             sal_uInt16 nStrFlags = dumpHex< sal_uInt16 >( "string-flags", "CONNECTION-STRINGFLAGS" );
1228             dumpDec< sal_Int32 >( "data-source-type", "CONNECTION-SOURCETYPE" );
1229             dumpDec< sal_Int32 >( "reconnect-type", "CONNECTION-RECONNECTTYPE" );
1230             dumpDec< sal_Int32 >( "id" );
1231             dumpDec< sal_uInt8 >( "credentials", "CONNECTION-CREDENTIALS" );
1232             if( nStrFlags & 0x0001 ) dumpString( "source-file" );
1233             if( nStrFlags & 0x0002 ) dumpString( "source-conn-file" );
1234             if( nStrFlags & 0x0004 ) dumpString( "description" );
1235             if( nStrFlags & 0x0008 ) dumpString( "name" );
1236             if( nStrFlags & 0x0010 ) dumpString( "sso-id" );
1237         }
1238         break;
1239 
1240         case BIFF12_ID_CONTROL:
1241             dumpDec< sal_Int32 >( "shape-id" );
1242             dumpString( "rel-id" );
1243             dumpString( "name" );
1244         break;
1245 
1246         case BIFF12_ID_CUSTOMFILTER:
1247         {
1248             sal_uInt8 nType = dumpDec< sal_uInt8 >( "data-type", "CUSTOMFILTER-DATATYPE" );
1249             dumpDec< sal_uInt8 >( "operator", "CUSTOMFILTER-OPERATOR" );
1250             switch( nType )
1251             {
1252                 case 4:     dumpDec< double >( "value" );               break;
1253                 case 6:     dumpUnused( 8 ); dumpString( "value" );     break;
1254                 case 8:     dumpBoolean( "value" ); dumpUnused( 7 );    break;
1255                 default:    dumpUnused( 8 );
1256             }
1257         }
1258         break;
1259 
1260         case BIFF12_ID_DATATABLE:
1261             dumpRange( "table-range" );
1262             dumpAddress( "ref1" );
1263             dumpAddress( "ref2" );
1264             dumpHex< sal_uInt8 >( "flags", "DATATABLE-FLAGS" );
1265         break;
1266 
1267         case BIFF12_ID_DATAVALIDATION:
1268             dumpHex< sal_uInt32 >( "flags", "DATAVALIDATION-FLAGS" );
1269             dumpRangeList();
1270             dumpString( "error-title" );
1271             dumpString( "error-message" );
1272             dumpString( "input-title" );
1273             dumpString( "input-message" );
1274             mxFmlaObj->dumpNameFormula( "formula1" );
1275             mxFmlaObj->dumpNameFormula( "formula2" );
1276         break;
1277 
1278         case BIFF12_ID_DATAVALIDATIONS:
1279             dumpHex< sal_uInt16 >( "flags", "DATAVALIDATIONS-FLAGS" );
1280             dumpDec< sal_Int32 >( "input-x" );
1281             dumpDec< sal_Int32 >( "input-y" );
1282             dumpUnused( 4 );
1283             dumpDec< sal_Int32 >( "count" );
1284         break;
1285 
1286         case BIFF12_ID_DDEITEMVALUES:
1287             dumpDec< sal_Int32 >( "rows" );
1288             dumpDec< sal_Int32 >( "columns" );
1289         break;
1290 
1291         case BIFF12_ID_DDEITEM_STRING:
1292             dumpString( "value" );
1293         break;
1294 
1295         case BIFF12_ID_DEFINEDNAME:
1296             dumpHex< sal_uInt32 >( "flags", "DEFINEDNAME-FLAGS" );
1297             dumpChar( "accelerator", RTL_TEXTENCODING_ISO_8859_1 );
1298             dumpDec< sal_Int32 >( "sheet-id", "DEFINEDNAME-SHEETID" );
1299             dumpString( "name" );
1300             mxFmlaObj->dumpNameFormula();
1301             dumpString( "comment" );
1302             if( mxStrm->getRemaining() >= 4 ) dumpString( "menu-text" );
1303             if( mxStrm->getRemaining() >= 4 ) dumpString( "description-text" );
1304             if( mxStrm->getRemaining() >= 4 ) dumpString( "help-text" );
1305             if( mxStrm->getRemaining() >= 4 ) dumpString( "statusbar-text" );
1306         break;
1307 
1308         case BIFF12_ID_DIMENSION:
1309             dumpRange( "used-range" );
1310         break;
1311 
1312         case BIFF12_ID_DISCRETEFILTER:
1313             dumpString( "value" );
1314         break;
1315 
1316         case BIFF12_ID_DISCRETEFILTERS:
1317             dumpBool< sal_Int32 >( "show-blank" );
1318             dumpDec< sal_Int32 >( "calendar-type", "DISCRETEFILTERS-CALTYPE" );
1319         break;
1320 
1321         case BIFF12_ID_DRAWING:
1322             dumpString( "rel-id" );
1323         break;
1324 
1325         case BIFF12_ID_DXF:
1326             dumpHex< sal_uInt32 >( "flags", "DXF-FLAGS" );
1327             for( sal_uInt16 nIndex = 0, nCount = dumpDec< sal_uInt16 >( "subrec-count" ); !mxStrm->isEof() && (nIndex < nCount); ++nIndex )
1328             {
1329                 mxOut->startMultiItems();
1330                 sal_Int64 nStartPos = mxStrm->tell();
1331                 writeEmptyItem( "SUBREC" );
1332                 sal_uInt16 nSubRecId = dumpDec< sal_uInt16 >( "id", "DXF-SUBREC" );
1333                 sal_uInt16 nSubRecSize = dumpDec< sal_uInt16 >( "size" );
1334                 sal_Int64 nEndPos = nStartPos + nSubRecSize;
1335                 mxOut->endMultiItems();
1336                 IndentGuard aIndGuard( mxOut );
1337                 switch( nSubRecId )
1338                 {
1339                     case 0:
1340                         dumpDec< sal_uInt8 >( "pattern", "FILLPATTERNS" );
1341                     break;
1342                     case 1: case 2: case 5:
1343                         dumpColor();
1344                     break;
1345                     case 3:
1346                         dumpGradientHead();
1347                     break;
1348                     case 4:
1349                         dumpDec< sal_uInt16 >( "index" );
1350                         dumpDec< double >( "stop-position" );
1351                         dumpColor( "stop-color" );
1352                     break;
1353                     case 6: case 7: case 8: case 9: case 10: case 11: case 12:
1354                         dumpColor( "color" );
1355                         dumpDec< sal_uInt16 >( "style", "BORDERSTYLES" );
1356                     break;
1357                     case 13: case 14:
1358                         dumpBoolean( "value" );
1359                     break;
1360                     case 15:
1361                         dumpDec< sal_uInt8 >( "alignment", "XF-HORALIGN" );
1362                     break;
1363                     case 16:
1364                         dumpDec< sal_uInt8 >( "alignment", "XF-VERALIGN" );
1365                     break;
1366                     case 17:
1367                         dumpDec< sal_uInt8 >( "rotation", "TEXTROTATION" );
1368                     break;
1369                     case 18:
1370                         dumpDec< sal_uInt16 >( "indent" );
1371                     break;
1372                     case 19:
1373                         dumpDec< sal_uInt8 >( "text-dir", "XF-TEXTDIRECTION" );
1374                     break;
1375                     case 20: case 21: case 22:
1376                         dumpBoolean( "value" );
1377                     break;
1378                     case 24:
1379                         dumpString( "name", false, false );
1380                     break;
1381                     case 25:
1382                         dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" );
1383                     break;
1384                     case 26:
1385                         dumpDec< sal_uInt16 >( "underline", "FONT-UNDERLINE" );
1386                     break;
1387                     case 27:
1388                         dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" );
1389                     break;
1390                     case 28: case 29: case 30: case 31: case 32: case 33:
1391                         dumpBoolean( "value" );
1392                     break;
1393                     case 34:
1394                         dumpDec< sal_uInt8 >( "charset", "CHARSET" );
1395                     break;
1396                     case 35:
1397                         dumpDec< sal_uInt8 >( "family", "FONT-FAMILY" );
1398                     break;
1399                     case 36:
1400                         dumpDec< sal_Int32 >( "height", "CONV-TWIP-TO-PT" );
1401                     break;
1402                     case 37:
1403                         dumpDec< sal_uInt8 >( "scheme", "FONT-SCHEME" );
1404                     break;
1405                     case 38:
1406                         dumpString( "numfmt", false, false );
1407                     break;
1408                     case 41:
1409                         dumpDec< sal_uInt16 >( "numfmt-id" );
1410                     break;
1411                     case 42:
1412                         dumpDec< sal_Int16 >( "relative-indent" );
1413                     break;
1414                     case 43: case 44:
1415                         dumpBoolean( "value" );
1416                     break;
1417                 }
1418                 dumpRemainingTo( nEndPos );
1419             }
1420         break;
1421 
1422         case BIFF12_ID_EXTCELL_BOOL:
1423             dumpColIndex();
1424             dumpBoolean();
1425         break;
1426 
1427         case BIFF12_ID_EXTCELL_DOUBLE:
1428             dumpColIndex();
1429             dumpDec< double >( "value" );
1430         break;
1431 
1432         case BIFF12_ID_EXTCELL_ERROR:
1433             dumpColIndex();
1434             dumpErrorCode();
1435         break;
1436 
1437         case BIFF12_ID_EXTCELL_STRING:
1438             dumpColIndex();
1439             dumpString( "value" );
1440         break;
1441 
1442         case BIFF12_ID_EXTERNALBOOK:
1443             switch( dumpDec< sal_uInt16 >( "type", "EXTERNALBOOK-TYPE" ) )
1444             {
1445                 case 0:
1446                     dumpString( "rel-id" );
1447                     dumpDec< sal_Int32 >( "unused" );
1448                 break;
1449                 case 1:
1450                     dumpString( "dde-service" );
1451                     dumpString( "dde-topic" );
1452                 break;
1453                 case 2:
1454                     dumpString( "rel-id" );
1455                     dumpString( "prog-id" );
1456                 break;
1457             }
1458         break;
1459 
1460         case BIFF12_ID_EXTERNALNAME:
1461             dumpString( "name" );
1462         break;
1463 
1464         case BIFF12_ID_EXTERNALNAMEFLAGS:
1465             dumpHex< sal_uInt16 >( "flags", "EXTERNALNAMEFLAGS-FLAGS" );
1466             dumpDec< sal_Int32 >( "sheet-id" );
1467             dumpBoolean( "is-dde-ole" );
1468         break;
1469 
1470         case BIFF12_ID_EXTERNALREF:
1471             dumpString( "rel-id" );
1472         break;
1473 
1474         case BIFF12_ID_EXTERNALSHEETS:
1475         {
1476             sal_Int32 nCount = dumpDec< sal_Int32 >( "ref-count" );
1477             TableGuard aTabGuard( mxOut, 13, 17, 24 );
1478             mxOut->resetItemIndex();
1479             for( sal_Int32 nRefId = 0; !mxStrm->isEof() && (nRefId < nCount); ++nRefId )
1480             {
1481                 MultiItemsGuard aMultiGuard( mxOut );
1482                 writeEmptyItem( "#ref" );
1483                 dumpDec< sal_Int32 >( "extref-id" );
1484                 dumpDec< sal_Int32 >( "first-sheet", "EXTERNALSHEETS-ID" );
1485                 dumpDec< sal_Int32 >( "last-sheet", "EXTERNALSHEETS-ID" );
1486             }
1487         }
1488         break;
1489 
1490         case BIFF12_ID_EXTROW:
1491             dumpRowIndex();
1492         break;
1493 
1494         case BIFF12_ID_EXTSHEETDATA:
1495             dumpDec< sal_Int32 >( "sheet-id" );
1496             dumpHex< sal_uInt8 >( "flags", "EXTSHEETDATA-FLAGS" );
1497         break;
1498 
1499         case BIFF12_ID_EXTSHEETNAMES:
1500             mxOut->resetItemIndex();
1501             for( sal_Int32 nSheet = 0, nCount = dumpDec< sal_Int32 >( "sheet-count" ); !mxStrm->isEof() && (nSheet < nCount); ++nSheet )
1502                 dumpString( "#sheet-name" );
1503         break;
1504 
1505         case BIFF12_ID_FILESHARING:
1506             dumpBool< sal_uInt16 >( "recommend-read-only" );
1507             dumpHex< sal_uInt16 >( "password-hash" );
1508             dumpString( "password-creator" );
1509         break;
1510 
1511         case BIFF12_ID_FILL:
1512             dumpDec< sal_Int32 >( "fill-pattern", "FILLPATTERNS" );
1513             dumpColor( "fg-color" );
1514             dumpColor( "bg-color" );
1515             dumpGradientHead();
1516             mxOut->resetItemIndex();
1517             for( sal_Int32 nStop = 0, nStopCount = dumpDec< sal_Int32 >( "stop-count" ); (nStop < nStopCount) && !mxStrm->isEof(); ++nStop )
1518             {
1519                 writeEmptyItem( "#stop" );
1520                 IndentGuard aIndGuard( mxOut );
1521                 dumpColor( "stop-color" );
1522                 dumpDec< double >( "stop-position" );
1523             }
1524         break;
1525 
1526         case BIFF12_ID_FILEVERSION:
1527             dumpGuid( "codename" );
1528             dumpString( "app-name" );
1529             dumpString( "last-edited" );
1530             dumpString( "lowest-edited" );
1531             dumpString( "build-version" );
1532         break;
1533 
1534         case BIFF12_ID_FILTERCOLUMN:
1535             dumpDec< sal_Int32 >( "column-index" );
1536             dumpHex< sal_uInt16 >( "flags", "FILTERCOLUMN-FLAGS" );
1537         break;
1538 
1539         case BIFF12_ID_FONT:
1540             dumpDec< sal_uInt16 >( "height", "CONV-TWIP-TO-PT" );
1541             dumpHex< sal_uInt16 >( "flags", "FONT-FLAGS" );
1542             dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" );
1543             dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" );
1544             dumpDec< sal_uInt8 >( "underline", "FONT-UNDERLINE" );
1545             dumpDec< sal_uInt8 >( "family", "FONT-FAMILY" );
1546             dumpDec< sal_uInt8 >( "charset", "CHARSET" );
1547             dumpUnused( 1 );
1548             dumpColor();
1549             dumpDec< sal_uInt8 >( "scheme", "FONT-SCHEME" );
1550             dumpString( "name" );
1551         break;
1552 
1553         case BIFF12_ID_FORMULA_BOOL:
1554             dumpCellHeader( true );
1555             dumpBoolean();
1556             dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" );
1557             mxFmlaObj->dumpCellFormula();
1558         break;
1559 
1560         case BIFF12_ID_FORMULA_DOUBLE:
1561             dumpCellHeader( true );
1562             dumpDec< double >( "value" );
1563             dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" );
1564             mxFmlaObj->dumpCellFormula();
1565         break;
1566 
1567         case BIFF12_ID_FORMULA_ERROR:
1568             dumpCellHeader( true );
1569             dumpErrorCode();
1570             dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" );
1571             mxFmlaObj->dumpCellFormula();
1572         break;
1573 
1574         case BIFF12_ID_FORMULA_STRING:
1575             dumpCellHeader( true );
1576             dumpString( "value" );
1577             dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" );
1578             mxFmlaObj->dumpCellFormula();
1579         break;
1580 
1581         case BIFF12_ID_FUNCTIONGROUP:
1582             dumpString( "name" );
1583         break;
1584 
1585         case BIFF12_ID_HEADERFOOTER:
1586             dumpHex< sal_uInt16 >( "flags", "HEADERFOOTER-FLAGS" );
1587             dumpString( "odd-header" );
1588             dumpString( "odd-footer" );
1589             dumpString( "even-header" );
1590             dumpString( "even-footer" );
1591             dumpString( "first-header" );
1592             dumpString( "first-footer" );
1593         break;
1594 
1595         case BIFF12_ID_HYPERLINK:
1596             dumpRange();
1597             dumpString( "rel-id" );
1598             dumpString( "location" );
1599             dumpString( "tooltip" );
1600             dumpString( "display" );
1601         break;
1602 
1603         case BIFF12_ID_INPUTCELLS:
1604             dumpAddress( "pos" );
1605             dumpUnused( 8 );
1606             dumpDec< sal_uInt16 >( "numfmt-id" );
1607             dumpString( "value" );
1608         break;
1609 
1610         case BIFF12_ID_LEGACYDRAWING:
1611             dumpString( "rel-id" );
1612         break;
1613 
1614         case BIFF12_ID_MERGECELL:
1615             dumpRange();
1616         break;
1617 
1618         case BIFF12_ID_MULTCELL_BLANK:
1619             dumpCellHeader( false );
1620         break;
1621 
1622         case BIFF12_ID_MULTCELL_BOOL:
1623             dumpCellHeader( false );
1624             dumpBoolean();
1625         break;
1626 
1627         case BIFF12_ID_MULTCELL_DOUBLE:
1628             dumpCellHeader( false );
1629             dumpDec< double >( "value" );
1630         break;
1631 
1632         case BIFF12_ID_MULTCELL_ERROR:
1633             dumpCellHeader( false );
1634             dumpErrorCode();
1635         break;
1636 
1637         case BIFF12_ID_MULTCELL_RK:
1638             dumpCellHeader( false );
1639             dumpRk( "value" );
1640         break;
1641 
1642         case BIFF12_ID_MULTCELL_RSTRING:
1643             dumpCellHeader( false );
1644             dumpString( "value", true );
1645         break;
1646 
1647         case BIFF12_ID_MULTCELL_SI:
1648             dumpCellHeader( false );
1649             dumpDec< sal_Int32 >( "string-id" );
1650         break;
1651 
1652         case BIFF12_ID_MULTCELL_STRING:
1653             dumpCellHeader( false );
1654             dumpString( "value" );
1655         break;
1656 
1657         case BIFF12_ID_NUMFMT:
1658             dumpDec< sal_uInt16 >( "numfmt-id" );
1659             dumpString( "format" );
1660         break;
1661 
1662         case BIFF12_ID_OLEOBJECT:
1663         {
1664             dumpDec< sal_Int32 >( "aspect", "OLEOBJECT-ASPECT" );
1665             dumpDec< sal_Int32 >( "update", "OLEOBJECT-UPDATE" );
1666             dumpDec< sal_Int32 >( "shape-id" );
1667             sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "OLEOBJECT-FLAGS" );
1668             dumpString( "prog-id" );
1669             if( getFlag( nFlags, BIFF12_OLEOBJECT_LINKED ) )
1670                 mxFmlaObj->dumpNameFormula( "link" );
1671             else
1672                 dumpString( "rel-id" );
1673         }
1674         break;
1675 
1676         case BIFF12_ID_OLESIZE:
1677             dumpRange( "visible-range" );
1678         break;
1679 
1680         case BIFF12_ID_PAGEMARGINS:
1681             dumpDec< double >( "left-margin" );
1682             dumpDec< double >( "right-margin" );
1683             dumpDec< double >( "top-margin" );
1684             dumpDec< double >( "bottom-margin" );
1685             dumpDec< double >( "header-margin" );
1686             dumpDec< double >( "footer-margin" );
1687         break;
1688 
1689         case BIFF12_ID_PAGESETUP:
1690             dumpDec< sal_Int32 >( "paper-size", "PAGESETUP-PAPERSIZE" );
1691             dumpDec< sal_Int32 >( "scaling", "CONV-PERCENT" );
1692             dumpDec< sal_Int32 >( "horizontal-res", "PAGESETUP-DPI" );
1693             dumpDec< sal_Int32 >( "vertical-res", "PAGESETUP-DPI" );
1694             dumpDec< sal_Int32 >( "copies" );
1695             dumpDec< sal_Int32 >( "first-page" );
1696             dumpDec< sal_Int32 >( "scale-to-width", "PAGESETUP-SCALETOPAGES" );
1697             dumpDec< sal_Int32 >( "scale-to-height", "PAGESETUP-SCALETOPAGES" );
1698             dumpHex< sal_uInt16 >( "flags", "PAGESETUP-FLAGS" );
1699             dumpString( "printer-settings-rel-id" );
1700         break;
1701 
1702         case BIFF12_ID_PANE:
1703             dumpDec< double >( "x-split-pos" );
1704             dumpDec< double >( "y-split-pos" );
1705             dumpAddress( "second-top-left" );
1706             dumpDec< sal_Int32 >( "active-pane", "PANE-ID" );
1707             dumpHex< sal_uInt8 >( "flags", "PANE-FLAGS" );
1708         break;
1709 
1710         case BIFF12_ID_PCDEFINITION:
1711         {
1712             dumpDec< sal_uInt8 >( "refreshed-version" );
1713             dumpDec< sal_uInt8 >( "min-refresh-version" );
1714             dumpDec< sal_uInt8 >( "created-version" );
1715             dumpHex< sal_uInt8 >( "flags-1", "PCDEFINITION-FLAGS1" );
1716             dumpDec< sal_Int32 >( "missing-items-limit", "PCDEFINITION-MISSINGITEMS" );
1717             dumpDec< double >( "refreshed-date" );
1718             sal_uInt8 nFlags2 = dumpHex< sal_uInt8 >( "flags-2", "PCDEFINITION-FLAGS2" );
1719             dumpDec< sal_Int32 >( "record-count" );
1720             if( nFlags2 & 0x01 ) dumpString( "refreshed-by" );
1721             if( nFlags2 & 0x02 ) dumpString( "rel-id" );
1722         }
1723         break;
1724 
1725         case BIFF12_ID_PCDFIELD:
1726         {
1727             sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "PCDFIELD-FLAGS" );
1728             dumpDec< sal_Int32 >( "numfmt-id" );
1729             dumpDec< sal_Int16 >( "sql-datatype" );
1730             dumpDec< sal_Int32 >( "hierarchy" );
1731             dumpDec< sal_Int32 >( "hierarchy-level" );
1732             sal_Int32 nMappingCount = dumpDec< sal_Int32 >( "property-mapping-count" );
1733             dumpString( "name" );
1734             if( nFlags & 0x0008 ) dumpString( "caption" );
1735             if( nFlags & 0x0100 ) mxFmlaObj->dumpNameFormula( "formula" );
1736             if( nMappingCount > 0 )
1737             {
1738                 sal_Int32 nBytes = dumpDec< sal_Int32 >( "property-mapping-size" );
1739                 dumpArray( "property-mapping-indexes", nBytes );
1740             }
1741             if( nFlags & 0x0200 ) dumpString( "property-name" );
1742         }
1743         break;
1744 
1745         case BIFF12_ID_PCDFIELDGROUP:
1746             dumpDec< sal_Int32 >( "parent-field" );
1747             dumpDec< sal_Int32 >( "base-field" );
1748         break;
1749 
1750         case BIFF12_ID_PCDFRANGEPR:
1751             dumpDec< sal_uInt8 >( "group-by", "PCDFRANGEPR-GROUPBY" );
1752             dumpHex< sal_uInt8 >( "flags", "PCDFRANGEPR-FLAGS" );
1753             dumpDec< double >( "start-value" );
1754             dumpDec< double >( "end-value" );
1755             dumpDec< double >( "interval" );
1756         break;
1757 
1758         case BIFF12_ID_PCDFSHAREDITEMS:
1759         {
1760             sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "PCDFSHAREDITEMS-FLAGS" );
1761             dumpDec< sal_Int32 >( "count" );
1762             if( nFlags & 0x0100 ) dumpDec< double >( "min-value" );
1763             if( nFlags & 0x0100 ) dumpDec< double >( "max-value" );
1764         }
1765         break;
1766 
1767         case BIFF12_ID_PCDSHEETSOURCE:
1768         {
1769             sal_uInt8 nIsDefName = dumpBoolean( "is-def-name" );
1770             dumpBoolean( "is-builtin-def-name" );
1771             sal_uInt8 nFlags = dumpHex< sal_uInt8 >( "flags", "PCDWORKSHEETSOURCE-FLAGS" );
1772             if( nFlags & 0x02 ) dumpString( "sheet-name" );
1773             if( nFlags & 0x01 ) dumpString( "rel-id" );
1774             if( nIsDefName == 0 ) dumpRange(); else dumpString( "def-name" );
1775         }
1776         break;
1777 
1778         case BIFF12_ID_PCDSOURCE:
1779             dumpDec< sal_Int32 >( "source-type", "PCDSOURCE-TYPE" );
1780             dumpDec< sal_Int32 >( "connection-id" );
1781         break;
1782 
1783         case BIFF12_ID_PCITEM_ARRAY:
1784         {
1785             sal_uInt16 nType = dumpDec< sal_uInt16 >( "type", "PCITEM_ARRAY-TYPE" );
1786             sal_Int32 nCount = dumpDec< sal_Int32 >( "count" );
1787             mxOut->resetItemIndex();
1788             for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1789             {
1790                 switch( nType )
1791                 {
1792                     case 1:     dumpDec< double >( "#value" );  break;
1793                     case 2:     dumpString( "#value" );         break;
1794                     case 16:    dumpErrorCode( "#value" );      break;
1795                     case 32:    dumpPivotDateTime( "#value" );  break;
1796                     default:    nIdx = nCount;
1797                 }
1798             }
1799         }
1800         break;
1801 
1802         case BIFF12_ID_PCITEM_BOOL:
1803             dumpBoolean( "value" );
1804         break;
1805 
1806         case BIFF12_ID_PCITEM_DATE:
1807             dumpPivotDateTime( "value" );
1808         break;
1809 
1810         case BIFF12_ID_PCITEM_DOUBLE:
1811             dumpDec< double >( "value" );
1812             // TODO: server formatting
1813         break;
1814 
1815         case BIFF12_ID_PCITEM_ERROR:
1816             dumpErrorCode( "value" );
1817             // TODO: server formatting
1818         break;
1819 
1820         case BIFF12_ID_PCITEM_INDEX:
1821             dumpDec< sal_Int32 >( "index" );
1822         break;
1823 
1824         case BIFF12_ID_PCITEM_MISSING:
1825             // TODO: server formatting
1826         break;
1827 
1828 
1829         case BIFF12_ID_PCITEM_STRING:
1830             dumpString( "value" );
1831             // TODO: server formatting
1832         break;
1833 
1834         case BIFF12_ID_PCITEMA_BOOL:
1835             dumpBoolean( "value" );
1836             // TODO: additional info
1837         break;
1838 
1839         case BIFF12_ID_PCITEMA_DATE:
1840             dumpPivotDateTime( "value" );
1841             // TODO: additional info
1842         break;
1843 
1844         case BIFF12_ID_PCITEMA_DOUBLE:
1845             dumpDec< double >( "value" );
1846             // TODO: additional info
1847         break;
1848 
1849         case BIFF12_ID_PCITEMA_ERROR:
1850             dumpErrorCode( "value" );
1851             // TODO: additional info
1852         break;
1853 
1854         case BIFF12_ID_PCITEMA_MISSING:
1855             // TODO: additional info
1856         break;
1857 
1858         case BIFF12_ID_PCITEMA_STRING:
1859             dumpString( "value" );
1860             // TODO: additional info
1861         break;
1862 
1863         case BIFF12_ID_PHONETICPR:
1864             dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" );
1865             dumpDec< sal_Int32 >( "type", "PHONETICPR-TYPE" );
1866             dumpDec< sal_Int32 >( "alignment", "PHONETICPR-ALIGNMENT" );
1867         break;
1868 
1869         case BIFF12_ID_PICTURE:
1870             dumpString( "rel-id" );
1871         break;
1872 
1873         case BIFF12_ID_PIVOTAREA:
1874             dumpDec< sal_Int32 >( "field" );
1875             dumpDec< sal_uInt8 >( "type", "PIVOTAREA-TYPE" );
1876             dumpHex< sal_uInt8 >( "flags-1", "PIVOTAREA-FLAGS1" );
1877             dumpHex< sal_uInt16 >( "flags-2", "PIVOTAREA-FLAGS2" );
1878         break;
1879 
1880         case BIFF12_ID_PIVOTCACHE:
1881             dumpDec< sal_Int32 >( "cache-id" );
1882             dumpString( "rel-id" );
1883         break;
1884 
1885         case BIFF12_ID_PTCOLFIELDS:
1886             dumpDec< sal_Int32 >( "count" );
1887             mxOut->resetItemIndex();
1888             while( mxStrm->getRemaining() >= 4 )
1889                 dumpDec< sal_Int32 >( "#field", "PT-FIELDINDEX" );
1890         break;
1891 
1892         case BIFF12_ID_PTDATAFIELD:
1893             dumpDec< sal_Int32 >( "field" );
1894             dumpDec< sal_Int32 >( "subtotal", "PTDATAFIELD-SUBTOTAL" );
1895             dumpDec< sal_Int32 >( "show-data-as", "PTDATAFIELD-SHOWDATAAS" );
1896             dumpDec< sal_Int32 >( "base-field" );
1897             dumpDec< sal_Int32 >( "base-item", "PTDATAFIELD-BASEITEM" );
1898             dumpDec< sal_Int32 >( "number-format" );
1899             if( dumpBool< sal_uInt8 >( "has-name" ) )
1900                 dumpString( "name" );
1901         break;
1902 
1903         case BIFF12_ID_PTDEFINITION:
1904         {
1905             dumpDec< sal_uInt8 >( "created-version" );
1906             dumpHex< sal_uInt8 >( "flags-1", "PTDEFINITION-FLAGS1" );
1907             dumpHex< sal_uInt16 >( "flags-2", "PTDEFINITION-FLAGS2" );
1908             sal_uInt32 nFlags3 = dumpHex< sal_uInt32 >( "flags-3", "PTDEFINITION-FLAGS3" );
1909             sal_uInt32 nFlags4 = dumpHex< sal_uInt32 >( "flags-4", "PTDEFINITION-FLAGS4" );
1910             dumpDec< sal_uInt8 >( "datafield-axis", "PTDEFINITION-DATAFIELD-AXIS" );
1911             dumpDec< sal_uInt8 >( "page-wrap" );
1912             dumpDec< sal_uInt8 >( "refreshed-version" );
1913             dumpDec< sal_uInt8 >( "min-refresh-version" );
1914             dumpDec< sal_Int32 >( "datafield-position", "PTDEFINITION-DATAFIELD-POS" );
1915             dumpDec< sal_Int16 >( "autoformat-id" );
1916             dumpUnused( 2 );
1917             dumpDec< sal_Int32 >( "next-chart-id" );
1918             dumpDec< sal_Int32 >( "cache-id" );
1919             dumpString( "name" );
1920             if( nFlags3 & 0x00080000 ) dumpString( "data-caption" );
1921             if( nFlags3 & 0x00100000 ) dumpString( "grand-total-caption" );
1922             if( (nFlags4 & 0x00000040) == 0 ) dumpString( "error-caption" );
1923             if( (nFlags4 & 0x00000080) == 0 ) dumpString( "missing-caption" );
1924             if( nFlags3 & 0x00200000 ) dumpString( "page-field-style" );
1925             if( nFlags3 & 0x00400000 ) dumpString( "pivot-table-style" );
1926             if( nFlags3 & 0x00800000 ) dumpString( "vacated-style" );
1927             if( nFlags3 & 0x40000000 ) dumpString( "tag" );
1928             if( nFlags4 & 0x00000800 ) dumpString( "col-header-caption" );
1929             if( nFlags4 & 0x00000400 ) dumpString( "row-header-caption" );
1930         }
1931         break;
1932 
1933         case BIFF12_ID_PTFIELD:
1934             dumpHex< sal_uInt32 >( "flags-1", "PTFIELD-FLAGS1" );
1935             dumpDec< sal_Int32 >( "num-fmt" );
1936             dumpHex< sal_uInt32 >( "flags-2", "PTFIELD-FLAGS2" );
1937             dumpDec< sal_Int32 >( "autoshow-items" );
1938             dumpDec< sal_Int32 >( "autoshow-datafield-idx" );
1939         break;
1940 
1941         case BIFF12_ID_PTFILTER:
1942         {
1943             dumpDec< sal_Int32 >( "field" );
1944             dumpDec< sal_Int32 >( "member-prop-field" );
1945             dumpDec< sal_Int32 >( "type", "PTFILTER-TYPE" );
1946             dumpUnused( 4 );
1947             dumpDec< sal_Int32 >( "unique-id" );
1948             dumpDec< sal_Int32 >( "measure-data-field" );
1949             dumpDec< sal_Int32 >( "measure-data-hierarchy" );
1950             sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "PTFILTER-FLAGS" );
1951             if( nFlags & 0x0001 ) dumpString( "name" );
1952             if( nFlags & 0x0002 ) dumpString( "description" );
1953             if( nFlags & 0x0004 ) dumpString( "str-value1" );
1954             if( nFlags & 0x0008 ) dumpString( "str-value2" );
1955         }
1956         break;
1957 
1958         case BIFF12_ID_PTFITEM:
1959         {
1960             dumpDec< sal_uInt8 >( "type", "PTFITEM-TYPE" );
1961             sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "PTFITEM-FLAGS" );
1962             dumpDec< sal_Int32 >( "cache-idx" );
1963             if( nFlags & 0x0010 ) dumpString( "display-name" );
1964         }
1965         break;
1966 
1967         case BIFF12_ID_PTLOCATION:
1968             dumpRange( "location" );
1969             dumpDec< sal_Int32 >( "first-header-row" );
1970             dumpDec< sal_Int32 >( "first-data-row" );
1971             dumpDec< sal_Int32 >( "first-data-col" );
1972             dumpDec< sal_Int32 >( "page-row-count" );
1973             dumpDec< sal_Int32 >( "page-col-count" );
1974         break;
1975 
1976         case BIFF12_ID_PTPAGEFIELD:
1977         {
1978             dumpDec< sal_Int32 >( "field" );
1979             dumpDec< sal_Int32 >( "cache-item", "PTPAGEFIELD-ITEM" );
1980             dumpDec< sal_Int32 >( "olap-hierarchy" );
1981             sal_uInt8 nFlags = dumpHex< sal_uInt8 >( "flags", "PTPAGEFIELD-FLAGS" );
1982             if( nFlags & 0x01 ) dumpString( "unique-name" );
1983             if( nFlags & 0x02 ) dumpString( "olap-caption" );
1984         }
1985         break;
1986 
1987         case BIFF12_ID_PTREFERENCE:
1988             dumpDec< sal_Int32 >( "field", "PT-FIELDINDEX" );
1989             dumpDec< sal_Int32 >( "item-count" );
1990             dumpHex< sal_uInt16 >( "flags-1", "PTREFERENCE-FLAGS1" );
1991             dumpHex< sal_uInt8 >( "flags-2", "PTREFERENCE-FLAGS2" );
1992         break;
1993 
1994         case BIFF12_ID_PTROWFIELDS:
1995             dumpDec< sal_Int32 >( "count" );
1996             mxOut->resetItemIndex();
1997             while( mxStrm->getRemaining() >= 4 )
1998                 dumpDec< sal_Int32 >( "#field", "PT-FIELDINDEX" );
1999         break;
2000 
2001         case BIFF12_ID_QUERYTABLE:
2002             dumpHex< sal_uInt32 >( "flags", "QUERYTABLE-FLAGS" );
2003             dumpDec< sal_uInt16 >( "autoformat-id" );
2004             dumpDec< sal_Int32 >( "connection-id" );
2005             dumpString( "defined-name" );
2006         break;
2007 
2008         case BIFF12_ID_ROW:
2009             dumpRowIndex();
2010             dumpDec< sal_Int32 >( "custom-xf-id" );
2011             dumpDec< sal_uInt16 >( "height", "CONV-TWIP-TO-PT" );
2012             dumpHex< sal_uInt16 >( "flags", "ROW-FLAGS1" );
2013             dumpHex< sal_uInt8 >( "flags", "ROW-FLAGS2" );
2014             mxOut->resetItemIndex();
2015             for( sal_Int32 nSpan = 0, nSpanCount = dumpDec< sal_Int32 >( "row-spans-count" ); !mxStrm->isEof() && (nSpan < nSpanCount); ++nSpan )
2016                 dumpRowRange( "#row-spans" );
2017         break;
2018 
2019         case BIFF12_ID_ROWBREAKS:
2020             dumpDec< sal_Int32 >( "count" );
2021             dumpDec< sal_Int32 >( "manual-count" );
2022         break;
2023 
2024         case BIFF12_ID_SCENARIO:
2025             dumpDec< sal_uInt16 >( "cell-count" );
2026             // two longs instead of flag field
2027             dumpDec< sal_Int32 >( "locked", "BOOLEAN" );
2028             dumpDec< sal_Int32 >( "hidden", "BOOLEAN" );
2029             dumpString( "name" );
2030             dumpString( "comment" );
2031             dumpString( "user" );
2032         break;
2033 
2034         case BIFF12_ID_SCENARIOS:
2035             dumpDec< sal_uInt16 >( "selected" );
2036             dumpDec< sal_uInt16 >( "shown" );
2037             dumpRangeList( "result-cells" );
2038         break;
2039 
2040         case BIFF12_ID_SELECTION:
2041             dumpDec< sal_Int32 >( "pane", "PANE-ID" );
2042             dumpAddress( "active-cell" );
2043             dumpDec< sal_Int32 >( "active-cell-id" );
2044             dumpRangeList( "selection" );
2045         break;
2046 
2047         case BIFF12_ID_SHAREDFMLA:
2048             dumpRange( "formula-range" );
2049             mxFmlaObj->dumpCellFormula();
2050         break;
2051 
2052         case BIFF12_ID_SHEET:
2053             dumpDec< sal_Int32 >( "sheet-state", "SHEET-STATE" );
2054             dumpDec< sal_Int32 >( "sheet-id" );
2055             dumpString( "rel-id" );
2056             dumpString( "sheet-name" );
2057         break;
2058 
2059         case BIFF12_ID_SHEETFORMATPR:
2060             dumpDec< sal_Int32 >( "default-col-width", "CONV-COLWIDTH" );
2061             dumpDec< sal_uInt16 >( "base-col-width" );
2062             dumpDec< sal_uInt16 >( "default-row-height", "CONV-TWIP-TO-PT" );
2063             dumpHex< sal_uInt16 >( "flags", "SHEETFORMATPR-FLAGS" );
2064             dumpDec< sal_uInt8 >( "max-row-outline" );
2065             dumpDec< sal_uInt8 >( "max-col-outline" );
2066         break;
2067 
2068         case BIFF12_ID_SHEETPR:
2069             dumpHex< sal_uInt16 >( "flags1", "SHEETPR-FLAGS1" );
2070             dumpHex< sal_uInt8 >( "flags2", "SHEETPR-FLAGS2" );
2071             dumpColor( "tab-color" );
2072             dumpAddress( "window-anchor" );
2073             dumpString( "codename" );
2074         break;
2075 
2076         case BIFF12_ID_SHEETPROTECTION:
2077             dumpHex< sal_uInt16 >( "password-hash" );
2078             // no flags field for all these boolean flags?!?
2079             dumpDec< sal_Int32 >( "sheet-locked", "BOOLEAN" );
2080             dumpDec< sal_Int32 >( "objects-locked", "BOOLEAN" );
2081             dumpDec< sal_Int32 >( "scenarios-locked", "BOOLEAN" );
2082             dumpDec< sal_Int32 >( "format-cells-locked", "BOOLEAN" );
2083             dumpDec< sal_Int32 >( "format-columns-locked", "BOOLEAN" );
2084             dumpDec< sal_Int32 >( "format-rows-locked", "BOOLEAN" );
2085             dumpDec< sal_Int32 >( "insert-columns-locked", "BOOLEAN" );
2086             dumpDec< sal_Int32 >( "insert-rows-locked", "BOOLEAN" );
2087             dumpDec< sal_Int32 >( "insert-hyperlinks-locked", "BOOLEAN" );
2088             dumpDec< sal_Int32 >( "delete-columns-locked", "BOOLEAN" );
2089             dumpDec< sal_Int32 >( "delete-rows-locked", "BOOLEAN" );
2090             dumpDec< sal_Int32 >( "select-locked-cells-locked", "BOOLEAN" );
2091             dumpDec< sal_Int32 >( "sort-locked", "BOOLEAN" );
2092             dumpDec< sal_Int32 >( "autofilter-locked", "BOOLEAN" );
2093             dumpDec< sal_Int32 >( "pivot-tables-locked", "BOOLEAN" );
2094             dumpDec< sal_Int32 >( "select-unlocked-cells-locked", "BOOLEAN" );
2095         break;
2096 
2097         case BIFF12_ID_SHEETVIEW:
2098             dumpHex< sal_uInt16 >( "flags", "SHEETVIEW-FLAGS" );
2099             dumpDec< sal_Int32 >( "view-type", "SHEETVIEW-TYPE" );
2100             dumpAddress( "top-left" );
2101             dumpDec< sal_Int32 >( "gridcolor-id", "PALETTE-COLORS" );
2102             dumpDec< sal_uInt16 >( "zoom-scale", "CONV-PERCENT" );
2103             dumpDec< sal_uInt16 >( "zoom-scale-normal", "CONV-PERCENT" );
2104             dumpDec< sal_uInt16 >( "zoom-scale-sheet-layout", "CONV-PERCENT" );
2105             dumpDec< sal_uInt16 >( "zoom-scale-page-layout", "CONV-PERCENT" );
2106             dumpDec< sal_Int32 >( "workbookview-id" );
2107         break;
2108 
2109         case BIFF12_ID_SI:
2110             dumpString( "string", true );
2111         break;
2112 
2113         case BIFF12_ID_SST:
2114             dumpDec< sal_Int32 >( "string-cell-count" );
2115             dumpDec< sal_Int32 >( "sst-size" );
2116         break;
2117 
2118         case BIFF12_ID_TABLE:
2119             dumpRange();
2120             dumpDec< sal_Int32 >( "type", "TABLE-TYPE" );
2121             dumpDec< sal_Int32 >( "id" );
2122             dumpDec< sal_Int32 >( "header-rows" );
2123             dumpDec< sal_Int32 >( "totals-rows" );
2124             dumpHex< sal_uInt32 >( "flags", "TABLE-FLAGS" );
2125             dumpDec< sal_Int32 >( "headerrow-dxf-id" );
2126             dumpDec< sal_Int32 >( "data-dxf-id" );
2127             dumpDec< sal_Int32 >( "totalsrow-dxf-id" );
2128             dumpDec< sal_Int32 >( "table-border-dxf-id" );
2129             dumpDec< sal_Int32 >( "headerrow-border-dxf-id" );
2130             dumpDec< sal_Int32 >( "totalsrow-border-dxf-id" );
2131             dumpDec< sal_Int32 >( "connection-id" );
2132             dumpString( "name" );
2133             dumpString( "display-name" );
2134             dumpString( "comment" );
2135             dumpString( "headerrow-cell-style" );
2136             dumpString( "data-cell-style" );
2137             dumpString( "totalsrow-cell-style" );
2138         break;
2139 
2140         case BIFF12_ID_TABLEPART:
2141             dumpString( "rel-id" );
2142         break;
2143 
2144         case BIFF12_ID_TABLESTYLEINFO:
2145             dumpHex< sal_uInt16 >( "flags", "TABLESTYLEINFO-FLAGS" );
2146             dumpString( "style-name" );
2147         break;
2148 
2149         case BIFF12_ID_TOP10FILTER:
2150             dumpHex< sal_uInt8 >( "flags", "TOP10FILTER-FLAGS" );
2151             dumpDec< double >( "value" );
2152             dumpDec< double >( "cell-value" );
2153         break;
2154 
2155         case BIFF12_ID_VOLTYPEMAIN:
2156             dumpString( "first" );
2157         break;
2158 
2159         case BIFF12_ID_VOLTYPESTP:
2160             dumpString( "topic-value" );
2161         break;
2162 
2163         case BIFF12_ID_VOLTYPETR:
2164             dumpAddress( "ref" );
2165             dumpDec< sal_Int32 >( "sheet-id" );
2166         break;
2167 
2168         case BIFF12_ID_WEBPR:
2169         {
2170             dumpHex< sal_uInt32 >( "flags", "WEBPR-FLAGS" );
2171             sal_uInt8 nStrFlags = dumpHex< sal_uInt8 >( "string-flags", "WEBPR-STRINGFLAGS" );
2172             if( nStrFlags & 0x04 ) dumpString( "url" );
2173             if( nStrFlags & 0x01 ) dumpString( "post-method" );
2174             if( nStrFlags & 0x02 ) dumpString( "edit-page" );
2175         }
2176         break;
2177 
2178         case BIFF12_ID_WORKBOOKPR:
2179             dumpHex< sal_uInt32 >( "flags", "WORKBBOKPR-FLAGS" );
2180             dumpDec< sal_Int32 >( "default-theme-version" );
2181             dumpString( "codename" );
2182         break;
2183 
2184         case BIFF12_ID_WORKBOOKVIEW:
2185             dumpDec< sal_Int32 >( "x-window" );
2186             dumpDec< sal_Int32 >( "y-window" );
2187             dumpDec< sal_Int32 >( "win-width" );
2188             dumpDec< sal_Int32 >( "win-height" );
2189             dumpDec< sal_Int32 >( "tabbar-ratio" );
2190             dumpDec< sal_Int32 >( "first-sheet" );
2191             dumpDec< sal_Int32 >( "active-sheet" );
2192             dumpHex< sal_uInt8 >( "flags", "WORKBOOKVIEW-FLAGS" );
2193         break;
2194 
2195         case BIFF12_ID_XF:
2196             dumpDec< sal_uInt16 >( "parent-xf-id" );
2197             dumpDec< sal_uInt16 >( "numfmt-id" );
2198             dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" );
2199             dumpDec< sal_uInt16 >( "fill-id" );
2200             dumpDec< sal_uInt16 >( "border-id" );
2201             dumpHex< sal_uInt32 >( "alignment", "XF-ALIGNMENT" );
2202             dumpHex< sal_uInt16 >( "used-flags", "XF-USEDFLAGS" );
2203         break;
2204     }
2205 }
2206 
dumpGradientHead()2207 void RecordStreamObject::dumpGradientHead()
2208 {
2209     dumpDec< sal_Int32 >( "gradient-type", "FILL-GRADIENTTYPE" );
2210     dumpDec< double >( "linear-angle" );
2211     dumpDec< double >( "pos-left" );
2212     dumpDec< double >( "pos-right" );
2213     dumpDec< double >( "pos-top" );
2214     dumpDec< double >( "pos-bottom" );
2215 }
2216 
dumpCellHeader(bool bWithColumn)2217 void RecordStreamObject::dumpCellHeader( bool bWithColumn )
2218 {
2219     if( bWithColumn ) dumpColIndex();
2220     dumpHex< sal_uInt32 >( "xf-id", "CELL-XFID" );
2221 }
2222 
2223 // ============================================================================
2224 
RootStorageObject(const DumperBase & rParent)2225 RootStorageObject::RootStorageObject( const DumperBase& rParent )
2226 {
2227     StorageObjectBase::construct( rParent );
2228 }
2229 
implDumpStream(const Reference<XInputStream> & rxStrm,const OUString & rStrgPath,const OUString & rStrmName,const OUString & rSysFileName)2230 void RootStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName )
2231 {
2232     OUString aExt = InputOutputHelper::getFileNameExtension( rStrmName );
2233     if(
2234         aExt.equalsIgnoreAsciiCaseAscii( "xlsb" ) ||
2235         aExt.equalsIgnoreAsciiCaseAscii( "xlsm" ) ||
2236         aExt.equalsIgnoreAsciiCaseAscii( "xlsx" ) ||
2237         aExt.equalsIgnoreAsciiCaseAscii( "xltm" ) ||
2238         aExt.equalsIgnoreAsciiCaseAscii( "xltx" ) )
2239     {
2240         Dumper( getContext(), rxStrm, rSysFileName ).dump();
2241     }
2242     else if(
2243         aExt.equalsIgnoreAsciiCaseAscii( "xla" ) ||
2244         aExt.equalsIgnoreAsciiCaseAscii( "xlc" ) ||
2245         aExt.equalsIgnoreAsciiCaseAscii( "xlm" ) ||
2246         aExt.equalsIgnoreAsciiCaseAscii( "xls" ) ||
2247         aExt.equalsIgnoreAsciiCaseAscii( "xlt" ) ||
2248         aExt.equalsIgnoreAsciiCaseAscii( "xlw" ) )
2249     {
2250         ::oox::dump::biff::Dumper( getContext(), rxStrm, rSysFileName ).dump();
2251     }
2252     else if(
2253         aExt.equalsIgnoreAsciiCaseAscii( "pptx" ) ||
2254         aExt.equalsIgnoreAsciiCaseAscii( "potx" ) )
2255     {
2256         ::oox::dump::pptx::Dumper( getContext(), rxStrm, rSysFileName ).dump();
2257     }
2258     else if(
2259         aExt.equalsIgnoreAsciiCaseAscii( "xml" ) ||
2260         aExt.equalsIgnoreAsciiCaseAscii( "vml" ) ||
2261         aExt.equalsIgnoreAsciiCaseAscii( "rels" ) )
2262     {
2263         XmlStreamObject( *this, rxStrm, rSysFileName ).dump();
2264     }
2265     else if( aExt.equalsIgnoreAsciiCaseAscii( "bin" ) )
2266     {
2267         if( rStrgPath.equalsAscii( "xl" ) && rStrmName.equalsAscii( "vbaProject.bin" ) )
2268         {
2269             StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) );
2270             VbaProjectStorageObject( *this, xStrg, rSysFileName ).dump();
2271         }
2272         else if( rStrgPath.equalsAscii( "xl/embeddings" ) )
2273         {
2274             StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) );
2275             OleStorageObject( *this, xStrg, rSysFileName ).dump();
2276         }
2277         else if(
2278             rStrgPath.equalsAscii( "xl" ) ||
2279             rStrgPath.equalsAscii( "xl/chartsheets" ) ||
2280             rStrgPath.equalsAscii( "xl/dialogsheets" ) ||
2281             rStrgPath.equalsAscii( "xl/externalLinks" ) ||
2282             rStrgPath.equalsAscii( "xl/macrosheets" ) ||
2283             rStrgPath.equalsAscii( "xl/pivotCache" ) ||
2284             rStrgPath.equalsAscii( "xl/pivotTables" ) ||
2285             rStrgPath.equalsAscii( "xl/queryTables" ) ||
2286             rStrgPath.equalsAscii( "xl/tables" ) ||
2287             rStrgPath.equalsAscii( "xl/worksheets" ) )
2288         {
2289             RecordStreamObject( *this, rxStrm, rSysFileName ).dump();
2290         }
2291         else if( rStrgPath.equalsAscii( "xl/activeX" ) )
2292         {
2293             StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, true ) );
2294             ActiveXStorageObject( *this, xStrg, rSysFileName ).dump();
2295         }
2296         else
2297         {
2298             BinaryStreamObject( *this, rxStrm, rSysFileName ).dump();
2299         }
2300     }
2301 }
2302 
2303 // ============================================================================
2304 
2305 #define DUMP_XLSB_CONFIG_ENVVAR "OOO_XLSBDUMPER"
2306 
Dumper(const FilterBase & rFilter)2307 Dumper::Dumper( const FilterBase& rFilter )
2308 {
2309     ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rFilter ) );
2310     DumperBase::construct( xCfg );
2311 }
2312 
Dumper(const Reference<XComponentContext> & rxContext,const Reference<XInputStream> & rxInStrm,const OUString & rSysFileName)2313 Dumper::Dumper( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName )
2314 {
2315     if( rxContext.is() && rxInStrm.is() )
2316     {
2317         StorageRef xStrg( new ZipStorage( getContext(), rxInStrm ) );
2318         MediaDescriptor aMediaDesc;
2319         ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rxContext, xStrg, rSysFileName, aMediaDesc ) );
2320         DumperBase::construct( xCfg );
2321     }
2322 }
2323 
implDump()2324 void Dumper::implDump()
2325 {
2326     RootStorageObject( *this ).dump();
2327 }
2328 
2329 // ============================================================================
2330 
2331 } // namespace xlsb
2332 } // namespace dump
2333 } // namespace oox
2334 
2335 #endif
2336