1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/math.hxx>
21 #include <rtl/character.hxx>
25 #include <scitems.hxx>
26 #include <patattr.hxx>
27 #include <docpool.hxx>
28 #include <editeng/postitem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/wghtitem.hxx>
31 #include <editeng/justifyitem.hxx>
32 #include <comphelper/configuration.hxx>
34 #include <formulacell.hxx>
35 #include <document.hxx>
41 #include "lotfilter.hxx"
42 #include <lotform.hxx>
43 #include <lotrange.hxx>
50 static sal_uInt16 nDefWidth
= sal_uInt16( TWIPS_PER_CHAR
* 10 );
52 void NI(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
57 void OP_BOF(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16
/*n*/)
59 r
.SeekRel( 2 ); // skip version number
62 void OP_EOF(LotusContext
& rContext
, SvStream
& /*r*/, sal_uInt16
/*n*/)
67 void OP_Integer(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
70 sal_uInt16
nTmpCol(0), nTmpRow(0);
72 r
.ReadUChar(nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
).ReadInt16(nValue
);
73 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
74 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
76 ScAddress
aAddr(nCol
, nRow
, 0);
77 if (rContext
.rDoc
.ValidAddress(aAddr
))
79 rContext
.rDoc
.EnsureTable(0);
80 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
81 rContext
.rDoc
.SetValue(aAddr
, static_cast<double>(nValue
));
83 // 0 digits in fractional part!
84 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, 0);
88 void OP_Number(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
91 sal_uInt16
nTmpCol(0), nTmpRow(0);
93 r
.ReadUChar( nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
).ReadDouble(fValue
);
94 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
95 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
97 ScAddress
aAddr(nCol
, nRow
, 0);
98 if (rContext
.rDoc
.ValidAddress(aAddr
))
100 fValue
= ::rtl::math::round( fValue
, 15 );
101 rContext
.rDoc
.EnsureTable(0);
102 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
103 rContext
.rDoc
.SetValue(aAddr
, fValue
);
105 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalFloat
);
109 void OP_Label(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
111 sal_uInt8
nFormat(0);
112 sal_uInt16
nTmpCol(0), nTmpRow(0);
113 r
.ReadUChar(nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
);
114 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
115 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
117 n
-= std::min
<sal_uInt16
>(n
, 5);
119 std::vector
<char> aText(n
+ 1);
120 n
= r
.ReadBytes(aText
.data(), n
);
123 if (rContext
.rDoc
.ValidColRow(nCol
, nRow
))
125 nFormat
&= 0x80; // don't change Bit 7
126 nFormat
|= 0x75; // protected does not matter, special-text is set
128 PutFormString(rContext
, nCol
, nRow
, 0, aText
.data());
130 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalStd
);
134 void OP_Formula(LotusContext
&rContext
, SvStream
& r
, sal_uInt16
/*n*/)
136 sal_uInt8
nFormat(0);
137 sal_uInt16
nTmpCol(0), nTmpRow(0);
138 r
.ReadUChar(nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
);
139 r
.SeekRel(8); // skip result
140 sal_uInt16
nFormulaSize(0);
141 r
.ReadUInt16(nFormulaSize
);
143 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
144 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
146 std::unique_ptr
<ScTokenArray
> pResult
;
147 sal_Int32 nBytesLeft
= nFormulaSize
;
148 ScAddress
aAddress(nCol
, nRow
, 0);
150 svl::SharedStringPool
& rSPool
= rContext
.rDoc
.GetSharedStringPool();
151 LotusToSc
aConv(rContext
, r
, rSPool
, rContext
.eCharset
, false);
152 aConv
.Reset( aAddress
);
153 aConv
.Convert( pResult
, nBytesLeft
);
157 if (rContext
.rDoc
.ValidColRow(nCol
, nRow
))
159 ScFormulaCell
* pCell
= new ScFormulaCell(rContext
.rDoc
, aAddress
, std::move(pResult
));
160 pCell
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
161 rContext
.rDoc
.EnsureTable(0);
162 // coverity[tainted_data : FALSE] - ValidColRow has sanitized aAddr
163 rContext
.rDoc
.SetFormulaCell(ScAddress(nCol
, nRow
, 0), pCell
);
165 // nFormat = Default -> number of digits in fractional part like Float
166 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalFloat
);
170 void OP_ColumnWidth(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
172 sal_uInt16
nTmpCol(0);
173 sal_uInt8
nWidthSpaces(0);
174 r
.ReadUInt16(nTmpCol
).ReadUChar(nWidthSpaces
);
175 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
177 if (!rContext
.rDoc
.ValidCol(nCol
))
180 nCol
= rContext
.rDoc
.SanitizeCol(nCol
);
184 // assuming 10cpi character set
185 nBreite
= static_cast<sal_uInt16
>( TWIPS_PER_CHAR
* nWidthSpaces
);
188 rContext
.rDoc
.SetColHidden(nCol
, nCol
, 0, true);
192 rContext
.rDoc
.SetColWidth(nCol
, 0, nBreite
);
195 void OP_NamedRange(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
197 // POST: don't save for invalid coordinates
198 sal_uInt16 nColSt
, nRowSt
, nColEnd
, nRowEnd
;
200 char cBuffer
[ 16+1 ];
201 r
.ReadBytes(cBuffer
, 16);
204 r
.ReadUInt16( nColSt
).ReadUInt16( nRowSt
).ReadUInt16( nColEnd
).ReadUInt16( nRowEnd
);
209 if (!rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColSt
), nRowSt
) || !rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColEnd
), nRowEnd
))
212 std::unique_ptr
<LotusRange
> pRange
;
214 if( nColSt
== nColEnd
&& nRowSt
== nRowEnd
)
215 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
) ));
217 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
),
218 static_cast<SCCOL
> (nColEnd
), static_cast<SCROW
> (nRowEnd
) ));
220 char cBuf
[sizeof(cBuffer
)+1];
221 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer
) ) )
222 { // first char in name is a number -> prepend 'A'
224 strcpy( cBuf
+ 1, cBuffer
); // #100211# - checked
227 strcpy( cBuf
, cBuffer
); // #100211# - checked
229 OUString
aTmp( cBuf
, strlen(cBuf
), rContext
.eCharset
);
231 aTmp
= ScfTools::ConvertToScDefinedName( aTmp
);
233 rContext
.maRangeNames
.Append( &rContext
.rDoc
, std::move(pRange
) );
236 void OP_SymphNamedRange(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
238 // POST:don't save for invalid coordinates
239 sal_uInt16 nColSt
, nRowSt
, nColEnd
, nRowEnd
;
242 char cBuffer
[ 16+1 ];
243 r
.ReadBytes(cBuffer
, 16);
246 r
.ReadUInt16( nColSt
).ReadUInt16( nRowSt
).ReadUInt16( nColEnd
).ReadUInt16( nRowEnd
).ReadUChar( nType
);
251 if (!rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColSt
), nRowSt
) || !rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColEnd
), nRowEnd
))
254 std::unique_ptr
<LotusRange
> pRange
;
257 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
) ));
259 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
),
260 static_cast<SCCOL
> (nColEnd
), static_cast<SCROW
> (nRowEnd
) ));
262 char cBuf
[sizeof(cBuffer
)+1];
263 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer
) ) )
264 { // first char in name is a number -> prepend 'A'
266 strcpy( cBuf
+ 1, cBuffer
); // #100211# - checked
269 strcpy( cBuf
, cBuffer
); // #100211# - checked
271 OUString
aTmp( cBuf
, strlen(cBuf
), rContext
.eCharset
);
272 aTmp
= ScfTools::ConvertToScDefinedName( aTmp
);
274 rContext
.maRangeNames
.Append( &rContext
.rDoc
, std::move(pRange
) );
277 void OP_Footer(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
282 void OP_Header(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
287 void OP_Margins(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
292 void OP_HiddenCols(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
295 for (sal_uInt16 nByte
= 0; nByte
< 32; ++nByte
) // 32 Bytes with ...
297 sal_uInt8
nCurrent(0);
298 r
.ReadUChar(nCurrent
);
299 for (sal_uInt16 nBit
= 0; nBit
< 8; ++nBit
) // ...each 8 Bits = 256 Bits
301 if( nCurrent
& 0x01 ) // is lowest Bit set?
304 rContext
.rDoc
.SetColHidden(nCount
, nCount
, 0, true);
308 nCurrent
= nCurrent
/ 2; // the next please...
313 void OP_Window1(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
315 r
.SeekRel( 4 ); // skip Cursor Pos
317 sal_uInt8 nDefaultFormat
; // -> op.cpp, standard cell format
318 r
.ReadUChar(nDefaultFormat
);
320 r
.SeekRel( 1 ); // skip 'unused'
322 r
.ReadUInt16( nDefWidth
);
326 r
.SeekRel( n
- 8 ); // skip the rest
328 nDefWidth
= static_cast<sal_uInt16
>( TWIPS_PER_CHAR
* nDefWidth
);
330 const bool bFuzzing
= comphelper::IsFuzzing();
332 // instead of default, set all Cols in SC by hand
333 for (SCCOL nCol
= 0 ; nCol
<= rContext
.rDoc
.MaxCol() ; nCol
++)
335 rContext
.rDoc
.SetColWidth( nCol
, 0, nDefWidth
);
341 void OP_Blank(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
343 sal_uInt8
nFormat(0);
344 sal_uInt16
nTmpCol(0), nTmpRow(0);
345 r
.ReadUChar( nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
);
346 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
347 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
349 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalFloat
);
352 void OP_BOF123(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16
/*n*/)
357 void OP_EOF123(LotusContext
& rContext
, SvStream
& /*r*/, sal_uInt16
/*n*/)
359 rContext
.bEOF
= true;
362 void OP_Label123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
364 sal_uInt8
nTmpTab(0), nTmpCol(0);
365 sal_uInt16
nTmpRow(0);
366 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
367 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
368 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
369 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
371 n
-= std::min
<sal_uInt16
>(n
, 4);
373 std::unique_ptr
<char[]> pText(new char[n
+ 1]);
374 r
.ReadBytes(pText
.get(), n
);
377 PutFormString(rContext
, nCol
, nRow
, nTab
, pText
.get());
380 void OP_Number123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
382 sal_uInt16
nTmpRow(0);
383 sal_uInt8
nTmpCol(0), nTmpTab(0);
384 sal_uInt32
nValue(0);
385 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
).ReadUInt32(nValue
);
386 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
387 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
388 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
390 ScAddress
aAddr(nCol
, nRow
, nTab
);
391 if (rContext
.rDoc
.ValidAddress(aAddr
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
393 double fValue
= Snum32ToDouble( nValue
);
394 rContext
.rDoc
.EnsureTable(nTab
);
395 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
396 rContext
.rDoc
.SetValue(aAddr
, fValue
);
400 void OP_Formula123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
402 sal_uInt16
nTmpRow(0);
403 sal_uInt8
nTmpCol(0), nTmpTab(0);
404 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
405 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
406 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
407 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
408 r
.SeekRel( 8 ); // skip Result
410 std::unique_ptr
<ScTokenArray
> pResult
;
411 sal_Int32 nBytesLeft
= (n
> 12) ? n
- 12 : 0;
412 ScAddress
aAddress(nCol
, nRow
, nTab
);
414 svl::SharedStringPool
& rSPool
= rContext
.rDoc
.GetSharedStringPool();
415 LotusToSc
aConv(rContext
, r
, rSPool
, rContext
.eCharset
, true);
416 aConv
.Reset( aAddress
);
417 aConv
.Convert( pResult
, nBytesLeft
);
421 if (rContext
.rDoc
.ValidAddress(aAddress
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
423 ScFormulaCell
* pCell
= new ScFormulaCell(rContext
.rDoc
, aAddress
, std::move(pResult
));
424 pCell
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
425 rContext
.rDoc
.EnsureTable(nTab
);
426 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
427 rContext
.rDoc
.SetFormulaCell(aAddress
, pCell
);
431 void OP_IEEENumber123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
433 sal_uInt16
nTmpRow(0);
434 sal_uInt8
nTmpCol(0), nTmpTab(0);
436 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
).ReadDouble(dValue
);
437 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
438 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
439 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
441 ScAddress
aAddr(nCol
, nRow
, nTab
);
442 if (rContext
.rDoc
.ValidAddress(aAddr
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
444 rContext
.rDoc
.EnsureTable(nTab
);
445 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
446 rContext
.rDoc
.SetValue(aAddr
, dValue
);
450 void OP_Note123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
452 sal_uInt16
nTmpRow(0);
453 sal_uInt8
nTmpTab(0), nTmpCol(0);
454 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
455 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
456 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
457 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
459 n
-= std::min
<sal_uInt16
>(n
, 4);
461 std::unique_ptr
<char[]> pText(new char[n
+ 1]);
462 r
.ReadBytes(pText
.get(), n
);
465 OUString
aNoteText(pText
.get(), strlen(pText
.get()), rContext
.eCharset
);
468 ScAddress
aPos(nCol
, nRow
, nTab
);
469 ScNoteUtil::CreateNoteFromString( rContext
.rDoc
, aPos
, aNoteText
, false, false );
472 void OP_HorAlign123(LotusContext
& /*rContext*/, sal_uInt8 nAlignPattern
, SfxItemSet
& rPatternItemSet
)
474 // pre: Pattern is stored in the last 3 bites of the 21st byte
475 // post: Appropriate Horizontal Alignment is set in rPattern according to the bit pattern.
477 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
478 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
480 nAlignPattern
= ( nAlignPattern
& 0x07);
482 switch (nAlignPattern
)
485 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Left
, ATTR_HOR_JUSTIFY
) );
488 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Right
, ATTR_HOR_JUSTIFY
) );
491 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Center
, ATTR_HOR_JUSTIFY
) );
494 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard
, ATTR_HOR_JUSTIFY
) );
497 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Block
, ATTR_HOR_JUSTIFY
) );
500 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard
, ATTR_HOR_JUSTIFY
) );
505 void OP_VerAlign123(LotusContext
& /*rContext*/, sal_uInt8 nAlignPattern
, SfxItemSet
& rPatternItemSet
)
507 // pre: Pattern is stored in the last 3 bites of the 22nd byte
508 // post: Appropriate Vertical Alignment is set in rPattern according to the bit pattern.
510 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
512 nAlignPattern
= ( nAlignPattern
& 0x07);
514 switch (nAlignPattern
)
517 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard
, ATTR_VER_JUSTIFY
) );
520 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Top
, ATTR_VER_JUSTIFY
) );
523 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Center
, ATTR_VER_JUSTIFY
) );
526 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Bottom
, ATTR_VER_JUSTIFY
) );
529 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard
, ATTR_VER_JUSTIFY
) );
534 void OP_CreatePattern123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
538 ScPatternAttr
aPattern(rContext
.rDoc
.getCellAttributeHelper());
539 SfxItemSet
& rItemSet
= aPattern
.GetItemSet();
541 r
.ReadUInt16( nCode
);
542 n
-= std::min
<sal_uInt16
>(n
, 2);
544 if ( nCode
== 0x0fd2 )
546 sal_uInt16 nPatternId
;
547 r
.ReadUInt16( nPatternId
);
549 sal_uInt8 Hor_Align
, Ver_Align
, temp
;
550 bool bIsBold
,bIsUnderLine
,bIsItalics
;
557 bIsBold
= (temp
& 0x01);
558 bIsItalics
= (temp
& 0x02);
559 bIsUnderLine
= (temp
& 0x04);
562 rItemSet
.Put( SvxWeightItem(WEIGHT_BOLD
,ATTR_FONT_WEIGHT
) );
564 rItemSet
.Put( SvxPostureItem(ITALIC_NORMAL
, ATTR_FONT_POSTURE
) );
566 rItemSet
.Put( SvxUnderlineItem( LINESTYLE_SINGLE
, ATTR_FONT_UNDERLINE
) );
571 r
.ReadUChar( Hor_Align
);
572 OP_HorAlign123(rContext
, Hor_Align
, rItemSet
);
574 r
.ReadUChar( Ver_Align
);
575 OP_VerAlign123(rContext
, Ver_Align
, rItemSet
);
577 rContext
.aLotusPatternPool
.emplace( nPatternId
, aPattern
);
578 n
-= std::min
<sal_uInt16
>(n
, 20);
583 void OP_SheetName123(LotusContext
& rContext
, SvStream
& rStream
, sal_uInt16 nLength
)
587 rStream
.SeekRel(nLength
);
591 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
592 rStream
.SeekRel(2); // ignore the first 2 bytes (B0 36).
593 sal_uInt16
nSheetNum(0);
594 rStream
.ReadUInt16(nSheetNum
);
596 const size_t nStrLen
= nLength
- 4;
597 std::vector
<char> sSheetName(nStrLen
+ 1);
598 sSheetName
[rStream
.ReadBytes(sSheetName
.data(), nStrLen
)] = 0;
600 if (!ValidTab(nSheetNum
))
602 // coverity[tainted_data : FALSE] - ValidTab has sanitized nSheetNum
603 rContext
.rDoc
.MakeTable(nSheetNum
);
604 if (!sSheetName
.empty())
606 OUString
aName(sSheetName
.data(), strlen(sSheetName
.data()), rContext
.eCharset
);
607 rContext
.rDoc
.RenameTab(nSheetNum
, aName
);
611 void OP_ApplyPatternArea123(LotusContext
& rContext
, SvStream
& rStream
)
613 sal_uInt16 nOpcode
, nLength
;
614 sal_uInt16 nCol
= 0, nColCount
= 0, nRow
= 0, nRowCount
= 0, nTab
= 0, nData
, nTabCount
= 0;
619 rStream
.ReadUInt16( nOpcode
).ReadUInt16( nLength
);
622 case ROW_FORMAT_MARKER
:
625 case COL_FORMAT_MARKER
:
629 nTab
= nTab
+ nTabCount
;
630 nCol
= 0; nColCount
= 0;
631 nRow
= 0; nRowCount
= 0;
634 case LOTUS_FORMAT_INDEX
:
637 rStream
.ReadUInt16( nData
);
638 rStream
.SeekRel( nLength
- 2 );
640 nTabCount
= SanitizeTab(nData
);
641 else if( nLevel
== 2 )
643 nCol
= nCol
+ nColCount
;
645 if ( nCol
> 0xff ) // 256 is the max col size supported by 123
648 else if( nLevel
== 3 )
650 nRow
= nRow
+ nRowCount
;
652 if ( nRow
> 0x1fff ) // 8192 is the max row size supported by 123
657 rStream
.SeekRel( nLength
);
659 case LOTUS_FORMAT_INFO
:
662 rStream
.ReadUInt16( nData
);
663 rStream
.SeekRel( nLength
- 2 );
664 std::map
<sal_uInt16
, ScPatternAttr
>::iterator loc
= rContext
.aLotusPatternPool
.find( nData
);
665 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
666 if ( loc
!= rContext
.aLotusPatternPool
.end() )
667 for( int i
= 0; i
< nTabCount
; i
++)
669 rContext
.rDoc
.ApplyPatternAreaTab( nCol
, nRow
, nCol
+ nColCount
- 1, nRow
+ nRowCount
- 1, static_cast< SCTAB
>( nTab
+ i
), loc
->second
);
673 rStream
.SeekRel( nLength
);
676 rStream
.SeekRel( nLength
);
680 while (nLevel
> 0 && rStream
.good());
682 rContext
.aLotusPatternPool
.clear();
685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */