LCOV - code coverage report
Current view: top level - sc/source/filter/dif - difimp.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 228 420 54.3 %
Date: 2014-11-03 Functions: 18 23 78.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10