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
* pDoc
, 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();
56 OUString
aLabel(readString(nLen
- 7));
58 pStyle
->SetFormat( pDoc
, nCol
, nRow
, nTab
, nStyle
);
59 pDoc
->EnsureTable(nTab
);
60 pDoc
->SetTextCell(ScAddress(nCol
,nRow
,nTab
), aLabel
);
63 eRet
= SCERR_IMPORT_FORMAT
;
67 case 0x00cb: // End of sheet
71 case 0x000c: // Blank cell
72 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
);
74 pStyle
->SetFormat( pDoc
, nCol
, nRow
, nTab
, nStyle
);
77 case 0x000d:{ // Integer cell
79 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadInt16( nValue
);
81 pStyle
->SetFormat( pDoc
, nCol
, nRow
, nTab
, nStyle
);
82 pDoc
->EnsureTable(nTab
);
83 pDoc
->SetValue(ScAddress(nCol
,nRow
,nTab
), static_cast<double>(nValue
));
87 case 0x000e:{ // Floating point cell
89 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadDouble( nValue
);
91 pStyle
->SetFormat( pDoc
, nCol
, nRow
, nTab
, nStyle
);
92 pDoc
->EnsureTable(nTab
);
93 pDoc
->SetValue(ScAddress(nCol
,nRow
,nTab
), nValue
);
101 sal_uInt16 nState
, nLen
;
102 mpStream
->ReadUChar( nCol
).ReadUChar( nDummy
).ReadUInt16( nRow
).ReadUInt16( nStyle
).ReadDouble( nValue
).ReadUInt16( nState
).ReadUInt16( nLen
);
103 if (!mpStream
->good())
105 eRet
= SCERR_IMPORT_FORMAT
;
108 ScAddress
aAddr( nCol
, nRow
, nTab
);
109 std::unique_ptr
<ScTokenArray
> pArray
;
111 QProToSc
aConv(*mpStream
, pDoc
->GetSharedStringPool(), aAddr
);
112 if (ConvErr::OK
!= aConv
.Convert( pArray
))
113 eRet
= SCERR_IMPORT_FORMAT
;
116 ScFormulaCell
* pFormula
= new ScFormulaCell(pDoc
, aAddr
, std::move(pArray
));
117 nStyle
= nStyle
>> 3;
118 pFormula
->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE
);
119 pStyle
->SetFormat( pDoc
, nCol
, nRow
, nTab
, nStyle
);
120 pDoc
->EnsureTable(nTab
);
121 pDoc
->SetFormulaCell(ScAddress(nCol
,nRow
,nTab
), pFormula
);
130 ErrCode
ScFormatFilterPluginImpl::ScImportQuattroPro(SvStream
*pStream
, ScDocument
*pDoc
)
132 ScQProReader
aReader(pStream
);
133 ErrCode eRet
= aReader
.import( pDoc
);
137 ScQProReader::ScQProReader(SvStream
* pStream
)
143 , mnMaxTab(utl::ConfigManager::IsFuzzing() ? 128 : MAXTAB
)
147 mpStream
->SetBufferSize( 65535 );
148 mpStream
->SetStreamCharSet( RTL_TEXTENCODING_MS_1252
);
152 ScQProReader::~ScQProReader()
155 mpStream
->SetBufferSize( 0 );
158 ErrCode
ScQProReader::parse( ScDocument
*pDoc
)
160 ErrCode eRet
= ERRCODE_NONE
;
162 sal_uInt16 i
= 1, j
= 1;
167 return SCERR_IMPORT_OPEN
;
169 std::unique_ptr
<ScQProStyle
> pStyleElement( new ScQProStyle
);
171 while( nextRecord() && eRet
== ERRCODE_NONE
)
175 case 0x0000: // Beginning of file
176 mpStream
->ReadUInt16( nVersion
);
179 case 0x00ca: // Beginning of sheet
180 if (nTab
<= mnMaxTab
)
184 OUString aName
= OUStringChar( sal_Unicode('A' + nTab
) );
186 pDoc
->RenameTab( nTab
, aName
);
188 pDoc
->InsertTab( nTab
, aName
);
190 eRet
= readSheet( nTab
, pDoc
, pStyleElement
.get() );
195 case 0x0001: // End of file
199 case 0x00ce:{ // Attribute cell
200 sal_uInt8 nFormat
, nAlign
, nFont
;
202 mpStream
->ReadUChar( nFormat
).ReadUChar( nAlign
).ReadInt16( nColor
).ReadUChar( nFont
);
203 pStyleElement
->setAlign( i
, nAlign
);
204 pStyleElement
->setFont( i
, nFont
);
209 case 0x00cf:{ // Font description
210 sal_uInt16 nPtSize
, nFontAttr
;
212 mpStream
->ReadUInt16( nPtSize
).ReadUInt16( nFontAttr
);
213 pStyleElement
->setFontRecord( j
, nFontAttr
, nPtSize
);
214 sal_uInt16 nLen
= getLength();
216 aLabel
= readString(nLen
- 4);
218 eRet
= SCERR_IMPORT_FORMAT
;
219 pStyleElement
->setFontType( j
, aLabel
);
228 ErrCode
ScQProReader::import( ScDocument
*pDoc
)
230 ErrCode eRet
= parse(pDoc
);
231 pDoc
->CalcAfterLoad();
235 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportQPW(SvStream
&rStream
)
238 ScDocument aDocument
;
239 ScDocOptions aDocOpt
= aDocument
.GetDocOptions();
240 aDocOpt
.SetLookUpColRowNames(false);
241 aDocument
.SetDocOptions(aDocOpt
);
242 aDocument
.MakeTable(0);
243 aDocument
.EnableExecuteLink(false);
244 aDocument
.SetInsertingFromOtherDoc(true);
245 aDocument
.SetImportingXML(true);
246 aDocument
.SetHardRecalcState(ScDocument::HardRecalcState::ETERNAL
);
248 ScQProReader
aReader(&rStream
);
249 ErrCode eRet
= aReader
.parse(&aDocument
);
250 return eRet
== ERRCODE_NONE
;
253 bool ScQProReader::recordsLeft()
255 return mpStream
&& mpStream
->good();
258 bool ScQProReader::nextRecord()
266 sal_uInt32 nPos
= mpStream
->Tell();
267 if( nPos
!= mnOffset
+ mnLength
)
268 mpStream
->Seek( mnOffset
+ mnLength
);
271 mpStream
->ReadUInt16( mnId
).ReadUInt16( mnLength
);
273 mnOffset
= mpStream
->Tell();
275 fprintf( stderr
, "Read record 0x%x length 0x%x at offset 0x%x\n",
276 (unsigned)mnId
, (unsigned)mnLength
, (unsigned)mnOffset
);
278 #if 1 // rather verbose
281 int i
, chunk
= std::min(len
, 16);
282 unsigned char data
[16];
283 mpStream
->Read( data
, chunk
);
285 for (i
= 0; i
< chunk
; i
++)
286 fprintf( stderr
, "%.2x ", data
[i
] );
287 fprintf( stderr
, "| " );
288 for (i
= 0; i
< chunk
; i
++)
289 fprintf( stderr
, "%c", data
[i
] < 127 && data
[i
] > 30 ? data
[i
] : '.' );
290 fprintf( stderr
, "\n" );
294 mpStream
->Seek( mnOffset
);
300 OUString
ScQProReader::readString(sal_uInt16 nLength
)
302 return read_uInt8s_ToOUString(*mpStream
, nLength
, mpStream
->GetStreamCharSet());
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */