Line data Source code
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 "lotfilter.hxx"
21 : #include "lotimpop.hxx"
22 : #include <osl/mutex.hxx>
23 :
24 : #include "attrib.hxx"
25 : #include "document.hxx"
26 : #include "rangenam.hxx"
27 : #include "formulacell.hxx"
28 : #include "patattr.hxx"
29 : #include "docpool.hxx"
30 : #include "compiler.hxx"
31 : #include "global.hxx"
32 :
33 : #include "root.hxx"
34 : #include "lotfntbf.hxx"
35 : #include "lotform.hxx"
36 : #include "tool.h"
37 : #include "namebuff.hxx"
38 : #include "lotrange.hxx"
39 : #include "lotattr.hxx"
40 : #include "stringutil.hxx"
41 :
42 4 : LOTUS_ROOT::LOTUS_ROOT( ScDocument* pDocP, rtl_TextEncoding eQ )
43 : :
44 : pDoc( pDocP),
45 4 : pRangeNames( new LotusRangeList(this)),
46 4 : pScRangeName( pDocP->GetRangeName()),
47 : eCharsetQ( eQ),
48 : eFirstType( Lotus_X),
49 : eActType( Lotus_X),
50 4 : pRngNmBffWK3( new RangeNameBufferWK3(this)),
51 4 : pFontBuff( new LotusFontBuffer),
52 20 : pAttrTable( new LotAttrTable(this))
53 : {
54 4 : }
55 :
56 4 : LOTUS_ROOT::~LOTUS_ROOT()
57 : {
58 4 : delete pRangeNames;
59 4 : delete pRngNmBffWK3;
60 4 : delete pFontBuff;
61 4 : delete pAttrTable;
62 4 : }
63 :
64 10 : static osl::Mutex aLotImpSemaphore;
65 :
66 4 : ImportLotus::ImportLotus(LotusContext &rContext, SvStream& aStream, ScDocument* pDoc, rtl_TextEncoding eQ)
67 : : ImportTyp(pDoc, eQ)
68 : , pIn(&aStream)
69 4 : , aConv(rContext, *pIn, pDoc->GetSharedStringPool(), eQ, false)
70 : , nTab(0)
71 8 : , nExtTab(0)
72 : {
73 : // good point to start locking of import lotus
74 4 : aLotImpSemaphore.acquire();
75 :
76 4 : rContext.pLotusRoot = new LOTUS_ROOT(pDoc, eQ);
77 4 : }
78 :
79 8 : ImportLotus::~ImportLotus()
80 : {
81 4 : LotusContext &rContext = aConv.getContext();
82 4 : delete rContext.pLotusRoot;
83 4 : rContext.pLotusRoot = NULL;
84 :
85 : // no need 4 pLotusRoot anymore
86 4 : aLotImpSemaphore.release();
87 4 : }
88 :
89 0 : void ImportLotus::Bof()
90 : {
91 : sal_uInt16 nFileCode, nFileSub, nSaveCnt;
92 : sal_uInt8 nMajorId, nMinorId, nFlags;
93 :
94 0 : Read( nFileCode );
95 0 : Read( nFileSub );
96 0 : LotusContext &rContext = aConv.getContext();
97 0 : Read( rContext.pLotusRoot->aActRange );
98 0 : Read( nSaveCnt );
99 0 : Read( nMajorId );
100 0 : Read( nMinorId );
101 0 : Skip( 1 );
102 0 : Read( nFlags );
103 :
104 0 : if( nFileSub == 0x0004 )
105 : {
106 0 : if( nFileCode == 0x1000 )
107 : {// <= WK3
108 0 : rContext.pLotusRoot->eFirstType = rContext.pLotusRoot->eActType = Lotus_WK3;
109 : }
110 0 : else if( nFileCode == 0x1002 )
111 : {// WK4
112 0 : rContext.pLotusRoot->eFirstType = rContext.pLotusRoot->eActType = Lotus_WK4;
113 : }
114 : }
115 0 : }
116 :
117 0 : bool ImportLotus::BofFm3()
118 : {
119 : sal_uInt16 nFileCode, nFileSub;
120 :
121 0 : Read( nFileCode );
122 0 : Read( nFileSub );
123 :
124 0 : return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) );
125 : }
126 :
127 0 : void ImportLotus::Columnwidth( sal_uInt16 nRecLen )
128 : {
129 : OSL_ENSURE( nRecLen >= 4, "*ImportLotus::Columnwidth(): Record zu kurz!" );
130 :
131 : sal_uInt8 nLTab, nWindow2;
132 0 : sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
133 :
134 0 : Read( nLTab );
135 0 : Read( nWindow2 );
136 :
137 0 : if( !pD->HasTable( static_cast<SCTAB> (nLTab) ) )
138 0 : pD->MakeTable( static_cast<SCTAB> (nLTab) );
139 :
140 0 : if( !nWindow2 )
141 : {
142 0 : Skip( 2 );
143 :
144 : sal_uInt8 nCol, nSpaces;
145 :
146 0 : while( nCnt )
147 : {
148 0 : Read( nCol );
149 0 : Read( nSpaces );
150 : // Attention: ambiguous Correction factor!
151 0 : pD->SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), ( sal_uInt16 ) ( TWIPS_PER_CHAR * 1.28 * nSpaces ) );
152 :
153 0 : nCnt--;
154 : }
155 : }
156 0 : }
157 :
158 0 : void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen )
159 : {
160 : OSL_ENSURE( nRecLen >= 4, "*ImportLotus::Hiddencolumn(): Record too short!" );
161 :
162 : sal_uInt8 nLTab, nWindow2;
163 0 : sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
164 :
165 0 : Read( nLTab );
166 0 : Read( nWindow2 );
167 :
168 0 : if( !nWindow2 )
169 : {
170 0 : Skip( 2 );
171 :
172 : sal_uInt8 nCol;
173 :
174 0 : while( nCnt )
175 : {
176 0 : Read( nCol );
177 :
178 0 : pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
179 0 : nCnt--;
180 : }
181 : }
182 0 : }
183 :
184 0 : void ImportLotus::Userrange()
185 : {
186 : sal_uInt16 nRangeType;
187 0 : ScRange aScRange;
188 :
189 0 : Read( nRangeType );
190 :
191 : sal_Char aBuffer[ 17 ];
192 0 : pIn->Read( aBuffer, 16 );
193 0 : aBuffer[ 16 ] = 0;
194 0 : OUString aName( aBuffer, strlen(aBuffer), eQuellChar );
195 :
196 0 : Read( aScRange );
197 :
198 0 : LotusContext &rContext = aConv.getContext();
199 0 : rContext.pLotusRoot->pRngNmBffWK3->Add( aName, aScRange );
200 0 : }
201 :
202 0 : void ImportLotus::Errcell()
203 : {
204 0 : ScAddress aA;
205 :
206 0 : Read( aA );
207 :
208 0 : ScSetStringParam aParam;
209 0 : aParam.setTextInput();
210 0 : pD->EnsureTable(aA.Tab());
211 0 : pD->SetString(aA, "#ERR!", &aParam);
212 0 : }
213 :
214 0 : void ImportLotus::Nacell()
215 : {
216 0 : ScAddress aA;
217 :
218 0 : Read( aA );
219 :
220 0 : ScSetStringParam aParam;
221 0 : aParam.setTextInput();
222 0 : pD->EnsureTable(aA.Tab());
223 0 : pD->SetString(aA, "#NA!", &aParam);
224 0 : }
225 :
226 0 : void ImportLotus::Labelcell()
227 : {
228 0 : ScAddress aA;
229 0 : OUString aLabel;
230 : sal_Char cAlign;
231 :
232 0 : Read( aA );
233 0 : Read( cAlign );
234 0 : Read( aLabel );
235 :
236 0 : ScSetStringParam aParam;
237 0 : aParam.setTextInput();
238 0 : pD->EnsureTable(aA.Tab());
239 0 : pD->SetString(aA, aLabel, &aParam);
240 0 : }
241 :
242 0 : void ImportLotus::Numbercell()
243 : {
244 0 : ScAddress aAddr;
245 : double fVal;
246 :
247 0 : Read( aAddr );
248 0 : Read( fVal );
249 :
250 0 : pD->EnsureTable(aAddr.Tab());
251 0 : pD->SetValue(aAddr, fVal);
252 0 : }
253 :
254 0 : void ImportLotus::Smallnumcell()
255 : {
256 0 : ScAddress aAddr;
257 : sal_Int16 nVal;
258 :
259 0 : Read( aAddr );
260 0 : Read( nVal );
261 :
262 0 : pD->EnsureTable(aAddr.Tab());
263 0 : pD->SetValue(aAddr, SnumToDouble(nVal));
264 0 : }
265 :
266 0 : ScFormulaCell *ImportLotus::Formulacell( sal_uInt16 n )
267 : {
268 : OSL_ENSURE( pIn, "-ImportLotus::Formulacell(): Null-Stream!" );
269 :
270 0 : ScAddress aAddr;
271 :
272 0 : Read( aAddr );
273 0 : Skip( 10 );
274 :
275 0 : n -= (n > 14) ? 14 : n;
276 :
277 : const ScTokenArray* pErg;
278 0 : sal_Int32 nRest = n;
279 :
280 0 : aConv.Reset( aAddr );
281 0 : aConv.SetWK3();
282 0 : aConv.Convert( pErg, nRest );
283 :
284 0 : ScFormulaCell* pCell = pErg ? new ScFormulaCell(pD, aAddr, *pErg) : new ScFormulaCell(pD, aAddr);
285 0 : pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
286 0 : pD->EnsureTable(aAddr.Tab());
287 0 : pD->SetFormulaCell(aAddr, pCell);
288 :
289 0 : return NULL;
290 : }
291 :
292 0 : void ImportLotus::Read( OUString &r )
293 : {
294 0 : ScfTools::AppendCString( *pIn, r, eQuellChar );
295 0 : }
296 :
297 0 : void ImportLotus::RowPresentation( sal_uInt16 nRecLen )
298 : {
299 : OSL_ENSURE( nRecLen > 4, "*ImportLotus::RowPresentation(): Record too short!" );
300 :
301 : sal_uInt8 nLTab, nFlags;
302 : sal_uInt16 nRow, nHeight;
303 0 : sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 8;
304 :
305 0 : Read( nLTab );
306 0 : Skip( 1 );
307 :
308 0 : while( nCnt )
309 : {
310 0 : Read( nRow );
311 0 : Read( nHeight );
312 0 : Skip( 2 );
313 0 : Read( nFlags );
314 0 : Skip( 1 );
315 :
316 0 : if( nFlags & 0x02 ) // Fixed / Stretch to fit fonts
317 : { // fixed
318 : // Height in Lotus in 1/32 Points
319 0 : nHeight *= 20; // -> 32 * TWIPS
320 0 : nHeight /= 32; // -> TWIPS
321 :
322 0 : pD->SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), pD->GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CR_MANUALSIZE );
323 :
324 0 : pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight );
325 : }
326 :
327 0 : nCnt--;
328 : }
329 0 : }
330 :
331 0 : void ImportLotus::NamedSheet()
332 : {
333 0 : sal_uInt16 nTmpTab(0);
334 0 : Read(nTmpTab);
335 0 : OUString aName;
336 0 : Read(aName);
337 :
338 0 : SCTAB nLTab(SanitizeTab(static_cast<SCTAB>(nTmpTab)));
339 :
340 0 : if (pD->HasTable(nLTab))
341 0 : pD->RenameTab(nLTab, aName);
342 : else
343 0 : pD->InsertTab(nLTab, aName);
344 0 : }
345 :
346 0 : void ImportLotus::Font_Face()
347 : {
348 : sal_uInt8 nNum;
349 0 : OUString aName;
350 :
351 0 : Read( nNum );
352 :
353 0 : if( nNum >= LotusFontBuffer::nSize )
354 0 : return; // nonsense
355 :
356 0 : Read( aName );
357 :
358 0 : LotusContext &rContext = aConv.getContext();
359 0 : rContext.pLotusRoot->pFontBuff->SetName( nNum, aName );
360 : }
361 :
362 0 : void ImportLotus::Font_Type()
363 : {
364 0 : LotusContext &rContext = aConv.getContext();
365 0 : for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
366 : {
367 : sal_uInt16 nType;
368 0 : Read( nType );
369 0 : rContext.pLotusRoot->pFontBuff->SetType( nCnt, nType );
370 : }
371 0 : }
372 :
373 0 : void ImportLotus::Font_Ysize()
374 : {
375 0 : LotusContext &rContext = aConv.getContext();
376 0 : for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
377 : {
378 : sal_uInt16 nSize;
379 0 : Read( nSize );
380 0 : rContext.pLotusRoot->pFontBuff->SetHeight( nCnt, nSize );
381 : }
382 0 : }
383 :
384 0 : void ImportLotus::_Row( const sal_uInt16 nRecLen )
385 : {
386 : OSL_ENSURE( nExtTab >= 0, "*ImportLotus::_Row(): not possible!" );
387 :
388 0 : sal_uInt16 nCntDwn = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 5;
389 0 : SCCOL nColCnt = 0;
390 : sal_uInt8 nRepeats;
391 : LotAttrWK3 aAttr;
392 :
393 0 : bool bCenter = false;
394 0 : SCCOL nCenterStart = 0, nCenterEnd = 0;
395 :
396 0 : sal_uInt16 nTmpRow(0);
397 0 : Read(nTmpRow);
398 0 : SCROW nRow(SanitizeRow(static_cast<SCROW>(nTmpRow)));
399 0 : sal_uInt16 nHeight(0);
400 0 : Read(nHeight);
401 :
402 0 : nHeight &= 0x0FFF;
403 0 : nHeight *= 22;
404 :
405 0 : SCTAB nDestTab(static_cast<SCTAB>(nExtTab));
406 :
407 0 : if( nHeight )
408 0 : pD->SetRowHeight(nRow, nDestTab, nHeight);
409 :
410 0 : LotusContext &rContext = aConv.getContext();
411 0 : while( nCntDwn )
412 : {
413 0 : Read( aAttr );
414 0 : Read( nRepeats );
415 :
416 0 : if( aAttr.HasStyles() )
417 : rContext.pLotusRoot->pAttrTable->SetAttr(
418 0 : nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), nRow, aAttr );
419 :
420 : // Do this here and NOT in class LotAttrTable, as we only add attributes if the other
421 : // attributes are set
422 : // -> for Center-Attribute default is centered
423 0 : if( aAttr.IsCentered() )
424 : {
425 0 : if( bCenter )
426 : {
427 0 : if (pD->HasData(nColCnt, nRow, nDestTab))
428 : {
429 : // new Center after previous Center
430 0 : pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
431 0 : nCenterStart = nColCnt;
432 : }
433 : }
434 : else
435 : {
436 : // fully new Center
437 0 : bCenter = true;
438 0 : nCenterStart = nColCnt;
439 : }
440 0 : nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
441 : }
442 : else
443 : {
444 0 : if( bCenter )
445 : {
446 : // possibly reset old Center
447 0 : pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
448 0 : bCenter = false;
449 : }
450 : }
451 :
452 0 : nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
453 0 : nColCnt++;
454 :
455 0 : nCntDwn--;
456 : }
457 :
458 0 : if( bCenter )
459 : // possibly reset old Center
460 0 : pD->DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
461 30 : }
462 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|