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
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