Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / qpro / qpro.cxx
blobb2162cb3f26ff0b77123a59a44ba2fd8e1ed1a41
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 <sal/config.h>
21 #include <sal/log.hxx>
23 #include <qproform.hxx>
24 #include <qpro.hxx>
25 #include <qprostyle.hxx>
27 #include <scerrors.hxx>
28 #include <ftools.hxx>
29 #include <document.hxx>
30 #include <formulacell.hxx>
31 #include <tools/stream.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <docoptio.hxx>
34 #include <scdll.hxx>
35 #include <memory>
37 ErrCode ScQProReader::readSheet( SCTAB nTab, ScDocument* pDoc, ScQProStyle *pStyle )
39 ErrCode eRet = ERRCODE_NONE;
40 sal_uInt8 nCol, nDummy;
41 sal_uInt16 nRow;
42 sal_uInt16 nStyle;
43 bool bEndOfSheet = false;
45 SAL_INFO("sc", "Read sheet " << nTab);
47 while( ERRCODE_NONE == eRet && !bEndOfSheet && nextRecord() )
49 switch( getId() )
51 case 0x000f:{ // Label cell
52 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadUChar( nDummy );
53 sal_uInt16 nLen = getLength();
54 if (nLen >= 7)
56 OUString aLabel(readString(nLen - 7));
57 nStyle = nStyle >> 3;
58 pStyle->SetFormat( pDoc, nCol, nRow, nTab, nStyle );
59 pDoc->EnsureTable(nTab);
60 pDoc->SetTextCell(ScAddress(nCol,nRow,nTab), aLabel);
62 else
63 eRet = SCERR_IMPORT_FORMAT;
65 break;
67 case 0x00cb: // End of sheet
68 bEndOfSheet = true;
69 break;
71 case 0x000c: // Blank cell
72 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle );
73 nStyle = nStyle >> 3;
74 pStyle->SetFormat( pDoc, nCol, nRow, nTab, nStyle );
75 break;
77 case 0x000d:{ // Integer cell
78 sal_Int16 nValue;
79 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadInt16( nValue );
80 nStyle = nStyle >> 3;
81 pStyle->SetFormat( pDoc, nCol, nRow, nTab, nStyle );
82 pDoc->EnsureTable(nTab);
83 pDoc->SetValue(ScAddress(nCol,nRow,nTab), static_cast<double>(nValue));
85 break;
87 case 0x000e:{ // Floating point cell
88 double nValue;
89 mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadDouble( nValue );
90 nStyle = nStyle >> 3;
91 pStyle->SetFormat( pDoc, nCol, nRow, nTab, nStyle );
92 pDoc->EnsureTable(nTab);
93 pDoc->SetValue(ScAddress(nCol,nRow,nTab), nValue);
95 break;
97 case 0x0010:
99 // Formula cell
100 double 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;
106 break;
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;
114 else
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);
124 break;
127 return eRet;
130 ErrCode ScFormatFilterPluginImpl::ScImportQuattroPro(SvStream *pStream, ScDocument *pDoc)
132 ScQProReader aReader(pStream);
133 ErrCode eRet = aReader.import( pDoc );
134 return eRet;
137 ScQProReader::ScQProReader(SvStream* pStream)
138 : mnId(0)
139 , mnLength(0)
140 , mnOffset(0)
141 , mpStream(pStream)
142 , mbEndOfFile(false)
143 , mnMaxTab(utl::ConfigManager::IsFuzzing() ? 128 : MAXTAB)
145 if( mpStream )
147 mpStream->SetBufferSize( 65535 );
148 mpStream->SetStreamCharSet( RTL_TEXTENCODING_MS_1252 );
152 ScQProReader::~ScQProReader()
154 if( mpStream )
155 mpStream->SetBufferSize( 0 );
158 ErrCode ScQProReader::parse( ScDocument *pDoc )
160 ErrCode eRet = ERRCODE_NONE;
161 sal_uInt16 nVersion;
162 sal_uInt16 i = 1, j = 1;
163 SCTAB nTab = 0;
164 SetEof( false );
166 if( !recordsLeft() )
167 return SCERR_IMPORT_OPEN;
169 std::unique_ptr<ScQProStyle> pStyleElement( new ScQProStyle );
171 while( nextRecord() && eRet == ERRCODE_NONE)
173 switch( getId() )
175 case 0x0000: // Beginning of file
176 mpStream->ReadUInt16( nVersion );
177 break;
179 case 0x00ca: // Beginning of sheet
180 if (nTab <= mnMaxTab)
182 if( nTab < 26 )
184 OUString aName = OUStringChar( sal_Unicode('A' + nTab) );
185 if (!nTab)
186 pDoc->RenameTab( nTab, aName );
187 else
188 pDoc->InsertTab( nTab, aName );
190 eRet = readSheet( nTab, pDoc, pStyleElement.get() );
191 nTab++;
193 break;
195 case 0x0001: // End of file
196 SetEof( true );
197 break;
199 case 0x00ce:{ // Attribute cell
200 sal_uInt8 nFormat, nAlign, nFont;
201 sal_Int16 nColor;
202 mpStream->ReadUChar( nFormat ).ReadUChar( nAlign ).ReadInt16( nColor ).ReadUChar( nFont );
203 pStyleElement->setAlign( i, nAlign );
204 pStyleElement->setFont( i, nFont );
205 i++;
207 break;
209 case 0x00cf:{ // Font description
210 sal_uInt16 nPtSize, nFontAttr;
211 OUString aLabel;
212 mpStream->ReadUInt16( nPtSize ).ReadUInt16( nFontAttr );
213 pStyleElement->setFontRecord( j, nFontAttr, nPtSize );
214 sal_uInt16 nLen = getLength();
215 if (nLen >= 4)
216 aLabel = readString(nLen - 4);
217 else
218 eRet = SCERR_IMPORT_FORMAT;
219 pStyleElement->setFontType( j, aLabel );
220 j++;
222 break;
225 return eRet;
228 ErrCode ScQProReader::import( ScDocument *pDoc )
230 ErrCode eRet = parse(pDoc);
231 pDoc->CalcAfterLoad();
232 return eRet;
235 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportQPW(SvStream &rStream)
237 ScDLL::Init();
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()
260 if( !recordsLeft() )
261 return false;
263 if( mbEndOfFile )
264 return false;
266 sal_uInt32 nPos = mpStream->Tell();
267 if( nPos != mnOffset + mnLength )
268 mpStream->Seek( mnOffset + mnLength );
270 mnLength = mnId = 0;
271 mpStream->ReadUInt16( mnId ).ReadUInt16( mnLength );
273 mnOffset = mpStream->Tell();
274 #ifdef DEBUG_SC_QPRO
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
279 int len = mnLength;
280 while (len > 0) {
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" );
292 len -= chunk;
294 mpStream->Seek( mnOffset );
295 #endif
296 #endif
297 return true;
300 OUString ScQProReader::readString(sal_uInt16 nLength)
302 return read_uInt8s_ToOUString(*mpStream, nLength, mpStream->GetStreamCharSet());
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */