Get the style color and number just once
[LibreOffice.git] / sc / source / filter / lotus / lotimpop.cxx
blob593c4068fdb2ad4d2ba5f89cfdd3fb10f6d7073d
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 <lotfntbf.hxx>
30 #include <lotform.hxx>
31 #include <tool.h>
32 #include <namebuff.hxx>
33 #include <lotattr.hxx>
34 #include <stringutil.hxx>
35 #include <config_fuzzers.h>
38 static osl::Mutex aLotImpSemaphore;
40 ImportLotus::ImportLotus(LotusContext &rContext, SvStream& aStream, rtl_TextEncoding eQ)
41 : ImportTyp(rContext.rDoc, eQ)
42 , pIn(&aStream)
43 , aConv(rContext, *pIn, rContext.rDoc.GetSharedStringPool(), eQ, false)
44 , nTab(0)
45 , nExtTab(0)
47 // good point to start locking of import lotus
48 aLotImpSemaphore.acquire();
51 ImportLotus::~ImportLotus()
53 // no need 4 pLotusRoot anymore
54 aLotImpSemaphore.release();
57 void ImportLotus::Bof()
59 sal_uInt16 nFileCode, nFileSub, nSaveCnt;
60 sal_uInt8 nMajorId, nMinorId, nFlags;
62 Read( nFileCode );
63 Read( nFileSub );
64 LotusContext &rContext = aConv.getContext();
65 Read( rContext.aActRange );
66 Read( nSaveCnt );
67 Read( nMajorId );
68 Read( nMinorId );
69 Skip( 1 );
70 Read( nFlags );
72 if (!pIn->good())
73 return;
75 if( nFileSub == 0x0004 )
77 if( nFileCode == 0x1000 )
78 {// <= WK3
79 rContext.eFirstType = rContext.eActType = Lotus123Typ::WK3;
81 else if( nFileCode == 0x1002 )
82 {// WK4
83 rContext.eFirstType = rContext.eActType = Lotus123Typ::WK4;
88 bool ImportLotus::BofFm3()
90 sal_uInt16 nFileCode(0), nFileSub(0);
92 Read( nFileCode );
93 Read( nFileSub );
95 return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) );
98 void ImportLotus::Columnwidth( sal_uInt16 nRecLen )
100 SAL_WARN_IF( nRecLen < 4, "sc.filter", "*ImportLotus::Columnwidth(): Record too short!" );
102 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
104 sal_uInt8 nLTab(0), nWindow2(0);
105 Read( nLTab );
106 Read( nWindow2 );
108 if( !rD.HasTable( static_cast<SCTAB> (nLTab) ) )
109 rD.MakeTable( static_cast<SCTAB> (nLTab) );
111 if( nWindow2 )
112 return;
114 Skip( 2 );
116 while (nCnt && pIn->good())
118 sal_uInt8 nCol(0), nSpaces(0);
119 Read( nCol );
120 Read( nSpaces );
121 // Attention: ambiguous Correction factor!
122 rD.SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), static_cast<sal_uInt16>( TWIPS_PER_CHAR * 1.28 * nSpaces ) );
124 nCnt--;
127 SAL_WARN_IF(!pIn->good(), "sc.filter", "*ImportLotus::Columnwidth(): short read");
130 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen )
132 SAL_WARN_IF( nRecLen < 4, "sc.filter", "*ImportLotus::Hiddencolumn(): Record too short!" );
134 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
136 sal_uInt8 nLTab(0), nWindow2(0);
137 Read( nLTab );
138 Read( nWindow2 );
140 if( nWindow2 )
141 return;
143 Skip( 2 );
145 while (nCnt && pIn->good())
147 sal_uInt8 nCol(0);
148 Read( nCol );
150 rD.SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
151 nCnt--;
154 SAL_WARN_IF(!pIn->good(), "sc.filter", "*ImportLotus::Hiddencolumn(): short read");
157 void ImportLotus::Userrange()
159 sal_uInt16 nRangeType;
160 ScRange aScRange;
162 Read( nRangeType );
164 char aBuffer[ 17 ];
165 aBuffer[pIn->ReadBytes(aBuffer, 16)] = 0;
166 OUString aName(aBuffer, strlen(aBuffer), eQuellChar);
168 Read(aScRange);
170 if (!pIn->good())
172 SAL_WARN("sc.filter", "invalid range");
173 return;
176 LotusContext &rContext = aConv.getContext();
177 rContext.pRngNmBffWK3->Add( rContext.rDoc, aName, aScRange );
180 void ImportLotus::Errcell()
182 ScAddress aA;
184 Read( aA );
186 if (!pIn->good() || !rD.ValidAddress(aA))
188 SAL_WARN("sc.filter", "invalid address");
189 return;
192 ScSetStringParam aParam;
193 aParam.setTextInput();
194 rD.EnsureTable(aA.Tab());
195 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
196 rD.SetString(aA, u"#ERR!"_ustr, &aParam);
199 void ImportLotus::Nacell()
201 ScAddress aA;
203 Read( aA );
205 if (!pIn->good() || !rD.ValidAddress(aA))
207 SAL_WARN("sc.filter", "invalid address");
208 return;
211 ScSetStringParam aParam;
212 aParam.setTextInput();
213 rD.EnsureTable(aA.Tab());
214 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
215 rD.SetString(aA, u"#NA!"_ustr, &aParam);
218 void ImportLotus::Labelcell()
220 ScAddress aA;
221 OUString aLabel;
222 char cAlign;
224 Read( aA );
225 Read( cAlign );
226 Read( aLabel );
228 if (!pIn->good() || !rD.ValidAddress(aA))
230 SAL_WARN("sc.filter", "invalid address");
231 return;
234 ScSetStringParam aParam;
235 aParam.setTextInput();
236 rD.EnsureTable(aA.Tab());
237 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
238 rD.SetString(aA, aLabel, &aParam);
241 void ImportLotus::Numbercell()
243 ScAddress aAddr;
244 double fVal;
246 Read( aAddr );
247 Read( fVal );
249 if (!pIn->good() || !rD.ValidAddress(aAddr))
251 SAL_WARN("sc.filter", "invalid address");
252 return;
255 rD.EnsureTable(aAddr.Tab());
256 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
257 rD.SetValue(aAddr, fVal);
260 void ImportLotus::Smallnumcell()
262 ScAddress aAddr;
263 sal_Int16 nVal;
265 Read( aAddr );
266 Read( nVal );
268 if (!pIn->good() || !rD.ValidAddress(aAddr))
270 SAL_WARN("sc.filter", "invalid address");
271 return;
274 rD.EnsureTable(aAddr.Tab());
275 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
276 rD.SetValue(aAddr, SnumToDouble(nVal));
279 void ImportLotus::Formulacell( sal_uInt16 n )
281 SAL_WARN_IF( !pIn, "sc.filter", "-ImportLotus::Formulacell(): Null-Stream!" );
283 ScAddress aAddr;
285 Read( aAddr );
286 Skip( 10 );
288 n -= std::min<sal_uInt16>(n, 14);
290 std::unique_ptr<ScTokenArray> pErg;
291 sal_Int32 nRest = n;
293 aConv.Reset( aAddr );
294 aConv.SetWK3();
295 aConv.Convert( pErg, nRest );
296 if (!aConv.good())
297 return;
299 if (!pIn->good() || !rD.ValidAddress(aAddr))
301 SAL_WARN("sc.filter", "invalid address");
302 return;
305 ScFormulaCell* pCell = pErg ? new ScFormulaCell(rD, aAddr, std::move(pErg)) : new ScFormulaCell(rD, aAddr);
306 pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
307 rD.EnsureTable(aAddr.Tab());
308 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
309 rD.SetFormulaCell(aAddr, pCell);
312 void ImportLotus::Read( OUString &r )
314 ScfTools::AppendCString( *pIn, r, eQuellChar );
317 void ImportLotus::RowPresentation( sal_uInt16 nRecLen )
319 SAL_WARN_IF( nRecLen < 5, "sc.filter", "*ImportLotus::RowPresentation(): Record too short!" );
321 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 8;
323 sal_uInt8 nLTab(0);
324 Read( nLTab );
325 Skip( 1 );
327 while (nCnt && pIn->good())
329 sal_uInt16 nRow(0);
330 Read( nRow );
331 sal_uInt16 nHeight(0);
332 Read( nHeight );
333 Skip( 2 );
334 sal_uInt8 nFlags(0);
335 Read( nFlags );
336 Skip( 1 );
338 if( nFlags & 0x02 ) // Fixed / Stretch to fit fonts
339 { // fixed
340 // Height in Lotus in 1/32 Points
341 nHeight *= 20; // -> 32 * TWIPS
342 nHeight /= 32; // -> TWIPS
344 rD.SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), rD.GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CRFlags::ManualSize );
346 rD.SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight );
349 nCnt--;
353 void ImportLotus::NamedSheet()
355 sal_uInt16 nTmpTab(0);
356 Read(nTmpTab);
357 OUString aName;
358 Read(aName);
360 SCTAB nLTab(SanitizeTab(static_cast<SCTAB>(nTmpTab)));
361 #if ENABLE_FUZZERS
362 //ofz#14167 arbitrary sheet limit to make fuzzing useful
363 if (nLTab > 5)
364 nLTab = 5;
365 #endif
367 if (rD.HasTable(nLTab))
368 rD.RenameTab(nLTab, aName);
369 else
370 rD.InsertTab(nLTab, aName);
373 void ImportLotus::Font_Face()
375 sal_uInt8 nNum;
376 OUString aName;
378 Read( nNum );
380 if( nNum >= LotusFontBuffer::nSize )
381 return; // nonsense
383 Read( aName );
385 LotusContext &rContext = aConv.getContext();
386 rContext.maFontBuff.SetName( nNum, aName );
389 void ImportLotus::Font_Type()
391 LotusContext &rContext = aConv.getContext();
392 for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
394 sal_uInt16 nType;
395 Read( nType );
396 rContext.maFontBuff.SetType( nCnt, nType );
400 void ImportLotus::Font_Ysize()
402 LotusContext &rContext = aConv.getContext();
403 for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
405 sal_uInt16 nSize;
406 Read( nSize );
407 rContext.maFontBuff.SetHeight( nCnt, nSize );
411 void ImportLotus::Row_( const sal_uInt16 nRecLen )
413 SAL_WARN_IF( nExtTab < 0, "sc.filter", "*ImportLotus::Row_(): not possible!" );
415 sal_uInt16 nCntDwn = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 5;
416 SCCOL nColCnt = 0;
417 sal_uInt8 nRepeats;
418 LotAttrWK3 aAttr;
420 bool bCenter = false;
421 SCCOL nCenterStart = 0, nCenterEnd = 0;
422 LotusContext &rContext = aConv.getContext();
424 sal_uInt16 nTmpRow(0);
425 Read(nTmpRow);
426 SCROW nRow(rContext.rDoc.SanitizeRow(static_cast<SCROW>(nTmpRow)));
427 sal_uInt16 nHeight(0);
428 Read(nHeight);
430 nHeight &= 0x0FFF;
431 nHeight *= 22;
433 SCTAB nDestTab(static_cast<SCTAB>(nExtTab));
435 if( nHeight )
436 rD.SetRowHeight(nRow, nDestTab, nHeight);
438 while( nCntDwn )
440 Read( aAttr );
441 Read( nRepeats );
443 if( aAttr.HasStyles() )
444 rContext.maAttrTable.SetAttr(
445 rContext, nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), nRow, aAttr );
447 // Do this here and NOT in class LotAttrTable, as we only add attributes if the other
448 // attributes are set
449 // -> for Center-Attribute default is centered
450 if( aAttr.IsCentered() )
452 if( bCenter )
454 if (rD.HasData(nColCnt, nRow, nDestTab))
456 // new Center after previous Center
457 rD.DoMerge( nCenterStart, nRow, nCenterEnd, nRow, nDestTab);
458 nCenterStart = nColCnt;
461 else
463 // fully new Center
464 bCenter = true;
465 nCenterStart = nColCnt;
467 nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
469 else
471 if( bCenter )
473 // possibly reset old Center
474 rD.DoMerge( nCenterStart, nRow, nCenterEnd, nRow, nDestTab );
475 bCenter = false;
479 nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
480 nColCnt++;
482 nCntDwn--;
485 if( bCenter )
486 // possibly reset old Center
487 rD.DoMerge( nCenterStart, nRow, nCenterEnd, nRow, nDestTab );
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */