Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / lotus / lotimpop.cxx
blob3b1a6660356111b94ce1153ea867894b2f710432
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
27 #include <global.hxx>
29 #include <root.hxx>
30 #include <lotfntbf.hxx>
31 #include <lotform.hxx>
32 #include <tool.h>
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 )
42 pDoc( pDocP),
43 maRangeNames(),
44 eCharsetQ( eQ),
45 eFirstType( Lotus123Typ::X),
46 eActType( Lotus123Typ::X),
47 pRngNmBffWK3( new RangeNameBufferWK3() ),
48 maAttrTable( this )
52 LOTUS_ROOT::~LOTUS_ROOT()
56 static osl::Mutex aLotImpSemaphore;
58 ImportLotus::ImportLotus(LotusContext &rContext, SvStream& aStream, ScDocument* pDoc, rtl_TextEncoding eQ)
59 : ImportTyp(pDoc, eQ)
60 , pIn(&aStream)
61 , aConv(rContext, *pIn, pDoc->GetSharedStringPool(), eQ, false)
62 , nTab(0)
63 , nExtTab(0)
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;
86 Read( nFileCode );
87 Read( nFileSub );
88 LotusContext &rContext = aConv.getContext();
89 Read( rContext.pLotusRoot->aActRange );
90 Read( nSaveCnt );
91 Read( nMajorId );
92 Read( nMinorId );
93 Skip( 1 );
94 Read( nFlags );
96 if( nFileSub == 0x0004 )
98 if( nFileCode == 0x1000 )
99 {// <= WK3
100 rContext.pLotusRoot->eFirstType = rContext.pLotusRoot->eActType = Lotus123Typ::WK3;
102 else if( nFileCode == 0x1002 )
103 {// WK4
104 rContext.pLotusRoot->eFirstType = rContext.pLotusRoot->eActType = Lotus123Typ::WK4;
109 bool ImportLotus::BofFm3()
111 sal_uInt16 nFileCode, nFileSub;
113 Read( nFileCode );
114 Read( 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;
126 Read( nLTab );
127 Read( nWindow2 );
129 if( !pD->HasTable( static_cast<SCTAB> (nLTab) ) )
130 pD->MakeTable( static_cast<SCTAB> (nLTab) );
132 if( !nWindow2 )
134 Skip( 2 );
136 sal_uInt8 nCol, nSpaces;
138 while( nCnt )
140 Read( nCol );
141 Read( 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 ) );
145 nCnt--;
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;
157 Read( nLTab );
158 Read( nWindow2 );
160 if( !nWindow2 )
162 Skip( 2 );
164 sal_uInt8 nCol;
166 while( nCnt )
168 Read( nCol );
170 pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
171 nCnt--;
176 void ImportLotus::Userrange()
178 sal_uInt16 nRangeType;
179 ScRange aScRange;
181 Read( nRangeType );
183 sal_Char aBuffer[ 17 ];
184 pIn->ReadBytes(aBuffer, 16);
185 aBuffer[ 16 ] = 0;
186 OUString aName( aBuffer, strlen(aBuffer), eQuellChar );
188 Read( aScRange );
190 LotusContext &rContext = aConv.getContext();
191 rContext.pLotusRoot->pRngNmBffWK3->Add( aName, aScRange );
194 void ImportLotus::Errcell()
196 ScAddress aA;
198 Read( aA );
200 ScSetStringParam aParam;
201 aParam.setTextInput();
202 pD->EnsureTable(aA.Tab());
203 pD->SetString(aA, "#ERR!", &aParam);
206 void ImportLotus::Nacell()
208 ScAddress aA;
210 Read( aA );
212 ScSetStringParam aParam;
213 aParam.setTextInput();
214 pD->EnsureTable(aA.Tab());
215 pD->SetString(aA, "#NA!", &aParam);
218 void ImportLotus::Labelcell()
220 ScAddress aA;
221 OUString aLabel;
222 sal_Char cAlign;
224 Read( aA );
225 Read( cAlign );
226 Read( aLabel );
228 ScSetStringParam aParam;
229 aParam.setTextInput();
230 pD->EnsureTable(aA.Tab());
231 pD->SetString(aA, aLabel, &aParam);
234 void ImportLotus::Numbercell()
236 ScAddress aAddr;
237 double fVal;
239 Read( aAddr );
240 Read( fVal );
242 pD->EnsureTable(aAddr.Tab());
243 pD->SetValue(aAddr, fVal);
246 void ImportLotus::Smallnumcell()
248 ScAddress aAddr;
249 sal_Int16 nVal;
251 Read( aAddr );
252 Read( nVal );
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!" );
262 ScAddress aAddr;
264 Read( aAddr );
265 Skip( 10 );
267 n -= std::min<sal_uInt16>(n, 14);
269 std::unique_ptr<ScTokenArray> pErg;
270 sal_Int32 nRest = n;
272 aConv.Reset( aAddr );
273 aConv.SetWK3();
274 aConv.Convert( pErg, nRest );
275 if (!aConv.good())
276 return;
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;
297 Read( nLTab );
298 Skip( 1 );
300 while( nCnt )
302 Read( nRow );
303 Read( nHeight );
304 Skip( 2 );
305 Read( nFlags );
306 Skip( 1 );
308 if( nFlags & 0x02 ) // Fixed / Stretch to fit fonts
309 { // fixed
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 );
319 nCnt--;
323 void ImportLotus::NamedSheet()
325 sal_uInt16 nTmpTab(0);
326 Read(nTmpTab);
327 OUString aName;
328 Read(aName);
330 SCTAB nLTab(SanitizeTab(static_cast<SCTAB>(nTmpTab)));
331 #if ENABLE_FUZZERS
332 //ofz#14167 arbitrary sheet limit to make fuzzing useful
333 if (nLTab > 5)
334 nLTab = 5;
335 #endif
337 if (pD->HasTable(nLTab))
338 pD->RenameTab(nLTab, aName);
339 else
340 pD->InsertTab(nLTab, aName);
343 void ImportLotus::Font_Face()
345 sal_uInt8 nNum;
346 OUString aName;
348 Read( nNum );
350 if( nNum >= LotusFontBuffer::nSize )
351 return; // nonsense
353 Read( aName );
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++ )
364 sal_uInt16 nType;
365 Read( nType );
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++ )
375 sal_uInt16 nSize;
376 Read( nSize );
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;
386 SCCOL nColCnt = 0;
387 sal_uInt8 nRepeats;
388 LotAttrWK3 aAttr;
390 bool bCenter = false;
391 SCCOL nCenterStart = 0, nCenterEnd = 0;
393 sal_uInt16 nTmpRow(0);
394 Read(nTmpRow);
395 SCROW nRow(SanitizeRow(static_cast<SCROW>(nTmpRow)));
396 sal_uInt16 nHeight(0);
397 Read(nHeight);
399 nHeight &= 0x0FFF;
400 nHeight *= 22;
402 SCTAB nDestTab(static_cast<SCTAB>(nExtTab));
404 if( nHeight )
405 pD->SetRowHeight(nRow, nDestTab, nHeight);
407 LotusContext &rContext = aConv.getContext();
408 while( nCntDwn )
410 Read( aAttr );
411 Read( nRepeats );
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() )
422 if( bCenter )
424 if (pD->HasData(nColCnt, nRow, nDestTab))
426 // new Center after previous Center
427 pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
428 nCenterStart = nColCnt;
431 else
433 // fully new Center
434 bCenter = true;
435 nCenterStart = nColCnt;
437 nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
439 else
441 if( bCenter )
443 // possibly reset old Center
444 pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
445 bCenter = false;
449 nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
450 nColCnt++;
452 nCntDwn--;
455 if( bCenter )
456 // possibly reset old Center
457 pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */