xref: /AOO41X/main/sc/source/filter/dif/difimp.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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