LibreOffice Module sc (master) 1
qpro.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <qproform.hxx>
24#include <qpro.hxx>
25#include <qprostyle.hxx>
26
27#include <scerrors.hxx>
28#include <ftools.hxx>
29#include <document.hxx>
30#include <formulacell.hxx>
31#include <tools/stream.hxx>
33#include <docoptio.hxx>
34#include <scdll.hxx>
35#include <memory>
36
38{
39 ErrCode eRet = ERRCODE_NONE;
40 sal_uInt8 nCol, nDummy;
41 sal_uInt16 nRow;
42 sal_uInt16 nStyle;
43 bool bEndOfSheet = false;
44
45 SAL_INFO("sc", "Read sheet " << nTab);
46
47 while( ERRCODE_NONE == eRet && !bEndOfSheet && nextRecord() )
48 {
49 switch( getId() )
50 {
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)
56 else
57 {
58 OUString aLabel(readString(nLen - 7));
59 nStyle = nStyle >> 3;
60 pStyle->SetFormat( &rDoc, nCol, nRow, nTab, nStyle );
61 rDoc.EnsureTable(nTab);
62 rDoc.SetTextCell(ScAddress(nCol,nRow,nTab), aLabel);
63 }
64 }
65 break;
66
67 case 0x00cb: // End of sheet
68 bEndOfSheet = true;
69 break;
70
71 case 0x000c: // Blank cell
72 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle );
73 if (!mpStream->good())
74 {
76 break;
77 }
78 nStyle = nStyle >> 3;
79 pStyle->SetFormat( &rDoc, nCol, nRow, nTab, nStyle );
80 break;
81
82 case 0x000d:{ // Integer cell
83 sal_Int16 nValue;
84 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadInt16( nValue );
85 if (!mpStream->good())
86 {
88 break;
89 }
90 nStyle = nStyle >> 3;
91 pStyle->SetFormat( &rDoc, nCol, nRow, nTab, nStyle );
92 rDoc.EnsureTable(nTab);
93 rDoc.SetValue(ScAddress(nCol,nRow,nTab), static_cast<double>(nValue));
94 }
95 break;
96
97 case 0x000e:{ // Floating point cell
98 double nValue;
99 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadDouble( nValue );
100 if (!mpStream->good())
101 {
102 eRet = SCERR_IMPORT_FORMAT;
103 break;
104 }
105 nStyle = nStyle >> 3;
106 pStyle->SetFormat( &rDoc, nCol, nRow, nTab, nStyle );
107 rDoc.EnsureTable(nTab);
108 rDoc.SetValue(ScAddress(nCol,nRow,nTab), nValue);
109 }
110 break;
111
112 case 0x0010:
113 {
114 // Formula cell
115 double 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())
119 {
120 eRet = SCERR_IMPORT_FORMAT;
121 break;
122 }
123 ScAddress aAddr( nCol, nRow, nTab );
124 std::unique_ptr<ScTokenArray> pArray;
125
126 QProToSc aConv(*mpStream, rDoc.GetSharedStringPool(), aAddr);
127 if (ConvErr::OK != aConv.Convert( rDoc, pArray ))
128 eRet = SCERR_IMPORT_FORMAT;
129 else
130 {
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);
137 }
138 }
139 break;
140 }
141 }
142 return eRet;
143}
144
146{
147 ScQProReader aReader(pStream);
148 ErrCode eRet = aReader.import(rDoc);
149 return eRet;
150}
151
153 : mnId(0)
154 , mnLength(0)
155 , mnOffset(0)
156 , mpStream(pStream)
157 , mbEndOfFile(false)
158 , mnMaxTab(utl::ConfigManager::IsFuzzing() ? 128 : MAXTAB)
159{
160 if( mpStream )
161 {
162 mpStream->SetBufferSize( 65535 );
163 mpStream->SetStreamCharSet( RTL_TEXTENCODING_MS_1252 );
164 }
165}
166
168{
169 if( mpStream )
171}
172
174{
175 ErrCode eRet = ERRCODE_NONE;
176 sal_uInt16 nVersion;
177 sal_uInt16 i = 1, j = 1;
178 SCTAB nTab = 0;
179 SetEof( false );
180
181 if( !recordsLeft() )
182 return SCERR_IMPORT_OPEN;
183
184 std::unique_ptr<ScQProStyle> pStyleElement( new ScQProStyle );
185
186 while( nextRecord() && eRet == ERRCODE_NONE)
187 {
188 switch( getId() )
189 {
190 case 0x0000: // Beginning of file
192 break;
193
194 case 0x00ca: // Beginning of sheet
195 if (nTab <= mnMaxTab)
196 {
197 if( nTab < 26 )
198 {
199 OUString aName = OUStringChar( sal_Unicode('A' + nTab) );
200 if (!nTab)
201 rDoc.RenameTab( nTab, aName );
202 else
203 rDoc.InsertTab( nTab, aName );
204 }
205 eRet = readSheet( nTab, rDoc, pStyleElement.get() );
206 nTab++;
207 }
208 break;
209
210 case 0x0001: // End of file
211 SetEof( true );
212 break;
213
214 case 0x00ce:{ // Attribute cell
215 sal_uInt8 nFormat, nAlign, nFont;
216 sal_Int16 nColor;
217 mpStream->ReadUChar( nFormat ).ReadUChar( nAlign ).ReadInt16( nColor ).ReadUChar( nFont );
218 pStyleElement->setAlign( i, nAlign );
219 pStyleElement->setFont( i, nFont );
220 i++;
221 }
222 break;
223
224 case 0x00cf:{ // Font description
225 sal_uInt16 nPtSize, nFontAttr;
226 OUString aLabel;
227 mpStream->ReadUInt16( nPtSize ).ReadUInt16( nFontAttr );
228 pStyleElement->setFontRecord( j, nFontAttr, nPtSize );
229 sal_uInt16 nLen = getLength();
230 if (nLen >= 4)
231 aLabel = readString(nLen - 4);
232 else
233 eRet = SCERR_IMPORT_FORMAT;
234 pStyleElement->setFontType( j, aLabel );
235 j++;
236 }
237 break;
238 }
239 }
240 return eRet;
241}
242
244{
245 ErrCode eRet = parse(rDoc);
246 rDoc.CalcAfterLoad();
247 return eRet;
248}
249
250extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportQPW(SvStream &rStream)
251{
252 ScDLL::Init();
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);
262
263 ScQProReader aReader(&rStream);
264 ErrCode eRet = aReader.parse(aDocument);
265 return eRet == ERRCODE_NONE;
266}
267
269{
270 return mpStream && mpStream->good();
271}
272
274{
275 if( !recordsLeft() )
276 return false;
277
278 if( mbEndOfFile )
279 return false;
280
281 sal_uInt32 nPos = mpStream->Tell();
282 if( nPos != mnOffset + mnLength )
284
285 mnLength = mnId = 0;
287
289#ifdef DEBUG_SC_QPRO
290 fprintf( stderr, "Read record 0x%x length 0x%x at offset 0x%x\n",
291 (unsigned)mnId, (unsigned)mnLength, (unsigned)mnOffset );
292
293#if 1 // rather verbose
294 int len = mnLength;
295 while (len > 0) {
296 int i, chunk = std::min(len, 16);
297 unsigned char data[16];
298 mpStream->Read( data, chunk );
299
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" );
306
307 len -= chunk;
308 }
310#endif
311#endif
312 return true;
313}
314
315OUString ScQProReader::readString(sal_uInt16 nLength)
316{
318}
319
320/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SCTAB MAXTAB
Definition: address.hxx:70
ScriptDocument aDocument
ConvErr Convert(const ScDocument &rDoc, std::unique_ptr< ScTokenArray > &pArray)
Definition: qproform.cxx:190
static SC_DLLPUBLIC void Init()
DLL-init/exit-code must be linked to the DLL only.
Definition: scdll.cxx:100
void SetLookUpColRowNames(bool bVal)
Definition: docoptio.hxx:52
SC_DLLPUBLIC bool InsertTab(SCTAB nPos, const OUString &rName, bool bExternalDocument=false, bool bUndoDeleteTab=false)
Definition: document.cxx:485
SC_DLLPUBLIC ScFormulaCell * SetFormulaCell(const ScAddress &rPos, ScFormulaCell *pCell)
Set formula cell, and transfer its ownership to the document.
Definition: documen2.cxx:1149
SC_DLLPUBLIC bool RenameTab(SCTAB nTab, const OUString &rName, bool bExternalDocument=false)
Definition: document.cxx:837
SC_DLLPUBLIC void SetTextCell(const ScAddress &rPos, const OUString &rStr)
Call this if you are not sure whether to put this as an edit text or a simple text.
Definition: document.cxx:3452
SC_DLLPUBLIC void EnsureTable(SCTAB nTab)
Definition: documen2.cxx:577
SC_DLLPUBLIC void CalcAfterLoad(bool bStartListening=true)
Definition: document.cxx:4029
@ ETERNAL
CalcAll() without broadcast/notify but setting up new listeners.
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3477
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:601
virtual ErrCode ScImportQuattroPro(SvStream *pStream, ScDocument &rDoc) override
Definition: qpro.cxx:145
void AddRecalcMode(ScRecalcMode)
~ScQProReader()
Definition: qpro.cxx:167
bool mbEndOfFile
Definition: qpro.hxx:38
ErrCode import(ScDocument &rDoc)
Definition: qpro.cxx:243
bool recordsLeft()
Definition: qpro.cxx:268
void SetEof(bool bValue)
Definition: qpro.hxx:46
sal_uInt32 mnOffset
Definition: qpro.hxx:36
SvStream * mpStream
Definition: qpro.hxx:37
sal_uInt16 getLength() const
Definition: qpro.hxx:49
OUString readString(sal_uInt16 nLength)
Definition: qpro.cxx:315
bool nextRecord()
Definition: qpro.cxx:273
ErrCode parse(ScDocument &rDoc)
Definition: qpro.cxx:173
const SCTAB mnMaxTab
Definition: qpro.hxx:39
ScQProReader(SvStream *pStream)
Definition: qpro.cxx:152
sal_uInt16 mnId
Definition: qpro.hxx:34
sal_uInt16 getId() const
Definition: qpro.hxx:48
ErrCode readSheet(SCTAB nTab, ScDocument &rDoc, ScQProStyle *pStyle)
Definition: qpro.cxx:37
sal_uInt16 mnLength
Definition: qpro.hxx:35
void SetFormat(ScDocument *pDoc, sal_uInt8 nCol, sal_uInt16 nRow, SCTAB nTab, sal_uInt16 nStyle)
Definition: qprostyle.cxx:38
sal_uInt64 Tell() const
bool good() const
SvStream & ReadDouble(double &rDouble)
SvStream & ReadInt16(sal_Int16 &rInt16)
void SetBufferSize(sal_uInt16 m_nBufSize)
sal_uInt64 Seek(sal_uInt64 nPos)
void SetStreamCharSet(rtl_TextEncoding eCharSet)
rtl_TextEncoding GetStreamCharSet() const
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
SvStream & ReadUChar(unsigned char &rChar)
sal_uInt16 mnId
sal_Int32 nState
#define ERRCODE_NONE
sal_Int16 nVersion
sal_Int16 nValue
OUString aName
sal_uInt16 nPos
#define SAL_INFO(area, stream)
int i
SAL_DLLPUBLIC_EXPORT bool TestImportQPW(SvStream &rStream)
Definition: qpro.cxx:250
#define SCERR_IMPORT_FORMAT
Definition: scerrors.hxx:33
#define SCERR_IMPORT_OPEN
Definition: scerrors.hxx:26
OUString read_uInt8s_ToOUString(SvStream &rStrm, std::size_t nUnits, rtl_TextEncoding eEnc)
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
sal_Int16 SCTAB
Definition: types.hxx:22
OUString aLabel
sal_Int32 nLength