xref: /trunk/main/sc/source/filter/dif/difimp.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 
27 //------------------------------------------------------------------------
28 
29 #include "scitems.hxx"
30 #include <svl/zforlist.hxx>
31 
32 #include "dif.hxx"
33 #include "filter.hxx"
34 #include "fprogressbar.hxx"
35 #include "scerrors.hxx"
36 #include "document.hxx"
37 #include "cell.hxx"
38 #include "patattr.hxx"
39 #include "docpool.hxx"
40 #include "attrib.hxx"
41 #include "ftools.hxx"
42 
43 #include <math.h>
44 
45 const sal_Unicode pKeyTABLE[]   = { 'T', 'A', 'B', 'L', 'E', 0 };
46 const sal_Unicode pKeyVECTORS[] = { 'V', 'E', 'C', 'T', 'O', 'R', 'S', 0 };
47 const sal_Unicode pKeyTUPLES[]  = { 'T', 'U', 'P', 'L', 'E', 'S', 0 };
48 const sal_Unicode pKeyDATA[]    = { 'D', 'A', 'T', 'A', 0 };
49 const sal_Unicode pKeyBOT[]     = { 'B', 'O', 'T', 0 };
50 const sal_Unicode pKeyEOD[]     = { 'E', 'O', 'D', 0 };
51 const sal_Unicode pKeyERROR[]   = { 'E', 'R', 'R', 'O', 'R', 0 };
52 const sal_Unicode pKeyTRUE[]    = { 'T', 'R', 'U', 'E', 0 };
53 const sal_Unicode pKeyFALSE[]   = { 'F', 'A', 'L', 'S', 'E', 0 };
54 const sal_Unicode pKeyNA[]      = { 'N', 'A', 0 };
55 const sal_Unicode pKeyV[]       = { 'V', 0 };
56 const sal_Unicode pKey1_0[]     = { '1', ',', '0', 0 };
57 
58 
ScImportDif(SvStream & rIn,ScDocument * pDoc,const ScAddress & rInsPos,const CharSet eVon,sal_uInt32 nDifOption)59 FltError ScFormatFilterPluginImpl::ScImportDif( SvStream& rIn, ScDocument* pDoc, const ScAddress& rInsPos,
60 						const CharSet eVon, sal_uInt32 nDifOption )
61 {
62 	DifParser	aDifParser( rIn, nDifOption, *pDoc, eVon );
63 
64 	const sal_Bool	bPlain = aDifParser.IsPlain();
65 
66 	SCTAB		nBaseTab = rInsPos.Tab();
67 
68 	TOPIC		eTopic = T_UNKNOWN;
69 	sal_Bool		bSyntErrWarn = sal_False;
70 	sal_Bool		bOverflowWarn = sal_False;
71 
72 	String&	    rData = aDifParser.aData;
73 	sal_Bool		bData = sal_False;
74 
75 	SCCOL		nNumCols = 0;
76 	SCROW		nNumRows = 0;
77 
78 	rIn.Seek( 0 );
79 
80     ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
81 
82 	while( eTopic != T_DATA && eTopic != T_END )
83 	{
84 		eTopic = aDifParser.GetNextTopic();
85 
86 		aPrgrsBar.Progress();
87 
88 		bData = rData.Len() > 0;
89 
90 		switch( eTopic )
91 		{
92 			case T_TABLE:
93 			{
94 				if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
95 					bSyntErrWarn = sal_True;
96 				if( bData )
97 					pDoc->RenameTab( nBaseTab, rData );
98 			}
99 				break;
100 			case T_VECTORS:
101 			{
102 				if( aDifParser.nVector != 0 )
103 					bSyntErrWarn = sal_True;
104 				if( aDifParser.nVal > MAXCOL + 1 )
105 					nNumCols = SCCOL_MAX;
106 				else
107 					nNumCols = static_cast<SCCOL>(aDifParser.nVal);
108 			}
109 				break;
110 			case T_TUPLES:
111 			{
112 				if( aDifParser.nVector != 0 )
113 					bSyntErrWarn = sal_True;
114 				if( aDifParser.nVal > MAXROW + 1 )
115 					nNumRows = SCROW_MAX;
116 				else
117 					nNumRows = static_cast<SCROW>(aDifParser.nVal);
118 			}
119 				break;
120 			case T_DATA:
121 			{
122 				if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
123 					bSyntErrWarn = sal_True;
124 			}
125 				break;
126 			case T_LABEL:
127 			case T_COMMENT:
128 			case T_SIZE:
129 			case T_PERIODICITY:
130 			case T_MAJORSTART:
131 			case T_MINORSTART:
132 			case T_TRUELENGTH:
133 			case T_UINITS:
134 			case T_DISPLAYUNITS:
135 			case T_END:
136 			case T_UNKNOWN:
137 				break;
138 			default:
139                 DBG_ERRORFILE( "ScImportDif - missing enum" );
140 		}
141 
142 	}
143 
144 
145 	if( eTopic == T_DATA )
146 	{	// Ab hier kommen die Daten
147 		SCCOL				nBaseCol = rInsPos.Col();
148 
149 		SCCOL				nColCnt = SCCOL_MAX;
150 		SCROW				nRowCnt = rInsPos.Row();
151 		DifAttrCache		aAttrCache( bPlain );
152 
153 		DATASET				eAkt = D_UNKNOWN;
154 
155 		while( eAkt != D_EOD )
156 			{
157 			eAkt = aDifParser.GetNextDataset();
158 
159 			aPrgrsBar.Progress();
160 
161 			switch( eAkt )
162 				{
163 				case D_BOT:
164 					if( nColCnt < SCCOL_MAX )
165 						nRowCnt++;
166 					nColCnt = nBaseCol;
167 					break;
168 				case D_EOD:
169 					break;
170 				case D_NUMERIC:					// Numbercell
171 					if( nColCnt == SCCOL_MAX )
172 						nColCnt = nBaseCol;
173 
174 					if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
175 					{
176 						ScBaseCell*		pCell;
177 						if( DifParser::IsV( rData.GetBuffer() ) )
178 						{
179 							pCell = new ScValueCell( aDifParser.fVal );
180 							if( !bPlain )
181 								aAttrCache.SetNumFormat( nColCnt, nRowCnt,
182 									aDifParser.nNumFormat );
183 						}
184 						else if( rData == pKeyTRUE || rData == pKeyFALSE )
185 						{
186 							pCell = new ScValueCell( aDifParser.fVal );
187 							if( bPlain )
188 								aAttrCache.SetLogical( nColCnt, nRowCnt );
189 							else
190 								aAttrCache.SetNumFormat( nColCnt, nRowCnt,
191 									aDifParser.nNumFormat );
192 						}
193 						else if( rData == pKeyNA || rData == pKeyERROR  )
194 							pCell = new ScStringCell( rData );
195 						else
196 						{
197 							String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#IND: " ));
198 							aTmp += rData;
199 							aTmp += sal_Unicode('?');
200 							pCell = new ScStringCell( aTmp );
201 						}
202 
203 						pDoc->PutCell( nColCnt, nRowCnt, nBaseTab, pCell, ( sal_Bool ) sal_True );
204 					}
205 					else
206 						bOverflowWarn = sal_True;
207 
208 					nColCnt++;
209 					break;
210 				case D_STRING:					// Textcell
211 					if( nColCnt == SCCOL_MAX )
212 						nColCnt = nBaseCol;
213 
214 					if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
215 					{
216 						if( rData.Len() > 0 )
217 						{
218 							pDoc->PutCell( nColCnt, nRowCnt, nBaseTab,
219 								ScBaseCell::CreateTextCell( rData, pDoc ), ( sal_Bool ) sal_True );
220 						}
221 					}
222 					else
223 						bOverflowWarn = sal_True;
224 
225 					nColCnt++;
226 					break;
227 				case D_UNKNOWN:
228 					break;
229 				case D_SYNT_ERROR:
230 					break;
231 				default:
232                     DBG_ERROR( "ScImportDif - missing enum" );
233 			}
234 		}
235 
236 		aAttrCache.Apply( *pDoc, nBaseTab );
237 	}
238 	else
239 		return eERR_FORMAT;
240 
241 	if( bSyntErrWarn )
242 		//###############################################
243 		// ACHTUNG: Hier fehlt noch die richtige Warnung!
244 		return eERR_RNGOVRFLW;
245 		//###############################################
246 	else if( bOverflowWarn )
247 		return eERR_RNGOVRFLW;
248 	else
249 		return eERR_OK;
250 }
251 
252 
DifParser(SvStream & rNewIn,const sal_uInt32 nOption,ScDocument & rDoc,CharSet e)253 DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, CharSet e ) :
254 	rIn( rNewIn )
255 {
256 	eCharSet = e;
257     if ( rIn.GetStreamCharSet() != eCharSet )
258     {
259         DBG_ERRORFILE( "CharSet passed overrides and modifies StreamCharSet" );
260         rIn.SetStreamCharSet( eCharSet );
261     }
262     rIn.StartReadingUnicodeText( eCharSet );
263 
264 	bPlain = ( nOption == SC_DIFOPT_PLAIN );
265 
266 	if( bPlain )
267 		pNumFormatter = NULL;
268 	else
269 		pNumFormatter = rDoc.GetFormatTable();
270 }
271 
272 
GetNextTopic(void)273 TOPIC DifParser::GetNextTopic( void )
274 {
275 	enum STATE { S_VectorVal, S_Data, S_END, S_START, S_UNKNOWN, S_ERROR_L2 };
276 
277     static const sal_Unicode pKeyLABEL[]        = { 'L', 'A', 'B', 'E', 'L', 0 };
278     static const sal_Unicode pKeyCOMMENT[]      = { 'C', 'O', 'M', 'M', 'E', 'N', 'T', 0 };
279     static const sal_Unicode pKeySIZE[]         = { 'S', 'I', 'Z', 'E', 0 };
280     static const sal_Unicode pKeyPERIODICITY[]  = { 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', 'I', 'T', 'Y', 0 };
281     static const sal_Unicode pKeyMAJORSTART[]   = { 'M', 'A', 'J', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
282     static const sal_Unicode pKeyMINORSTART[]   = { 'M', 'I', 'N', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
283     static const sal_Unicode pKeyTRUELENGTH[]   = { 'T', 'R', 'U', 'E', 'L', 'E', 'N', 'G', 'T', 'H', 0 };
284     static const sal_Unicode pKeyUINITS[]       = { 'U', 'I', 'N', 'I', 'T', 'S', 0 };
285     static const sal_Unicode pKeyDISPLAYUNITS[] = { 'D', 'I', 'S', 'P', 'L', 'A', 'Y', 'U', 'N', 'I', 'T', 'S', 0 };
286     static const sal_Unicode pKeyUNKNOWN[]      = { 0 };
287 
288 	static const sal_Unicode*	ppKeys[] =
289 	{
290 		pKeyTABLE,				// 0
291 		pKeyVECTORS,
292 		pKeyTUPLES,
293 		pKeyDATA,
294         pKeyLABEL,
295         pKeyCOMMENT,            // 5
296         pKeySIZE,
297         pKeyPERIODICITY,
298         pKeyMAJORSTART,
299         pKeyMINORSTART,
300         pKeyTRUELENGTH,         // 10
301         pKeyUINITS,
302         pKeyDISPLAYUNITS,
303 		pKeyUNKNOWN				// 13
304 	};
305 
306 	static const TOPIC		pTopics[] =
307 	{
308 		T_TABLE,				// 0
309 		T_VECTORS,
310 		T_TUPLES,
311 		T_DATA,
312 		T_LABEL,
313 		T_COMMENT,				// 5
314 		T_SIZE,
315 		T_PERIODICITY,
316 		T_MAJORSTART,
317 		T_MINORSTART,
318 		T_TRUELENGTH,			// 10
319 		T_UINITS,
320 		T_DISPLAYUNITS,
321 		T_UNKNOWN				// 13
322 	};
323 
324 	STATE					eS = S_START;
325 	String				    aLine;
326 
327 	nVector = 0;
328 	nVal = 0;
329 	TOPIC eRet = T_UNKNOWN;
330 
331 	while( eS != S_END )
332 	{
333 		if( !ReadNextLine( aLine ) )
334 		{
335 			eS = S_END;
336 			eRet = T_END;
337 		}
338 
339 		switch( eS )
340 		{
341 			case S_START:
342 			{
343 				const sal_Unicode*	pRef;
344 				sal_uInt16			nCnt = 0;
345 				sal_Bool			bSearch = sal_True;
346 
347 				pRef = ppKeys[ nCnt ];
348 
349 				while( bSearch )
350 				{
351 					if( aLine == pRef )
352 					{
353 						eRet = pTopics[ nCnt ];
354 						bSearch = sal_False;
355 					}
356 					else
357 					{
358 						nCnt++;
359 						pRef = ppKeys[ nCnt ];
360 						if( !*pRef )
361 							bSearch = sal_False;
362 					}
363 				}
364 
365 				if( *pRef )
366 					eS = S_VectorVal;
367 				else
368 					eS = S_UNKNOWN;
369 			}
370 				break;
371 			case S_VectorVal:
372 			{
373 				const sal_Unicode*		pCur = aLine.GetBuffer();
374 
375 				pCur = ScanIntVal( pCur, nVector );
376 
377 				if( pCur && *pCur == ',' )
378 				{
379 					pCur++;
380 					ScanIntVal( pCur, nVal );
381 					eS = S_Data;
382 				}
383 				else
384 					eS = S_ERROR_L2;
385 			}
386 				break;
387 			case S_Data:
388 				DBG_ASSERT( aLine.Len() >= 2,
389 					"+GetNextTopic(): <String> ist zu kurz!" );
390 				if( aLine.Len() > 2 )
391 					aData = aLine.Copy( 1, aLine.Len() - 2 );
392 				else
393 					aData.Erase();
394 				eS = S_END;
395 				break;
396 			case S_END:
397                 DBG_ERRORFILE( "DifParser::GetNextTopic - unexpected state" );
398 				break;
399 			case S_UNKNOWN:
400 				// 2 Zeilen ueberlesen
401 				ReadNextLine( aLine );
402 			case S_ERROR_L2:				// Fehler in Line 2 aufgetreten
403 				// eine Zeile ueberlesen
404 				ReadNextLine( aLine );
405 				eS = S_END;
406 				break;
407 			default:
408                 DBG_ERRORFILE( "DifParser::GetNextTopic - missing enum" );
409 		}
410 	}
411 
412 	return eRet;
413 }
414 
415 
lcl_DeEscapeQuotesDif(String & rString)416 static void lcl_DeEscapeQuotesDif( String& rString )
417 {
418 	//	Special handling for DIF import: Escaped (duplicated) quotes are resolved.
419 	//	Single quote characters are left in place because older versions didn't
420 	//	escape quotes in strings (and Excel doesn't when using the clipboard).
421 	//	The quotes around the string are removed before this function is called.
422 
423     static const sal_Unicode aDQ[] = { '"', '"', 0 };
424 	xub_StrLen nPos = 0;
425 	while ( (nPos = rString.Search( aDQ, nPos )) != STRING_NOTFOUND )
426 	{
427 		rString.Erase( nPos, 1 );
428 		++nPos;
429 	}
430 }
431 
432 // Determine if passed in string is numeric data and set fVal/nNumFormat if so
GetNumberDataset(const sal_Unicode * pPossibleNumericData)433 DATASET DifParser::GetNumberDataset( const sal_Unicode* pPossibleNumericData )
434 {
435     DATASET eRet = D_SYNT_ERROR;
436     if( bPlain )
437     {
438         if( ScanFloatVal( pPossibleNumericData ) )
439             eRet = D_NUMERIC;
440         else
441             eRet = D_SYNT_ERROR;
442     }
443     else
444     {   // ...und zur Strafe mit'm Numberformatter...
445         DBG_ASSERT( pNumFormatter, "-DifParser::GetNextDataset(): No Formatter, more fun!" );
446         String aTestVal( pPossibleNumericData );
447         sal_uInt32 nFormat = 0;
448         double fTmpVal;
449         if( pNumFormatter->IsNumberFormat( aTestVal, nFormat, fTmpVal ) )
450         {
451             fVal = fTmpVal;
452             nNumFormat = nFormat;
453             eRet = D_NUMERIC;
454         }
455         else
456             eRet = D_SYNT_ERROR;
457     }
458     return eRet;
459 }
460 
ReadNextLine(String & rStr)461 bool DifParser::ReadNextLine( String& rStr )
462 {
463     if( aLookAheadLine.Len() == 0 )
464     {
465         return rIn.ReadUniOrByteStringLine( rStr );
466     }
467     else
468     {
469         rStr = aLookAheadLine;
470         aLookAheadLine.Erase();
471         return true;
472     }
473 }
474 
475 // Look ahead in the stream to determine if the next line is the first line of
476 // a valid data record structure
LookAhead()477 bool DifParser::LookAhead()
478 {
479     const sal_Unicode* pAktBuffer;
480     bool bValidStructure = false;
481 
482     DBG_ASSERT( aLookAheadLine.Len() == 0, "*DifParser::LookAhead(): LookAhead called twice in a row" );
483     rIn.ReadUniOrByteStringLine( aLookAheadLine );
484 
485     pAktBuffer = aLookAheadLine.GetBuffer();
486 
487     switch( *pAktBuffer )
488     {
489         case '-':                   // Special Datatype
490             pAktBuffer++;
491 
492             if( Is1_0( pAktBuffer ) )
493             {
494                 bValidStructure = true;
495             }
496             break;
497         case '0':                   // Numeric Data
498             pAktBuffer++;
499             if( *pAktBuffer == ',' )
500             {
501                 pAktBuffer++;
502                 bValidStructure = ( GetNumberDataset(pAktBuffer) != D_SYNT_ERROR );
503             }
504             break;
505         case '1':                   // String Data
506             if( Is1_0( aLookAheadLine.GetBuffer() ) )
507             {
508                 bValidStructure = true;
509             }
510             break;
511     }
512     return bValidStructure;
513 }
514 
GetNextDataset(void)515 DATASET	DifParser::GetNextDataset( void )
516 {
517 	DATASET				eRet = D_UNKNOWN;
518 	String			    aLine;
519 	const sal_Unicode*		pAktBuffer;
520 
521 	ReadNextLine( aLine );
522 
523 	pAktBuffer = aLine.GetBuffer();
524 
525 	switch( *pAktBuffer )
526 	{
527 		case '-':					// Special Datatype
528 			pAktBuffer++;
529 
530 			if( Is1_0( pAktBuffer ) )
531 			{
532 				ReadNextLine( aLine );
533 				if( IsBOT( aLine.GetBuffer() ) )
534 					eRet = D_BOT;
535 				else if( IsEOD( aLine.GetBuffer() ) )
536 					eRet = D_EOD;
537 			}
538 			break;
539 		case '0':					// Numeric Data
540 			pAktBuffer++;			// Wert in fVal, 2. Zeile in aData
541 			if( *pAktBuffer == ',' )
542 			{
543 				pAktBuffer++;
544                 eRet = GetNumberDataset(pAktBuffer);
545                 ReadNextLine( aData );
546                 if ( eRet == D_SYNT_ERROR )
547                 {   // for broken records write "#ERR: data" to cell
548                     String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#ERR: " ));
549                     aTmp += pAktBuffer;
550                     aTmp.AppendAscii( " (" );
551                     aTmp += aData;
552                     aTmp += sal_Unicode(')');
553                     aData = aTmp;
554                     eRet = D_STRING;
555                 }
556 			}
557 			break;
558 		case '1':					// String Data
559 			if( Is1_0( aLine.GetBuffer() ) )
560 			{
561 				ReadNextLine( aLine );
562                 xub_StrLen nLineLength = aLine.Len();
563                 const sal_Unicode* pLine = aLine.GetBuffer();
564 
565                 if( nLineLength >= 1 && *pLine == '"' )
566                 {
567                     // Quotes are not always escaped (duplicated), see lcl_DeEscapeQuotesDif
568                     // A look ahead into the next line is needed in order to deal with
569                     // multiline strings containing quotes
570                     if( LookAhead() )
571                     {
572                         // Single line string
573                         if( nLineLength >= 2 && pLine[nLineLength - 1] == '"' )
574                         {
575                             aData = aLine.Copy( 1, nLineLength - 2 );
576                             lcl_DeEscapeQuotesDif( aData );
577                             eRet = D_STRING;
578                         }
579                     }
580                     else
581                     {
582                         // Multiline string
583                         aData = aLine.Copy( 1 );
584                         bool bContinue = true;
585                         while ( bContinue )
586                         {
587                             aData.Append( '\n' );
588                             bContinue = !rIn.IsEof() && ReadNextLine( aLine );
589                             if( bContinue )
590                             {
591                                 nLineLength = aLine.Len();
592                                 if( nLineLength >= 1 )
593                                 {
594                                     pLine = aLine.GetBuffer();
595                                     bContinue = !LookAhead();
596                                     if( bContinue )
597                                     {
598                                         aData.Append( aLine );
599                                     }
600                                     else if( pLine[nLineLength - 1] == '"' )
601                                     {
602                                         aData.Append( pLine, nLineLength - 1 );
603                                         lcl_DeEscapeQuotesDif( aData );
604                                         eRet = D_STRING;
605                                     }
606                                 }
607                             }
608                         };
609                     }
610                 }
611 			}
612 			break;
613 	}
614 
615 	if( eRet == D_UNKNOWN )
616 		ReadNextLine( aLine );
617 
618 	if( rIn.IsEof() )
619 		eRet = D_EOD;
620 
621 	return eRet;
622 }
623 
624 
ScanIntVal(const sal_Unicode * pStart,sal_uInt32 & rRet)625 const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
626 {
627     // eat leading whitespace, not specified, but seen in the wild
628     while (*pStart == ' ' || *pStart == '\t')
629         ++pStart;
630 
631 	sal_Unicode		cAkt = *pStart;
632 
633 	if( IsNumber( cAkt ) )
634 		rRet = ( sal_uInt32 ) ( cAkt - '0' );
635 	else
636 		return NULL;
637 
638 	pStart++;
639 	cAkt = *pStart;
640 
641 	while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
642 	{
643 		rRet *= 10;
644 		rRet += ( sal_uInt32 ) ( cAkt - '0' );
645 
646 		pStart++;
647 		cAkt = *pStart;
648 	}
649 
650 	return pStart;
651 }
652 
653 
ScanFloatVal(const sal_Unicode * pStart)654 sal_Bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
655 	{
656 	double					fNewVal = 0.0;
657 	sal_Bool					bNeg = sal_False;
658     double                  fFracPos = 1.0;
659 	sal_Int32					nExp = 0;
660 	sal_Bool					bExpNeg = sal_False;
661 	sal_Bool					bExpOverflow = sal_False;
662 	static const sal_uInt16		nExpLimit = 4096;	// ACHTUNG: muss genauer ermittelt werden!
663 
664 	sal_Unicode				cAkt;
665 	sal_Bool					bRet = sal_False;
666 
667 	enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
668 
669 	STATE	eS = S_FIRST;
670 
671 	fNewVal = 0.0;
672 
673 	while( eS != S_END )
674 	{
675 		cAkt = *pStart;
676 		switch( eS )
677 		{
678 			case S_FIRST:
679 				if( IsNumber( cAkt ) )
680 				{
681 					fNewVal *= 10;
682 					fNewVal += cAkt - '0';
683 					eS = S_PRE;
684 				}
685 				else
686 				{
687 					switch( cAkt )
688 					{
689 						case ' ':
690 						case '\t':
691 						case '+':
692 							break;
693 						case '-':
694 							bNeg = !bNeg;
695 							break;
696 						case '.':
697 						case ',':					//!
698 							eS = S_POST;
699 							fFracPos = 0.1;
700 							break;
701 						default:
702 							eS = S_END;
703 					}
704 				}
705 				break;
706 			case S_PRE:
707 				if( IsNumber( cAkt ) )
708 				{
709 					fNewVal *= 10;
710 					fNewVal += cAkt - '0';
711 				}
712 				else
713 				{
714 					switch( cAkt )
715 					{
716 						case '.':
717 						case ',':					//!
718 							eS = S_POST;
719 							fFracPos = 0.1;
720 							break;
721 						case 'e':
722 						case 'E':
723 							eS = S_EXP;
724 							break;
725 						case 0x00:				// IsNumberEnding( cAkt )
726 							bRet = sal_True;		// no
727 						default:				// break!
728 							eS = S_END;
729 					}
730 				}
731 				break;
732 			case S_POST:
733 				if( IsNumber( cAkt ) )
734 				{
735 					fNewVal += fFracPos * ( cAkt - '0' );
736 					fFracPos /= 10.0;
737 				}
738 				else
739 				{
740 					switch( cAkt )
741 					{
742 						case 'e':
743 						case 'E':
744 							eS = S_EXP_FIRST;
745 							break;
746 						case 0x00:				// IsNumberEnding( cAkt )
747 							bRet = sal_True;		// no
748 						default:				// break!
749 							eS = S_END;
750 					}
751 				}
752 				break;
753 			case S_EXP_FIRST:
754 				if( IsNumber( cAkt ) )
755 				{
756 					if( nExp < nExpLimit )
757 					{
758 						nExp *= 10;
759 						nExp += ( sal_uInt16 ) ( cAkt - '0' );
760 					}
761 					eS = S_EXP;
762 				}
763 				else
764 				{
765 					switch( cAkt )
766 					{
767 						case '+':
768 							break;
769 						case '-':
770 							bExpNeg = !bExpNeg;
771 							break;
772 						default:
773 							eS = S_END;
774 					}
775 				}
776 				break;
777 			case S_EXP:
778 				if( IsNumber( cAkt ) )
779 				{
780 					if( nExp < ( 0xFFFF / 10 ) )
781 					{
782 						nExp *= 10;
783 						nExp += ( sal_uInt16 ) ( cAkt - '0' );
784 					}
785 					else
786 					{
787 						bExpOverflow = sal_True;
788 						eS = S_FINDEND;
789 					}
790 				}
791 				else
792 				{
793 					bRet = IsNumberEnding( cAkt );
794 					eS = S_END;
795 				}
796 				break;
797 			case S_FINDEND:
798 				if( IsNumberEnding( cAkt ) )
799 				{
800 					bRet = sal_True;		// damit sinnvoll weitergeparst werden kann
801 					eS = S_END;
802 				}
803 				break;
804 			case S_END:
805                 DBG_ERRORFILE( "DifParser::ScanFloatVal - unexpected state" );
806 				break;
807 			default:
808                 DBG_ERRORFILE( "DifParser::ScanFloatVal - missing enum" );
809 		}
810 		pStart++;
811 	}
812 
813 	if( bRet )
814 	{
815 		if( bExpOverflow )
816 			return sal_False;		// ACHTUNG: hier muss noch differenziert werden
817 
818 		if( bNeg )
819 			fNewVal *= 1.0;
820 
821 		if( bExpNeg )
822 			nExp *= -1;
823 
824 		if( nExp != 0 )
825 			fNewVal *= pow( 10.0, ( double ) nExp );
826 		fVal = fNewVal;
827 	}
828 
829 	return bRet;
830 }
831 
832 
~DifColumn(void)833 DifColumn::~DifColumn( void )
834 {
835     ENTRY*  pEntry = ( ENTRY* ) List::First();
836 
837     while( pEntry )
838 	{
839         delete pEntry;
840         pEntry = ( ENTRY* ) List::Next();
841 	}
842 }
843 
844 
SetLogical(SCROW nRow)845 void DifColumn::SetLogical( SCROW nRow )
846 {
847 	DBG_ASSERT( ValidRow(nRow), "*DifColumn::SetLogical(): Row zu gross!" );
848 
849 	if( pAkt )
850 	{
851 		DBG_ASSERT( nRow > 0, "*DifColumn::SetLogical(): weitere koennen nicht 0 sein!" );
852 		nRow--;
853 		if( pAkt->nEnd == nRow )
854 			pAkt->nEnd++;
855 		else
856 			pAkt = NULL;
857 	}
858 	else
859 	{
860 		pAkt = new ENTRY;
861 		pAkt->nStart = pAkt->nEnd = nRow;
862 		List::Insert( pAkt, LIST_APPEND );
863 	}
864 }
865 
866 
SetNumFormat(SCROW nRow,const sal_uInt32 nNumFormat)867 void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
868 {
869 	DBG_ASSERT( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row zu gross!" );
870 
871 	if( nNumFormat > 0 )
872 	{
873 		if( pAkt )
874 		{
875 			DBG_ASSERT( nRow > 0,
876 				"*DifColumn::SetNumFormat(): weitere koennen nicht 0 sein!" );
877 			DBG_ASSERT( nRow > pAkt->nEnd,
878 				"*DifColumn::SetNumFormat(): Noch 'mal von vorne?" );
879 
880 			if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
881 				pAkt->nEnd = nRow;
882 			else
883 				NewEntry( nRow, nNumFormat );
884 			}
885 		else
886 			NewEntry( nRow, nNumFormat );
887 		}
888 	else
889 		pAkt = NULL;
890 }
891 
892 
NewEntry(const SCROW nPos,const sal_uInt32 nNumFormat)893 void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
894 {
895 	pAkt = new ENTRY;
896 	pAkt->nStart = pAkt->nEnd = nPos;
897 	pAkt->nNumFormat = nNumFormat;
898 	List::Insert( pAkt, LIST_APPEND );
899 }
900 
901 
Apply(ScDocument & rDoc,const SCCOL nCol,const SCTAB nTab,const ScPatternAttr & rPattAttr)902 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
903 {
904     ENTRY*  pEntry = ( ENTRY* ) List::First();
905 
906     while( pEntry )
907 	{
908         rDoc.ApplyPatternAreaTab( nCol, pEntry->nStart, nCol, pEntry->nEnd,
909 				nTab, rPattAttr );
910         pEntry = ( ENTRY* ) List::Next();
911 	}
912 }
913 
914 
Apply(ScDocument & rDoc,const SCCOL nCol,const SCTAB nTab)915 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
916 {
917 	ScPatternAttr	aAttr( rDoc.GetPool() );
918 	SfxItemSet&		rItemSet = aAttr.GetItemSet();
919 
920     ENTRY*          pEntry = ( ENTRY* ) List::First();
921 
922     while( pEntry )
923 		{
924         DBG_ASSERT( pEntry->nNumFormat > 0,
925 			"+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
926         rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, pEntry->nNumFormat ) );
927 
928         rDoc.ApplyPatternAreaTab( nCol, pEntry->nStart, nCol, pEntry->nEnd, nTab, aAttr );
929 
930 		rItemSet.ClearItem();
931 
932         pEntry = ( ENTRY* ) List::Next();
933 	}
934 }
935 
936 
DifAttrCache(const sal_Bool bNewPlain)937 DifAttrCache::DifAttrCache( const sal_Bool bNewPlain )
938 {
939 	bPlain = bNewPlain;
940 	ppCols = new DifColumn *[ MAXCOL + 1 ];
941 	for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
942 		ppCols[ nCnt ] = NULL;
943 }
944 
945 
~DifAttrCache()946 DifAttrCache::~DifAttrCache()
947 {
948 	for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
949 	{
950 		if( ppCols[ nCnt ] )
951 			delete ppCols[ nCnt ];
952 	}
953 }
954 
955 
SetNumFormat(const SCCOL nCol,const SCROW nRow,const sal_uInt32 nNumFormat)956 void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
957 {
958 	DBG_ASSERT( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col zu gross!" );
959 	DBG_ASSERT( !bPlain, "*DifAttrCache::SetNumFormat(): sollte nicht Plain sein!" );
960 
961 	if( !ppCols[ nCol ] )
962 		ppCols[ nCol ] = new DifColumn;
963 
964 	ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
965 }
966 
967 
Apply(ScDocument & rDoc,SCTAB nTab)968 void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
969 {
970 	if( bPlain )
971 	{
972 		ScPatternAttr*	pPatt = NULL;
973 
974 		for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
975 		{
976 			if( ppCols[ nCol ] )
977 			{
978 				if( !pPatt )
979 				{
980 					pPatt = new ScPatternAttr( rDoc.GetPool() );
981 					pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
982 						rDoc.GetFormatTable()->GetStandardFormat( NUMBERFORMAT_LOGICAL ) ) );
983 				}
984 
985 				ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
986 			}
987 		}
988 
989 		if( pPatt )
990 			delete pPatt;
991 	}
992 	else
993 	{
994 		for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
995 		{
996 			if( ppCols[ nCol ] )
997 				ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
998 		}
999 	}
1000 }
1001 
1002 
1003 
1004