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 <unotools/configmgr.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 rContext
.rDoc
.SetFormulaCell(ScAddress(nCol
, nRow
, 0), pCell
);
164 // nFormat = Default -> number of digits in fractional part like Float
165 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalFloat
);
169 void OP_ColumnWidth(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
171 sal_uInt16
nTmpCol(0);
172 sal_uInt8
nWidthSpaces(0);
173 r
.ReadUInt16(nTmpCol
).ReadUChar(nWidthSpaces
);
174 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
176 if (!rContext
.rDoc
.ValidCol(nCol
))
179 nCol
= rContext
.rDoc
.SanitizeCol(nCol
);
183 // assuming 10cpi character set
184 nBreite
= static_cast<sal_uInt16
>( TWIPS_PER_CHAR
* nWidthSpaces
);
187 rContext
.rDoc
.SetColHidden(nCol
, nCol
, 0, true);
191 rContext
.rDoc
.SetColWidth(nCol
, 0, nBreite
);
194 void OP_NamedRange(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
196 // POST: don't save for invalid coordinates
197 sal_uInt16 nColSt
, nRowSt
, nColEnd
, nRowEnd
;
199 char cBuffer
[ 16+1 ];
200 r
.ReadBytes(cBuffer
, 16);
203 r
.ReadUInt16( nColSt
).ReadUInt16( nRowSt
).ReadUInt16( nColEnd
).ReadUInt16( nRowEnd
);
208 if (!rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColSt
), nRowSt
) || !rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColEnd
), nRowEnd
))
211 std::unique_ptr
<LotusRange
> pRange
;
213 if( nColSt
== nColEnd
&& nRowSt
== nRowEnd
)
214 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
) ));
216 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
),
217 static_cast<SCCOL
> (nColEnd
), static_cast<SCROW
> (nRowEnd
) ));
219 char cBuf
[sizeof(cBuffer
)+1];
220 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer
) ) )
221 { // first char in name is a number -> prepend 'A'
223 strcpy( cBuf
+ 1, cBuffer
); // #100211# - checked
226 strcpy( cBuf
, cBuffer
); // #100211# - checked
228 OUString
aTmp( cBuf
, strlen(cBuf
), rContext
.eCharset
);
230 aTmp
= ScfTools::ConvertToScDefinedName( aTmp
);
232 rContext
.maRangeNames
.Append( &rContext
.rDoc
, std::move(pRange
) );
235 void OP_SymphNamedRange(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
237 // POST:don't save for invalid coordinates
238 sal_uInt16 nColSt
, nRowSt
, nColEnd
, nRowEnd
;
241 char cBuffer
[ 16+1 ];
242 r
.ReadBytes(cBuffer
, 16);
245 r
.ReadUInt16( nColSt
).ReadUInt16( nRowSt
).ReadUInt16( nColEnd
).ReadUInt16( nRowEnd
).ReadUChar( nType
);
250 if (!rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColSt
), nRowSt
) || !rContext
.rDoc
.ValidColRow(static_cast<SCCOL
>(nColEnd
), nRowEnd
))
253 std::unique_ptr
<LotusRange
> pRange
;
256 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
) ));
258 pRange
.reset(new LotusRange( static_cast<SCCOL
> (nColSt
), static_cast<SCROW
> (nRowSt
),
259 static_cast<SCCOL
> (nColEnd
), static_cast<SCROW
> (nRowEnd
) ));
261 char cBuf
[sizeof(cBuffer
)+1];
262 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer
) ) )
263 { // first char in name is a number -> prepend 'A'
265 strcpy( cBuf
+ 1, cBuffer
); // #100211# - checked
268 strcpy( cBuf
, cBuffer
); // #100211# - checked
270 OUString
aTmp( cBuf
, strlen(cBuf
), rContext
.eCharset
);
271 aTmp
= ScfTools::ConvertToScDefinedName( aTmp
);
273 rContext
.maRangeNames
.Append( &rContext
.rDoc
, std::move(pRange
) );
276 void OP_Footer(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
281 void OP_Header(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
286 void OP_Margins(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16 n
)
291 void OP_HiddenCols(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
294 for (sal_uInt16 nByte
= 0; nByte
< 32; ++nByte
) // 32 Bytes with ...
296 sal_uInt8
nCurrent(0);
297 r
.ReadUChar(nCurrent
);
298 for (sal_uInt16 nBit
= 0; nBit
< 8; ++nBit
) // ...each 8 Bits = 256 Bits
300 if( nCurrent
& 0x01 ) // is lowest Bit set?
303 rContext
.rDoc
.SetColHidden(nCount
, nCount
, 0, true);
307 nCurrent
= nCurrent
/ 2; // the next please...
312 void OP_Window1(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
314 r
.SeekRel( 4 ); // skip Cursor Pos
316 sal_uInt8 nDefaultFormat
; // -> op.cpp, standard cell format
317 r
.ReadUChar(nDefaultFormat
);
319 r
.SeekRel( 1 ); // skip 'unused'
321 r
.ReadUInt16( nDefWidth
);
325 r
.SeekRel( n
- 8 ); // skip the rest
327 nDefWidth
= static_cast<sal_uInt16
>( TWIPS_PER_CHAR
* nDefWidth
);
329 const bool bFuzzing
= utl::ConfigManager::IsFuzzing();
331 // instead of default, set all Cols in SC by hand
332 for (SCCOL nCol
= 0 ; nCol
<= rContext
.rDoc
.MaxCol() ; nCol
++)
334 rContext
.rDoc
.SetColWidth( nCol
, 0, nDefWidth
);
340 void OP_Blank(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
342 sal_uInt8
nFormat(0);
343 sal_uInt16
nTmpCol(0), nTmpRow(0);
344 r
.ReadUChar( nFormat
).ReadUInt16(nTmpCol
).ReadUInt16(nTmpRow
);
345 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
346 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
348 SetFormat(rContext
, nCol
, nRow
, 0, nFormat
, nFractionalFloat
);
351 void OP_BOF123(LotusContext
& /*rContext*/, SvStream
& r
, sal_uInt16
/*n*/)
356 void OP_EOF123(LotusContext
& rContext
, SvStream
& /*r*/, sal_uInt16
/*n*/)
358 rContext
.bEOF
= true;
361 void OP_Label123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
363 sal_uInt8
nTmpTab(0), nTmpCol(0);
364 sal_uInt16
nTmpRow(0);
365 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
366 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
367 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
368 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
370 n
-= std::min
<sal_uInt16
>(n
, 4);
372 std::unique_ptr
<char[]> pText(new char[n
+ 1]);
373 r
.ReadBytes(pText
.get(), n
);
376 PutFormString(rContext
, nCol
, nRow
, nTab
, pText
.get());
379 void OP_Number123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
381 sal_uInt16
nTmpRow(0);
382 sal_uInt8
nTmpCol(0), nTmpTab(0);
383 sal_uInt32
nValue(0);
384 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
).ReadUInt32(nValue
);
385 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
386 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
387 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
389 ScAddress
aAddr(nCol
, nRow
, nTab
);
390 if (rContext
.rDoc
.ValidAddress(aAddr
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
392 double fValue
= Snum32ToDouble( nValue
);
393 rContext
.rDoc
.EnsureTable(nTab
);
394 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
395 rContext
.rDoc
.SetValue(aAddr
, fValue
);
399 void OP_Formula123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
401 sal_uInt16
nTmpRow(0);
402 sal_uInt8
nTmpCol(0), nTmpTab(0);
403 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
404 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
405 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
406 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
407 r
.SeekRel( 8 ); // skip Result
409 std::unique_ptr
<ScTokenArray
> pResult
;
410 sal_Int32 nBytesLeft
= (n
> 12) ? n
- 12 : 0;
411 ScAddress
aAddress(nCol
, nRow
, nTab
);
413 svl::SharedStringPool
& rSPool
= rContext
.rDoc
.GetSharedStringPool();
414 LotusToSc
aConv(rContext
, r
, rSPool
, rContext
.eCharset
, true);
415 aConv
.Reset( aAddress
);
416 aConv
.Convert( pResult
, nBytesLeft
);
420 if (rContext
.rDoc
.ValidAddress(aAddress
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
422 ScFormulaCell
* pCell
= new ScFormulaCell(rContext
.rDoc
, aAddress
, std::move(pResult
));
423 pCell
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
424 rContext
.rDoc
.EnsureTable(nTab
);
425 rContext
.rDoc
.SetFormulaCell(aAddress
, pCell
);
429 void OP_IEEENumber123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16
/*n*/)
431 sal_uInt16
nTmpRow(0);
432 sal_uInt8
nTmpCol(0), nTmpTab(0);
434 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
).ReadDouble(dValue
);
435 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
436 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
437 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
439 ScAddress
aAddr(nCol
, nRow
, nTab
);
440 if (rContext
.rDoc
.ValidAddress(aAddr
) && nTab
<= rContext
.rDoc
.GetMaxTableNumber())
442 rContext
.rDoc
.EnsureTable(nTab
);
443 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
444 rContext
.rDoc
.SetValue(aAddr
, dValue
);
448 void OP_Note123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
450 sal_uInt16
nTmpRow(0);
451 sal_uInt8
nTmpTab(0), nTmpCol(0);
452 r
.ReadUInt16(nTmpRow
).ReadUChar(nTmpTab
).ReadUChar(nTmpCol
);
453 SCTAB
nTab(static_cast<SCTAB
>(nTmpTab
));
454 SCCOL
nCol(static_cast<SCCOL
>(nTmpCol
));
455 SCROW
nRow(static_cast<SCROW
>(nTmpRow
));
457 n
-= std::min
<sal_uInt16
>(n
, 4);
459 std::unique_ptr
<char[]> pText(new char[n
+ 1]);
460 r
.ReadBytes(pText
.get(), n
);
463 OUString
aNoteText(pText
.get(), strlen(pText
.get()), rContext
.eCharset
);
466 ScAddress
aPos(nCol
, nRow
, nTab
);
467 ScNoteUtil::CreateNoteFromString( rContext
.rDoc
, aPos
, aNoteText
, false, false );
470 void OP_HorAlign123(LotusContext
& /*rContext*/, sal_uInt8 nAlignPattern
, SfxItemSet
& rPatternItemSet
)
472 // pre: Pattern is stored in the last 3 bites of the 21st byte
473 // post: Appropriate Horizontal Alignment is set in rPattern according to the bit pattern.
475 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
476 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
478 nAlignPattern
= ( nAlignPattern
& 0x07);
480 switch (nAlignPattern
)
483 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Left
, ATTR_HOR_JUSTIFY
) );
486 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Right
, ATTR_HOR_JUSTIFY
) );
489 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Center
, ATTR_HOR_JUSTIFY
) );
492 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard
, ATTR_HOR_JUSTIFY
) );
495 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Block
, ATTR_HOR_JUSTIFY
) );
498 rPatternItemSet
.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard
, ATTR_HOR_JUSTIFY
) );
503 void OP_VerAlign123(LotusContext
& /*rContext*/, sal_uInt8 nAlignPattern
, SfxItemSet
& rPatternItemSet
)
505 // pre: Pattern is stored in the last 3 bites of the 22nd byte
506 // post: Appropriate Vertical Alignment is set in rPattern according to the bit pattern.
508 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
510 nAlignPattern
= ( nAlignPattern
& 0x07);
512 switch (nAlignPattern
)
515 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard
, ATTR_VER_JUSTIFY
) );
518 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Top
, ATTR_VER_JUSTIFY
) );
521 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Center
, ATTR_VER_JUSTIFY
) );
524 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Bottom
, ATTR_VER_JUSTIFY
) );
527 rPatternItemSet
.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard
, ATTR_VER_JUSTIFY
) );
532 void OP_CreatePattern123(LotusContext
& rContext
, SvStream
& r
, sal_uInt16 n
)
536 ScPatternAttr
aPattern(rContext
.rDoc
.GetPool());
537 SfxItemSet
& rItemSet
= aPattern
.GetItemSet();
539 r
.ReadUInt16( nCode
);
540 n
-= std::min
<sal_uInt16
>(n
, 2);
542 if ( nCode
== 0x0fd2 )
544 sal_uInt16 nPatternId
;
545 r
.ReadUInt16( nPatternId
);
547 sal_uInt8 Hor_Align
, Ver_Align
, temp
;
548 bool bIsBold
,bIsUnderLine
,bIsItalics
;
555 bIsBold
= (temp
& 0x01);
556 bIsItalics
= (temp
& 0x02);
557 bIsUnderLine
= (temp
& 0x04);
560 rItemSet
.Put( SvxWeightItem(WEIGHT_BOLD
,ATTR_FONT_WEIGHT
) );
562 rItemSet
.Put( SvxPostureItem(ITALIC_NORMAL
, ATTR_FONT_POSTURE
) );
564 rItemSet
.Put( SvxUnderlineItem( LINESTYLE_SINGLE
, ATTR_FONT_UNDERLINE
) );
569 r
.ReadUChar( Hor_Align
);
570 OP_HorAlign123(rContext
, Hor_Align
, rItemSet
);
572 r
.ReadUChar( Ver_Align
);
573 OP_VerAlign123(rContext
, Ver_Align
, rItemSet
);
575 rContext
.aLotusPatternPool
.emplace( nPatternId
, aPattern
);
576 n
-= std::min
<sal_uInt16
>(n
, 20);
581 void OP_SheetName123(LotusContext
& rContext
, SvStream
& rStream
, sal_uInt16 nLength
)
585 rStream
.SeekRel(nLength
);
589 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
590 rStream
.SeekRel(2); // ignore the first 2 bytes (B0 36).
591 sal_uInt16
nSheetNum(0);
592 rStream
.ReadUInt16(nSheetNum
);
594 const size_t nStrLen
= nLength
- 4;
595 std::vector
<char> sSheetName(nStrLen
+ 1);
596 sSheetName
[rStream
.ReadBytes(sSheetName
.data(), nStrLen
)] = 0;
598 if (!ValidTab(nSheetNum
))
600 // coverity[tainted_data : FALSE] - ValidTab has sanitized nSheetNum
601 rContext
.rDoc
.MakeTable(nSheetNum
);
602 if (!sSheetName
.empty())
604 OUString
aName(sSheetName
.data(), strlen(sSheetName
.data()), rContext
.eCharset
);
605 rContext
.rDoc
.RenameTab(nSheetNum
, aName
);
609 void OP_ApplyPatternArea123(LotusContext
& rContext
, SvStream
& rStream
)
611 sal_uInt16 nOpcode
, nLength
;
612 sal_uInt16 nCol
= 0, nColCount
= 0, nRow
= 0, nRowCount
= 0, nTab
= 0, nData
, nTabCount
= 0, nLevel
= 0;
616 rStream
.ReadUInt16( nOpcode
).ReadUInt16( nLength
);
619 case ROW_FORMAT_MARKER
:
622 case COL_FORMAT_MARKER
:
626 nTab
= nTab
+ nTabCount
;
627 nCol
= 0; nColCount
= 0;
628 nRow
= 0; nRowCount
= 0;
631 case LOTUS_FORMAT_INDEX
:
634 rStream
.ReadUInt16( nData
);
635 rStream
.SeekRel( nLength
- 2 );
637 nTabCount
= SanitizeTab(nData
);
638 else if( nLevel
== 2 )
640 nCol
= nCol
+ nColCount
;
642 if ( nCol
> 0xff ) // 256 is the max col size supported by 123
645 else if( nLevel
== 3 )
647 nRow
= nRow
+ nRowCount
;
649 if ( nRow
> 0x1fff ) // 8192 is the max row size supported by 123
654 rStream
.SeekRel( nLength
);
656 case LOTUS_FORMAT_INFO
:
659 rStream
.ReadUInt16( nData
);
660 rStream
.SeekRel( nLength
- 2 );
661 std::map
<sal_uInt16
, ScPatternAttr
>::iterator loc
= rContext
.aLotusPatternPool
.find( nData
);
662 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
663 if ( loc
!= rContext
.aLotusPatternPool
.end() )
664 for( int i
= 0; i
< nTabCount
; i
++)
666 rContext
.rDoc
.ApplyPatternAreaTab( nCol
, nRow
, nCol
+ nColCount
- 1, nRow
+ nRowCount
- 1, static_cast< SCTAB
>( nTab
+ i
), loc
->second
);
670 rStream
.SeekRel( nLength
);
673 rStream
.SeekRel( nLength
);
677 while( nLevel
&& rStream
.good() );
679 rContext
.aLotusPatternPool
.clear();
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */