xref: /aoo42x/main/sc/source/filter/lotus/lotimpop.cxx (revision b77af630)
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_scfilt.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