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 <sal/config.h>
21 #include <sal/log.hxx>
23 #include <qproform.hxx>
25 #include <qprostyle.hxx>
27 #include <scerrors.hxx>
29 #include <document.hxx>
30 #include <formulacell.hxx>
31 #include <tools/stream.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <docoptio.hxx>
37 ErrCode
ScQProReader::readSheet( SCTAB nTab
, ScDocument
& rDoc
, ScQProStyle
*pStyle
)
39 ErrCode eRet
= ERRCODE_NONE
;
40 sal_uInt8 nCol
, nDummy
;
43 bool bEndOfSheet
= false;
45 SAL_INFO("sc", "Read sheet " << nTab
);
47 while( ERRCODE_NONE
== eRet
&& !bEndOfSheet
&& nextRecord() )
51 case 0x000f:{ // Label cell
52 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadUChar( nDummy
);
53 sal_uInt16 nLen
= getLength();
54 if (!mpStream
->good() || nLen
< 7)
55 eRet
= SCERR_IMPORT_FORMAT
;
58 OUString
aLabel(readString(nLen
- 7));
60 pStyle
->SetFormat( &rDoc
, nCol
, nRow
, nTab
, nStyle
);
61 rDoc
.EnsureTable(nTab
);
62 rDoc
.SetTextCell(ScAddress(nCol
,nRow
,nTab
), aLabel
);
67 case 0x00cb: // End of sheet
71 case 0x000c: // Blank cell
72 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
);
73 if (!mpStream
->good())
75 eRet
= SCERR_IMPORT_FORMAT
;
79 pStyle
->SetFormat( &rDoc
, nCol
, nRow
, nTab
, nStyle
);
82 case 0x000d:{ // Integer cell
84 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadInt16( nValue
);
85 if (!mpStream
->good())
87 eRet
= SCERR_IMPORT_FORMAT
;
91 pStyle
->SetFormat( &rDoc
, nCol
, nRow
, nTab
, nStyle
);
92 rDoc
.EnsureTable(nTab
);
93 rDoc
.SetValue(ScAddress(nCol
,nRow
,nTab
), static_cast<double>(nValue
));
97 case 0x000e:{ // Floating point cell
99 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadDouble( nValue
);
100 if (!mpStream
->good())
102 eRet
= SCERR_IMPORT_FORMAT
;
105 nStyle
= nStyle
>> 3;
106 pStyle
->SetFormat( &rDoc
, nCol
, nRow
, nTab
, nStyle
);
107 rDoc
.EnsureTable(nTab
);
108 rDoc
.SetValue(ScAddress(nCol
,nRow
,nTab
), nValue
);
116 sal_uInt16 nState
, nLen
;
117 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadDouble( nValue
).ReadUInt16( nState
).ReadUInt16( nLen
);
118 if (!mpStream
->good())
120 eRet
= SCERR_IMPORT_FORMAT
;
123 ScAddress
aAddr( nCol
, nRow
, nTab
);
124 std::unique_ptr
<ScTokenArray
> pArray
;
126 QProToSc
aConv(*mpStream
, rDoc
.GetSharedStringPool(), aAddr
);
127 if (ConvErr::OK
!= aConv
.Convert( rDoc
, pArray
))
128 eRet
= SCERR_IMPORT_FORMAT
;
131 ScFormulaCell
* pFormula
= new ScFormulaCell(rDoc
, aAddr
, std::move(pArray
));
132 nStyle
= nStyle
>> 3;
133 pFormula
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
134 pStyle
->SetFormat( &rDoc
, nCol
, nRow
, nTab
, nStyle
);
135 rDoc
.EnsureTable(nTab
);
136 rDoc
.SetFormulaCell(ScAddress(nCol
,nRow
,nTab
), pFormula
);
145 ErrCode
ScFormatFilterPluginImpl::ScImportQuattroPro(SvStream
*pStream
, ScDocument
& rDoc
)
147 ScQProReader
aReader(pStream
);
148 ErrCode eRet
= aReader
.import(rDoc
);
152 ScQProReader::ScQProReader(SvStream
* pStream
)
158 , mnMaxTab(utl::ConfigManager::IsFuzzing() ? 128 : MAXTAB
)
162 mpStream
->SetBufferSize( 65535 );
163 mpStream
->SetStreamCharSet( RTL_TEXTENCODING_MS_1252
);
167 ScQProReader::~ScQProReader()
170 mpStream
->SetBufferSize( 0 );
173 ErrCode
ScQProReader::parse(ScDocument
& rDoc
)
175 ErrCode eRet
= ERRCODE_NONE
;
177 sal_uInt16 i
= 1, j
= 1;
182 return SCERR_IMPORT_OPEN
;
184 std::unique_ptr
<ScQProStyle
> pStyleElement( new ScQProStyle
);
186 while( nextRecord() && eRet
== ERRCODE_NONE
)
190 case 0x0000: // Beginning of file
191 mpStream
->ReadUInt16( nVersion
);
194 case 0x00ca: // Beginning of sheet
195 if (nTab
<= mnMaxTab
)
199 OUString aName
= OUStringChar( sal_Unicode('A' + nTab
) );
201 rDoc
.RenameTab( nTab
, aName
);
203 rDoc
.InsertTab( nTab
, aName
);
205 eRet
= readSheet( nTab
, rDoc
, pStyleElement
.get() );
210 case 0x0001: // End of file
214 case 0x00ce:{ // Attribute cell
215 sal_uInt8 nFormat
, nAlign
, nFont
;
217 mpStream
->ReadUChar( nFormat
).ReadUChar( nAlign
).ReadInt16( nColor
).ReadUChar( nFont
);
218 pStyleElement
->setAlign( i
, nAlign
);
219 pStyleElement
->setFont( i
, nFont
);
224 case 0x00cf:{ // Font description
225 sal_uInt16 nPtSize
, nFontAttr
;
227 mpStream
->ReadUInt16( nPtSize
).ReadUInt16( nFontAttr
);
228 pStyleElement
->setFontRecord( j
, nFontAttr
, nPtSize
);
229 sal_uInt16 nLen
= getLength();
231 aLabel
= readString(nLen
- 4);
233 eRet
= SCERR_IMPORT_FORMAT
;
234 pStyleElement
->setFontType( j
, aLabel
);
243 ErrCode
ScQProReader::import( ScDocument
& rDoc
)
245 ErrCode eRet
= parse(rDoc
);
246 rDoc
.CalcAfterLoad();
250 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportQPW(SvStream
&rStream
)
253 ScDocument aDocument
;
254 ScDocOptions aDocOpt
= aDocument
.GetDocOptions();
255 aDocOpt
.SetLookUpColRowNames(false);
256 aDocument
.SetDocOptions(aDocOpt
);
257 aDocument
.MakeTable(0);
258 aDocument
.EnableExecuteLink(false);
259 aDocument
.SetInsertingFromOtherDoc(true);
260 aDocument
.SetImportingXML(true);
261 aDocument
.SetHardRecalcState(ScDocument::HardRecalcState::ETERNAL
);
263 ScQProReader
aReader(&rStream
);
264 ErrCode eRet
= aReader
.parse(aDocument
);
265 return eRet
== ERRCODE_NONE
;
268 bool ScQProReader::recordsLeft()
270 return mpStream
&& mpStream
->good();
273 bool ScQProReader::nextRecord()
281 sal_uInt32 nPos
= mpStream
->Tell();
282 if( nPos
!= mnOffset
+ mnLength
)
283 mpStream
->Seek( mnOffset
+ mnLength
);
286 mpStream
->ReadUInt16( mnId
).ReadUInt16( mnLength
);
288 mnOffset
= mpStream
->Tell();
290 fprintf( stderr
, "Read record 0x%x length 0x%x at offset 0x%x\n",
291 (unsigned)mnId
, (unsigned)mnLength
, (unsigned)mnOffset
);
293 #if 1 // rather verbose
296 int i
, chunk
= std::min(len
, 16);
297 unsigned char data
[16];
298 mpStream
->Read( data
, chunk
);
300 for (i
= 0; i
< chunk
; i
++)
301 fprintf( stderr
, "%.2x ", data
[i
] );
302 fprintf( stderr
, "| " );
303 for (i
= 0; i
< chunk
; i
++)
304 fprintf( stderr
, "%c", data
[i
] < 127 && data
[i
] > 30 ? data
[i
] : '.' );
305 fprintf( stderr
, "\n" );
309 mpStream
->Seek( mnOffset
);
315 OUString
ScQProReader::readString(sal_uInt16 nLength
)
317 return read_uInt8s_ToOUString(*mpStream
, nLength
, mpStream
->GetStreamCharSet());
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */