xref: /aoo41x/main/sc/source/filter/lotus/lotimpop.cxx (revision b3f79822)
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 
49 
50 ImportLotus::ImportLotus( SvStream& aStream, ScDocument* pDoc, CharSet eQ ) :
51     ImportTyp( pDoc, eQ ),
52 	pIn( &aStream ),
53 	aConv( *pIn, eQ, sal_False )
54 {
55 	// good point to start locking of import lotus
56 	aLotImpSemaphore.acquire();
57 
58 	pLotusRoot = new LOTUS_ROOT;
59 	pLotusRoot->pDoc = pDoc;
60 	pLotusRoot->pRangeNames = new LotusRangeList;
61 	pLotusRoot->pScRangeName = pDoc->GetRangeName();
62 	pLotusRoot->eCharsetQ = eQ;
63 	pLotusRoot->eFirstType = Lotus_X;
64 	pLotusRoot->eActType = Lotus_X;
65 	pLotusRoot->pRngNmBffWK3 = new RangeNameBufferWK3;
66 	pFontBuff = pLotusRoot->pFontBuff = new LotusFontBuffer;
67 	pLotusRoot->pAttrTable = new LotAttrTable;
68 }
69 
70 
71 ImportLotus::~ImportLotus()
72 {
73 	delete pLotusRoot->pRangeNames;
74 	delete pLotusRoot->pRngNmBffWK3;
75 	delete pFontBuff;
76 	delete pLotusRoot->pAttrTable;
77 	delete pLotusRoot;
78 
79 #ifdef DBG_UTIL
80 	pLotusRoot = NULL;
81 #endif
82 
83 	// no need 4 pLotusRoot anymore
84 	aLotImpSemaphore.release();
85 }
86 
87 
88 void ImportLotus::Bof( void )
89 {
90 	sal_uInt16	nFileCode, nFileSub, nSaveCnt;
91 	sal_uInt8	nMajorId, nMinorId, nFlags;
92 
93 	Read( nFileCode );
94 	Read( nFileSub );
95 	Read( pLotusRoot->aActRange );
96 	Read( nSaveCnt );
97 	Read( nMajorId );
98 	Read( nMinorId );
99 	Skip( 1 );
100 	Read( nFlags );
101 
102 	if( nFileSub == 0x0004 )
103 	{
104 		if( nFileCode == 0x1000 )
105 		{// <= WK3
106 			pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK3;
107 		}
108 		else if( nFileCode == 0x1002 )
109 		{// WK4
110 			pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK4;
111 		}
112 	}
113 }
114 
115 
116 sal_Bool ImportLotus::BofFm3( void )
117 {
118 	sal_uInt16	nFileCode, nFileSub;
119 
120 	Read( nFileCode );
121 	Read( nFileSub );
122 
123 	return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) );
124 }
125 
126 
127 void ImportLotus::Columnwidth( sal_uInt16 nRecLen )
128 {
129 	DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Columnwidth(): Record zu kurz!" );
130 
131     sal_uInt8    nLTab, nWindow2;
132 	sal_uInt16	nCnt = ( nRecLen - 4 ) / 2;
133 
134     Read( nLTab );
135 	Read( nWindow2 );
136 
137     if( !pD->HasTable( static_cast<SCTAB> (nLTab) ) )
138         pD->MakeTable( static_cast<SCTAB> (nLTab) );
139 
140 	if( !nWindow2 )
141 	{
142 		Skip( 2 );
143 
144 		sal_uInt8	nCol, nSpaces;
145 
146 		while( nCnt )
147 		{
148 			Read( nCol );
149 			Read( nSpaces );
150 			// ACHTUNG: Korrekturfaktor nach 'Augenmass' ermittelt!
151             pD->SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), ( sal_uInt16 ) ( TWIPS_PER_CHAR * 1.28 * nSpaces ) );
152 
153 			nCnt--;
154 		}
155 	}
156 }
157 
158 
159 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen )
160 {
161 	DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Hiddencolumn(): Record zu kurz!" );
162 
163     sal_uInt8    nLTab, nWindow2;
164 	sal_uInt16	nCnt = ( nRecLen - 4 ) / 2;
165 
166     Read( nLTab );
167 	Read( nWindow2 );
168 
169 	if( !nWindow2 )
170 	{
171 		Skip( 2 );
172 
173 		sal_uInt8	nCol;
174 
175 		while( nCnt )
176 		{
177 			Read( nCol );
178 
179             pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
180 			nCnt--;
181 		}
182 	}
183 }
184 
185 
186 void ImportLotus::Userrange( void )
187 {
188 	sal_uInt16		nRangeType;
189 	ScRange		aScRange;
190 	sal_Char*	pBuffer = new sal_Char[ 32 ];
191 
192 	Read( nRangeType );
193 
194 	pIn->Read( pBuffer, 16 );
195 	pBuffer[ 16 ] = ( sal_Char ) 0x00;	// zur Sicherheit...
196 	String		aName( pBuffer, eQuellChar );
197 
198 	Read( aScRange );
199 
200 	pLotusRoot->pRngNmBffWK3->Add( aName, aScRange );
201 	delete[] pBuffer;
202 }
203 
204 
205 void ImportLotus::Errcell( void )
206 {
207 	ScAddress	aA;
208 
209 	Read( aA );
210 
211     pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#ERR!" ) ), (sal_Bool)sal_True );
212 }
213 
214 
215 void ImportLotus::Nacell( void )
216 {
217 	ScAddress	aA;
218 
219 	Read( aA );
220 
221     pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#NA!" ) ), (sal_Bool)sal_True );
222 }
223 
224 
225 void ImportLotus::Labelcell( void )
226 {
227 	ScAddress	aA;
228 	String		aLabel;
229 	sal_Char	cAlign;
230 
231 	Read( aA );
232 	Read( cAlign );
233 	Read( aLabel );
234 
235 //	aLabel.Convert( pLotusRoot->eCharsetQ );
236 
237 	pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( aLabel ), (sal_Bool)sal_True );
238 }
239 
240 
241 void ImportLotus::Numbercell( void )
242 	{
243 	ScAddress	aAddr;
244 	double		fVal;
245 
246 	Read( aAddr );
247 	Read( fVal );
248 
249 	pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(),
250 		new ScValueCell( fVal ), (sal_Bool)sal_True );
251 	}
252 
253 
254 void ImportLotus::Smallnumcell( void )
255 	{
256 	ScAddress	aAddr;
257 	sal_Int16		nVal;
258 
259 	Read( aAddr );
260 	Read( nVal );
261 
262 	pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(),
263 		new ScValueCell( SnumToDouble( nVal ) ), ( sal_Bool ) sal_True );
264 	}
265 
266 
267 ScFormulaCell *ImportLotus::Formulacell( sal_uInt16 n )
268 	{
269 	DBG_ASSERT( pIn, "-ImportLotus::Formulacell(): Null-Stream -> Rums!" );
270 
271 	ScAddress			aAddr;
272 
273 	Read( aAddr );
274 	Skip( 10 );
275 
276 	n -= 14;
277 
278 	const ScTokenArray*	pErg;
279 	sal_Int32				nRest = n;
280 
281 	aConv.Reset( aAddr );
282 	aConv.SetWK3();
283 	aConv.Convert( pErg, nRest );
284 
285 	ScFormulaCell*		pZelle = new ScFormulaCell( pD, aAddr, pErg );
286 
287 	pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
288 
289 	pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(), pZelle, (sal_Bool)sal_True );
290 
291 	return NULL;
292 	}
293 
294 
295 void ImportLotus::Read( String &r )
296 {
297     ScfTools::AppendCString( *pIn, r, eQuellChar );
298 }
299 
300 
301 void ImportLotus::RowPresentation( sal_uInt16 nRecLen )
302 {
303 	DBG_ASSERT( nRecLen > 4, "*ImportLotus::RowPresentation(): Record zu kurz!" );
304 
305     sal_uInt8    nLTab, nFlags;
306 	sal_uInt16	nRow, nHeight;
307 	sal_uInt16	nCnt = ( nRecLen - 4 ) / 8;
308 
309     Read( nLTab );
310 	Skip( 1 );
311 
312 	while( nCnt )
313 	{
314 		Read( nRow );
315 		Read( nHeight );
316 		Skip( 2 );
317 		Read( nFlags );
318 		Skip( 1 );
319 
320 		if( nFlags & 0x02 )		// Fixed / Strech to fit fonts
321 		{	// fixed
322 			// Height in Lotus in 1/32 Points
323 			nHeight *= 20;	// -> 32 * TWIPS
324 			nHeight /= 32;	// -> TWIPS
325 
326             pD->SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), pD->GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CR_MANUALSIZE );
327 
328             pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight );
329 		}
330 
331 		nCnt--;
332 	}
333 }
334 
335 
336 void ImportLotus::NamedSheet( void )
337 {
338     sal_uInt16  nLTab;
339 	String	aName;
340 
341     Read( nLTab );
342 	Read( aName );
343 
344     if( pD->HasTable( static_cast<SCTAB> (nLTab) ) )
345         pD->RenameTab( static_cast<SCTAB> (nLTab), aName );
346 	else
347         pD->InsertTab( static_cast<SCTAB> (nLTab), aName );
348 }
349 
350 
351 void ImportLotus::Font_Face( void )
352 {
353 	sal_uInt8	nNum;
354 	String	aName;
355 
356 	Read( nNum );
357 
358 	// ACHTUNG: QUICK-HACK gegen unerklaerliche Loops
359 	if( nNum > 7 )
360 		return;
361 	// ACHTUNG
362 
363 	Read( aName );
364 
365 	pFontBuff->SetName( nNum, aName );
366 }
367 
368 
369 void ImportLotus::Font_Type( void )
370 {
371 	static const sal_uInt16 nAnz = 8;
372 	sal_uInt16				nCnt;
373 	sal_uInt16				nType;
374 
375 	for( nCnt = 0 ; nCnt < nAnz ; nCnt++ )
376 	{
377 		Read( nType );
378 		pFontBuff->SetType( nCnt, nType );
379 	}
380 }
381 
382 
383 void ImportLotus::Font_Ysize( void )
384 {
385 	static const sal_uInt16	nAnz = 8;
386 	sal_uInt16				nCnt;
387 	sal_uInt16				nSize;
388 
389 	for( nCnt = 0 ; nCnt < nAnz ; nCnt++ )
390 	{
391 		Read( nSize );
392 		pFontBuff->SetHeight( nCnt, nSize );
393 	}
394 }
395 
396 
397 void ImportLotus::_Row( const sal_uInt16 nRecLen )
398 	{
399 	DBG_ASSERT( nExtTab >= 0, "*ImportLotus::_Row(): Kann hier nicht sein!" );
400 
401 	sal_uInt16			nRow;
402 	sal_uInt16			nHeight;
403 	sal_uInt16			nCntDwn = ( nRecLen - 4 ) / 5;
404 	SCCOL			nColCnt = 0;
405 	sal_uInt8			nRepeats;
406 	LotAttrWK3		aAttr;
407 
408 	sal_Bool			bCenter = sal_False;
409     SCCOL           nCenterStart = 0, nCenterEnd = 0;
410 
411 	Read( nRow );
412 	Read( nHeight );
413 
414 	nHeight &= 0x0FFF;
415 	nHeight *= 22;
416 
417 	if( nHeight )
418 		pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab), nHeight );
419 
420 	while( nCntDwn )
421 		{
422 		Read( aAttr );
423 		Read( nRepeats );
424 
425 		if( aAttr.HasStyles() )
426 			pLotusRoot->pAttrTable->SetAttr(
427 				nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), static_cast<SCROW> (nRow), aAttr );
428 
429 		// hier und NICHT in class LotAttrTable, weil nur Attributiert wird,
430 		// wenn die anderen Attribute gesetzt sind
431 		//  -> bei Center-Attribute wird generell zentriert gesetzt
432 		if( aAttr.IsCentered() )
433 			{
434 			if( bCenter )
435 				{
436 				if( pD->HasData( nColCnt, static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab) ) )
437 					{// neue Center nach vorheriger Center
438 					pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
439 					nCenterStart = nColCnt;
440 					}
441 				}
442 			else
443 				{// ganz neue Center
444 				bCenter = sal_True;
445 				nCenterStart = nColCnt;
446 				}
447 			nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
448 			}
449 		else
450 			{
451 			if( bCenter )
452 				{// evtl. alte Center bemachen
453 				pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
454 				bCenter = sal_False;
455 				}
456 			}
457 
458         nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
459 		nColCnt++;
460 
461 		nCntDwn--;
462 		}
463 
464 	if( bCenter )
465 		// evtl. alte Center bemachen
466 		pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) );
467 	}
468 
469 
470