1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 #include "lotimpop.hxx"
27 #include <vos/mutex.hxx>
28
29 #include "attrib.hxx"
30 #include "document.hxx"
31 #include "rangenam.hxx"
32 #include "cell.hxx"
33 #include "patattr.hxx"
34 #include "docpool.hxx"
35 #include "compiler.hxx"
36 #include "global.hxx"
37
38 #include "root.hxx"
39 #include "lotfntbf.hxx"
40 #include "lotform.hxx"
41 #include "tool.h"
42 #include "namebuff.hxx"
43 #include "lotrange.hxx"
44 #include "lotattr.hxx"
45
46
47 static vos:: OMutex aLotImpSemaphore;
48
LOTUS_ROOT(ScDocument * pDocP,CharSet eQ)49 LOTUS_ROOT::LOTUS_ROOT( ScDocument* pDocP, CharSet eQ )
50 :
51 pDoc( pDocP),
52 pRangeNames( new LotusRangeList),
53 pScRangeName( pDocP->GetRangeName()),
54 eCharsetQ( eQ),
55 eFirstType( Lotus_X),
56 eActType( Lotus_X),
57 pRngNmBffWK3( new RangeNameBufferWK3),
58 pFontBuff( new LotusFontBuffer)
59 {
60 pLotusRoot = this; // #122841# the singleton global var is already needed for LotAttrTable
61 pAttrTable = new LotAttrTable;
62 }
63
64
~LOTUS_ROOT()65 LOTUS_ROOT::~LOTUS_ROOT()
66 {
67 delete pRangeNames;
68 delete pRngNmBffWK3;
69 delete pFontBuff;
70 delete pAttrTable;
71 }
72
73
ImportLotus(SvStream & aStream,ScDocument * pDoc,CharSet eQ)74 ImportLotus::ImportLotus( SvStream& aStream, ScDocument* pDoc, CharSet eQ ) :
75 ImportTyp( pDoc, eQ ),
76 pIn( &aStream ),
77 aConv( *pIn, eQ, sal_False )
78 {
79 // good point to start locking of import lotus
80 aLotImpSemaphore.acquire();
81
82 pLotusRoot = new LOTUS_ROOT( pDoc, eQ);
83 }
84
85
~ImportLotus()86 ImportLotus::~ImportLotus()
87 {
88 delete pLotusRoot;
89 pLotusRoot = NULL;
90
91 // no need 4 pLotusRoot anymore
92 aLotImpSemaphore.release();
93 }
94
95
Bof(void)96 void ImportLotus::Bof( void )
97 {
98 sal_uInt16 nFileCode, nFileSub, nSaveCnt;
99 sal_uInt8 nMajorId, nMinorId, nFlags;
100
101 Read( nFileCode );
102 Read( nFileSub );
103 Read( pLotusRoot->aActRange );
104 Read( nSaveCnt );
105 Read( nMajorId );
106 Read( nMinorId );
107 Skip( 1 );
108 Read( nFlags );
109
110 if( nFileSub == 0x0004 )
111 {
112 if( nFileCode == 0x1000 )
113 {// <= WK3
114 pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK3;
115 }
116 else if( nFileCode == 0x1002 )
117 {// WK4
118 pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK4;
119 }
120 }
121 }
122
123
BofFm3(void)124 sal_Bool ImportLotus::BofFm3( void )
125 {
126 sal_uInt16 nFileCode, nFileSub;
127
128 Read( nFileCode );
129 Read( nFileSub );
130
131 return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) );
132 }
133
134
Columnwidth(sal_uInt16 nRecLen)135 void ImportLotus::Columnwidth( sal_uInt16 nRecLen )
136 {
137 DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Columnwidth(): Record zu kurz!" );
138
139 sal_uInt8 nLTab, nWindow2;
140 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
141
142 Read( nLTab );
143 Read( nWindow2 );
144
145 if( !pD->HasTable( static_cast<SCTAB> (nLTab) ) )
146 pD->MakeTable( static_cast<SCTAB> (nLTab) );
147
148 if( !nWindow2 )
149 {
150 Skip( 2 );
151
152 sal_uInt8 nCol, nSpaces;
153
154 while( nCnt )
155 {
156 Read( nCol );
157 Read( nSpaces );
158 // ACHTUNG: Korrekturfaktor nach 'Augenmass' ermittelt!
159 pD->SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), ( sal_uInt16 ) ( TWIPS_PER_CHAR * 1.28 * nSpaces ) );
160
161 nCnt--;
162 }
163 }
164 }
165
166
Hiddencolumn(sal_uInt16 nRecLen)167 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen )
168 {
169 DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Hiddencolumn(): Record zu kurz!" );
170
171 sal_uInt8 nLTab, nWindow2;
172 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
173
174 Read( nLTab );
175 Read( nWindow2 );
176
177 if( !nWindow2 )
178 {
179 Skip( 2 );
180
181 sal_uInt8 nCol;
182
183 while( nCnt )
184 {
185 Read( nCol );
186
187 pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
188 nCnt--;
189 }
190 }
191 }
192
193
Userrange(void)194 void ImportLotus::Userrange( void )
195 {
196 sal_uInt16 nRangeType;
197 ScRange aScRange;
198
199 Read( nRangeType );
200
201 sal_Char aBuffer[ 17 ];
202 pIn->Read( aBuffer, 16 );
203 aBuffer[ 16 ] = 0;
204 String aName( aBuffer, eQuellChar );
205
206 Read( aScRange );
207
208 pLotusRoot->pRngNmBffWK3->Add( aName, aScRange );
209 }
210
211
Errcell(void)212 void ImportLotus::Errcell( void )
213 {
214 ScAddress aA;
215
216 Read( aA );
217
218 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#ERR!" ) ), (sal_Bool)sal_True );
219 }
220
221
Nacell(void)222 void ImportLotus::Nacell( void )
223 {
224 ScAddress aA;
225
226 Read( aA );
227
228 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#NA!" ) ), (sal_Bool)sal_True );
229 }
230
231
Labelcell(void)232 void ImportLotus::Labelcell( void )
233 {
234 ScAddress aA;
235 String aLabel;
236 sal_Char cAlign;
237
238 Read( aA );
239 Read( cAlign );
240 Read( aLabel );
241
242 // aLabel.Convert( pLotusRoot->eCharsetQ );
243
244 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( aLabel ), (sal_Bool)sal_True );
245 }
246
247
Numbercell(void)248 void ImportLotus::Numbercell( void )
249 {
250 ScAddress aAddr;
251 double fVal;
252
253 Read( aAddr );
254 Read( fVal );
255
256 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(),
257 new ScValueCell( fVal ), (sal_Bool)sal_True );
258 }
259
260
Smallnumcell(void)261 void ImportLotus::Smallnumcell( void )
262 {
263 ScAddress aAddr;
264 sal_Int16 nVal;
265
266 Read( aAddr );
267 Read( nVal );
268
269 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(),
270 new ScValueCell( SnumToDouble( nVal ) ), ( sal_Bool ) sal_True );
271 }
272
273
Formulacell(sal_uInt16 n)274 ScFormulaCell *ImportLotus::Formulacell( sal_uInt16 n )
275 {
276 DBG_ASSERT( pIn, "-ImportLotus::Formulacell(): Null-Stream -> Rums!" );
277
278 ScAddress aAddr;
279
280 Read( aAddr );
281 Skip( 10 );
282
283 n -= (n > 14) ? 14 : n;
284
285 const ScTokenArray* pErg;
286 sal_Int32 nRest = n;
287
288 aConv.Reset( aAddr );
289 aConv.SetWK3();
290 aConv.Convert( pErg, nRest );
291
292 ScFormulaCell* pZelle = new ScFormulaCell( pD, aAddr, pErg );
293
294 pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
295
296 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(), pZelle, (sal_Bool)sal_True );
297
298 return NULL;
299 }
300
301
Read(String & r)302 void ImportLotus::Read( String &r )
303 {
304 ScfTools::AppendCString( *pIn, r, eQuellChar );
305 }
306
307
RowPresentation(sal_uInt16 nRecLen)308 void ImportLotus::RowPresentation( sal_uInt16 nRecLen )
309 {
310 DBG_ASSERT( nRecLen > 4, "*ImportLotus::RowPresentation(): Record zu kurz!" );
311
312 sal_uInt8 nLTab, nFlags;
313 sal_uInt16 nRow, nHeight;
314 sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 8;
315
316 Read( nLTab );
317 Skip( 1 );
318
319 while( nCnt )
320 {
321 Read( nRow );
322 Read( nHeight );
323 Skip( 2 );
324 Read( nFlags );
325 Skip( 1 );
326
327 if( nFlags & 0x02 ) // Fixed / Strech to fit fonts
328 { // fixed
329 // Height in Lotus in 1/32 Points
330 nHeight *= 20; // -> 32 * TWIPS
331 nHeight /= 32; // -> TWIPS
332
333 pD->SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), pD->GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CR_MANUALSIZE );
334
335 pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight );
336 }
337
338 nCnt--;
339 }
340 }
341
342
NamedSheet(void)343 void ImportLotus::NamedSheet( void )
344 {
345 sal_uInt16 nLTab;
346 String aName;
347
348 Read( nLTab );
349 Read( aName );
350
351 if( pD->HasTable( static_cast<SCTAB> (nLTab) ) )
352 pD->RenameTab( static_cast<SCTAB> (nLTab), aName );
353 else
354 pD->InsertTab( static_cast<SCTAB> (nLTab), aName );
355 }
356
357
Font_Face(void)358 void ImportLotus::Font_Face( void )
359 {
360 sal_uInt8 nNum;
361 String aName;
362
363 Read( nNum );
364
365 if( nNum >= LotusFontBuffer::nSize )
366 return; // nonsense
367
368 Read( aName );
369
370 pLotusRoot->pFontBuff->SetName( nNum, aName );
371 }
372
373
Font_Type(void)374 void ImportLotus::Font_Type( void )
375 {
376 for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
377 {
378 sal_uInt16 nType;
379 Read( nType );
380 pLotusRoot->pFontBuff->SetType( nCnt, nType );
381 }
382 }
383
384
Font_Ysize(void)385 void ImportLotus::Font_Ysize( void )
386 {
387 for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
388 {
389 sal_uInt16 nSize;
390 Read( nSize );
391 pLotusRoot->pFontBuff->SetHeight( nCnt, nSize );
392 }
393 }
394
395
_Row(const sal_uInt16 nRecLen)396 void ImportLotus::_Row( const sal_uInt16 nRecLen )
397 {
398 DBG_ASSERT( nExtTab >= 0, "*ImportLotus::_Row(): Kann hier nicht sein!" );
399
400 sal_uInt16 nRow;
401 sal_uInt16 nHeight;
402 sal_uInt16 nCntDwn = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 5;
403 SCCOL nColCnt = 0;
404 sal_uInt8 nRepeats;
405 LotAttrWK3 aAttr;
406
407 sal_Bool bCenter = sal_False;
408 SCCOL nCenterStart = 0, nCenterEnd = 0;
409
410 Read( nRow );
411 Read( nHeight );
412
413 nHeight &= 0x0FFF;
414 nHeight *= 22;
415
416 if( nHeight )
417 pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab), nHeight );
418
419 while( nCntDwn )
420 {
421 Read( aAttr );
422 Read( nRepeats );
423
424 if( aAttr.HasStyles() )
425 pLotusRoot->pAttrTable->SetAttr(
426 nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), static_cast<SCROW> (nRow), aAttr );
427
428 // hier und NICHT in class LotAttrTable, weil nur Attributiert wird,
429 // wenn die anderen Attribute gesetzt sind
430 // -> bei Center-Attribute wird generell zentriert gesetzt
431 if( aAttr.IsCentered() )
432 {
433 if( bCenter )
434 {
435 if( pD->HasData( nColCnt, static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab) ) )
436 {// neue Center nach vorheriger Center
437 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
438 nCenterStart = nColCnt;
439 }
440 }
441 else
442 {// ganz neue Center
443 bCenter = sal_True;
444 nCenterStart = nColCnt;
445 }
446 nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
447 }
448 else
449 {
450 if( bCenter )
451 {// evtl. alte Center bemachen
452 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
453 bCenter = sal_False;
454 }
455 }
456
457 nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
458 nColCnt++;
459
460 nCntDwn--;
461 }
462
463 if( bCenter )
464 // evtl. alte Center bemachen
465 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
466 }
467