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 "lotfilter.hxx"
21 #include <lotimpop.hxx>
22 #include <osl/mutex.hxx>
23 #include <sal/log.hxx>
25 #include <document.hxx>
26 #include <formulacell.hxx>
30 #include <lotfntbf.hxx>
31 #include <lotform.hxx>
33 #include <namebuff.hxx>
34 #include <lotattr.hxx>
35 #include <stringutil.hxx>
36 #include <config_fuzzers.h>
38 #include <unotools/configmgr.hxx>
40 LOTUS_ROOT::LOTUS_ROOT( ScDocument
* pDocP
, rtl_TextEncoding eQ
)
45 eFirstType( Lotus123Typ::X
),
46 eActType( Lotus123Typ::X
),
47 pRngNmBffWK3( new RangeNameBufferWK3() ),
52 LOTUS_ROOT::~LOTUS_ROOT()
56 static osl::Mutex aLotImpSemaphore
;
58 ImportLotus::ImportLotus(LotusContext
&rContext
, SvStream
& aStream
, ScDocument
* pDoc
, rtl_TextEncoding eQ
)
61 , aConv(rContext
, *pIn
, pDoc
->GetSharedStringPool(), eQ
, false)
65 // good point to start locking of import lotus
66 aLotImpSemaphore
.acquire();
68 rContext
.pLotusRoot
= new LOTUS_ROOT(pDoc
, eQ
);
71 ImportLotus::~ImportLotus()
73 LotusContext
&rContext
= aConv
.getContext();
74 delete rContext
.pLotusRoot
;
75 rContext
.pLotusRoot
= nullptr;
77 // no need 4 pLotusRoot anymore
78 aLotImpSemaphore
.release();
81 void ImportLotus::Bof()
83 sal_uInt16 nFileCode
, nFileSub
, nSaveCnt
;
84 sal_uInt8 nMajorId
, nMinorId
, nFlags
;
88 LotusContext
&rContext
= aConv
.getContext();
89 Read( rContext
.pLotusRoot
->aActRange
);
96 if( nFileSub
== 0x0004 )
98 if( nFileCode
== 0x1000 )
100 rContext
.pLotusRoot
->eFirstType
= rContext
.pLotusRoot
->eActType
= Lotus123Typ::WK3
;
102 else if( nFileCode
== 0x1002 )
104 rContext
.pLotusRoot
->eFirstType
= rContext
.pLotusRoot
->eActType
= Lotus123Typ::WK4
;
109 bool ImportLotus::BofFm3()
111 sal_uInt16 nFileCode
, nFileSub
;
116 return ( nFileCode
== 0x8007 && ( nFileSub
== 0x0000 || nFileSub
== 0x00001 ) );
119 void ImportLotus::Columnwidth( sal_uInt16 nRecLen
)
121 SAL_WARN_IF( nRecLen
< 4, "sc.filter", "*ImportLotus::Columnwidth(): Record too short!" );
123 sal_uInt8 nLTab
, nWindow2
;
124 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 2;
129 if( !pD
->HasTable( static_cast<SCTAB
> (nLTab
) ) )
130 pD
->MakeTable( static_cast<SCTAB
> (nLTab
) );
136 sal_uInt8 nCol
, nSpaces
;
142 // Attention: ambiguous Correction factor!
143 pD
->SetColWidth( static_cast<SCCOL
> (nCol
), static_cast<SCTAB
> (nLTab
), static_cast<sal_uInt16
>( TWIPS_PER_CHAR
* 1.28 * nSpaces
) );
150 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen
)
152 SAL_WARN_IF( nRecLen
< 4, "sc.filter", "*ImportLotus::Hiddencolumn(): Record too short!" );
154 sal_uInt8 nLTab
, nWindow2
;
155 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 2;
170 pD
->SetColHidden(static_cast<SCCOL
>(nCol
), static_cast<SCCOL
>(nCol
), static_cast<SCTAB
>(nLTab
), true);
176 void ImportLotus::Userrange()
178 sal_uInt16 nRangeType
;
183 sal_Char aBuffer
[ 17 ];
184 pIn
->ReadBytes(aBuffer
, 16);
186 OUString
aName( aBuffer
, strlen(aBuffer
), eQuellChar
);
190 LotusContext
&rContext
= aConv
.getContext();
191 rContext
.pLotusRoot
->pRngNmBffWK3
->Add( aName
, aScRange
);
194 void ImportLotus::Errcell()
200 ScSetStringParam aParam
;
201 aParam
.setTextInput();
202 pD
->EnsureTable(aA
.Tab());
203 pD
->SetString(aA
, "#ERR!", &aParam
);
206 void ImportLotus::Nacell()
212 ScSetStringParam aParam
;
213 aParam
.setTextInput();
214 pD
->EnsureTable(aA
.Tab());
215 pD
->SetString(aA
, "#NA!", &aParam
);
218 void ImportLotus::Labelcell()
228 ScSetStringParam aParam
;
229 aParam
.setTextInput();
230 pD
->EnsureTable(aA
.Tab());
231 pD
->SetString(aA
, aLabel
, &aParam
);
234 void ImportLotus::Numbercell()
242 pD
->EnsureTable(aAddr
.Tab());
243 pD
->SetValue(aAddr
, fVal
);
246 void ImportLotus::Smallnumcell()
254 pD
->EnsureTable(aAddr
.Tab());
255 pD
->SetValue(aAddr
, SnumToDouble(nVal
));
258 void ImportLotus::Formulacell( sal_uInt16 n
)
260 SAL_WARN_IF( !pIn
, "sc.filter", "-ImportLotus::Formulacell(): Null-Stream!" );
267 n
-= std::min
<sal_uInt16
>(n
, 14);
269 std::unique_ptr
<ScTokenArray
> pErg
;
272 aConv
.Reset( aAddr
);
274 aConv
.Convert( pErg
, nRest
);
278 ScFormulaCell
* pCell
= pErg
? new ScFormulaCell(pD
, aAddr
, std::move(pErg
)) : new ScFormulaCell(pD
, aAddr
);
279 pCell
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
280 pD
->EnsureTable(aAddr
.Tab());
281 pD
->SetFormulaCell(aAddr
, pCell
);
284 void ImportLotus::Read( OUString
&r
)
286 ScfTools::AppendCString( *pIn
, r
, eQuellChar
);
289 void ImportLotus::RowPresentation( sal_uInt16 nRecLen
)
291 SAL_WARN_IF( nRecLen
< 5, "sc.filter", "*ImportLotus::RowPresentation(): Record too short!" );
293 sal_uInt8 nLTab
, nFlags
;
294 sal_uInt16 nRow
, nHeight
;
295 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 8;
308 if( nFlags
& 0x02 ) // Fixed / Stretch to fit fonts
310 // Height in Lotus in 1/32 Points
311 nHeight
*= 20; // -> 32 * TWIPS
312 nHeight
/= 32; // -> TWIPS
314 pD
->SetRowFlags( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
), pD
->GetRowFlags( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
) ) | CRFlags::ManualSize
);
316 pD
->SetRowHeight( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
), nHeight
);
323 void ImportLotus::NamedSheet()
325 sal_uInt16
nTmpTab(0);
330 SCTAB
nLTab(SanitizeTab(static_cast<SCTAB
>(nTmpTab
)));
332 //ofz#14167 arbitrary sheet limit to make fuzzing useful
337 if (pD
->HasTable(nLTab
))
338 pD
->RenameTab(nLTab
, aName
);
340 pD
->InsertTab(nLTab
, aName
);
343 void ImportLotus::Font_Face()
350 if( nNum
>= LotusFontBuffer::nSize
)
355 LotusContext
&rContext
= aConv
.getContext();
356 rContext
.pLotusRoot
->maFontBuff
.SetName( nNum
, aName
);
359 void ImportLotus::Font_Type()
361 LotusContext
&rContext
= aConv
.getContext();
362 for( sal_uInt16 nCnt
= 0 ; nCnt
< LotusFontBuffer::nSize
; nCnt
++ )
366 rContext
.pLotusRoot
->maFontBuff
.SetType( nCnt
, nType
);
370 void ImportLotus::Font_Ysize()
372 LotusContext
&rContext
= aConv
.getContext();
373 for( sal_uInt16 nCnt
= 0 ; nCnt
< LotusFontBuffer::nSize
; nCnt
++ )
377 rContext
.pLotusRoot
->maFontBuff
.SetHeight( nCnt
, nSize
);
381 void ImportLotus::Row_( const sal_uInt16 nRecLen
)
383 SAL_WARN_IF( nExtTab
< 0, "sc.filter", "*ImportLotus::Row_(): not possible!" );
385 sal_uInt16 nCntDwn
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 5;
390 bool bCenter
= false;
391 SCCOL nCenterStart
= 0, nCenterEnd
= 0;
393 sal_uInt16
nTmpRow(0);
395 SCROW
nRow(SanitizeRow(static_cast<SCROW
>(nTmpRow
)));
396 sal_uInt16
nHeight(0);
402 SCTAB
nDestTab(static_cast<SCTAB
>(nExtTab
));
405 pD
->SetRowHeight(nRow
, nDestTab
, nHeight
);
407 LotusContext
&rContext
= aConv
.getContext();
413 if( aAttr
.HasStyles() )
414 rContext
.pLotusRoot
->maAttrTable
.SetAttr(
415 nColCnt
, static_cast<SCCOL
> ( nColCnt
+ nRepeats
), nRow
, aAttr
);
417 // Do this here and NOT in class LotAttrTable, as we only add attributes if the other
418 // attributes are set
419 // -> for Center-Attribute default is centered
420 if( aAttr
.IsCentered() )
424 if (pD
->HasData(nColCnt
, nRow
, nDestTab
))
426 // new Center after previous Center
427 pD
->DoMerge(nDestTab
, nCenterStart
, nRow
, nCenterEnd
, nRow
);
428 nCenterStart
= nColCnt
;
435 nCenterStart
= nColCnt
;
437 nCenterEnd
= nColCnt
+ static_cast<SCCOL
>(nRepeats
);
443 // possibly reset old Center
444 pD
->DoMerge(nDestTab
, nCenterStart
, nRow
, nCenterEnd
, nRow
);
449 nColCnt
= nColCnt
+ static_cast<SCCOL
>(nRepeats
);
456 // possibly reset old Center
457 pD
->DoMerge(nDestTab
, nCenterStart
, nRow
, nCenterEnd
, nRow
);
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */