LCOV - code coverage report
Current view: top level - sc/source/filter/dif - difimp.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 227 419 54.2 %
Date: 2015-06-13 12:38:46 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 <osl/diagnose.h>
      24             : #include "attrib.hxx"
      25             : #include "dif.hxx"
      26             : #include "docpool.hxx"
      27             : #include "document.hxx"
      28             : #include "filter.hxx"
      29             : #include "fprogressbar.hxx"
      30             : #include "ftools.hxx"
      31             : #include "patattr.hxx"
      32             : #include "scerrors.hxx"
      33             : #include "scitems.hxx"
      34             : #include "stringutil.hxx"
      35             : #include <boost/scoped_ptr.hpp>
      36             : 
      37             : const sal_Unicode pKeyTABLE[]   = { 'T', 'A', 'B', 'L', 'E', 0 };
      38             : const sal_Unicode pKeyVECTORS[] = { 'V', 'E', 'C', 'T', 'O', 'R', 'S', 0 };
      39             : const sal_Unicode pKeyTUPLES[]  = { 'T', 'U', 'P', 'L', 'E', 'S', 0 };
      40             : const sal_Unicode pKeyDATA[]    = { 'D', 'A', 'T', 'A', 0 };
      41             : const sal_Unicode pKeyBOT[]     = { 'B', 'O', 'T', 0 };
      42             : const sal_Unicode pKeyEOD[]     = { 'E', 'O', 'D', 0 };
      43             : const sal_Unicode pKeyERROR[]   = { 'E', 'R', 'R', 'O', 'R', 0 };
      44             : const sal_Unicode pKeyTRUE[]    = { 'T', 'R', 'U', 'E', 0 };
      45             : const sal_Unicode pKeyFALSE[]   = { 'F', 'A', 'L', 'S', 'E', 0 };
      46             : const sal_Unicode pKeyNA[]      = { 'N', 'A', 0 };
      47             : const sal_Unicode pKeyV[]       = { 'V', 0 };
      48             : const sal_Unicode pKey1_0[]     = { '1', ',', '0', 0 };
      49             : 
      50           1 : FltError ScFormatFilterPluginImpl::ScImportDif( SvStream& rIn, ScDocument* pDoc, const ScAddress& rInsPos,
      51             :                         const rtl_TextEncoding eVon, sal_uInt32 nDifOption )
      52             : {
      53           1 :     DifParser   aDifParser( rIn, nDifOption, *pDoc, eVon );
      54             : 
      55           1 :     const bool bPlain = aDifParser.IsPlain();
      56             : 
      57           1 :     SCTAB       nBaseTab = rInsPos.Tab();
      58             : 
      59           1 :     TOPIC       eTopic = T_UNKNOWN;
      60           1 :     bool        bSyntErrWarn = false;
      61           1 :     bool        bOverflowWarn = false;
      62             : 
      63           1 :     OUString&   aData = aDifParser.aData;
      64             : 
      65           1 :     rIn.Seek( 0 );
      66             : 
      67           2 :     ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
      68             : 
      69           6 :     while( eTopic != T_DATA && eTopic != T_END )
      70             :     {
      71           4 :         eTopic = aDifParser.GetNextTopic();
      72             : 
      73           4 :         aPrgrsBar.Progress();
      74             : 
      75           4 :         const bool bData = !aData.isEmpty();
      76             : 
      77           4 :         switch( eTopic )
      78             :         {
      79             :             case T_TABLE:
      80             :             {
      81           1 :                 if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
      82           0 :                     bSyntErrWarn = true;
      83           1 :                 if( bData )
      84           1 :                     pDoc->RenameTab( nBaseTab, aData );
      85             :             }
      86           1 :                 break;
      87             :             case T_VECTORS:
      88             :             {
      89           1 :                 if( aDifParser.nVector != 0 )
      90           0 :                     bSyntErrWarn = true;
      91             :             }
      92           1 :                 break;
      93             :             case T_TUPLES:
      94             :             {
      95           1 :                 if( aDifParser.nVector != 0 )
      96           0 :                     bSyntErrWarn = true;
      97             :             }
      98           1 :                 break;
      99             :             case T_DATA:
     100             :             {
     101           1 :                 if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
     102           0 :                     bSyntErrWarn = true;
     103             :             }
     104           1 :                 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           1 :     if( eTopic == T_DATA )
     124             :     {   // data starts here
     125           1 :         SCCOL               nBaseCol = rInsPos.Col();
     126             : 
     127           1 :         SCCOL               nColCnt = SCCOL_MAX;
     128           1 :         SCROW               nRowCnt = rInsPos.Row();
     129           1 :         DifAttrCache        aAttrCache( bPlain );
     130             : 
     131           1 :         DATASET             eAkt = D_UNKNOWN;
     132             : 
     133           1 :         ScSetStringParam aStrParam; // used to set string value without number detection.
     134           1 :         aStrParam.setTextInput();
     135             : 
     136          39 :         while( eAkt != D_EOD )
     137             :         {
     138          37 :             eAkt = aDifParser.GetNextDataset();
     139             : 
     140          37 :             aPrgrsBar.Progress();
     141          37 :             ScAddress aPos(nColCnt, nRowCnt, nBaseTab);
     142             : 
     143          37 :             switch( eAkt )
     144             :             {
     145             :                 case D_BOT:
     146           4 :                     if( nColCnt < SCCOL_MAX )
     147           3 :                         nRowCnt++;
     148           4 :                     nColCnt = nBaseCol;
     149           4 :                     break;
     150             :                 case D_EOD:
     151           1 :                     break;
     152             :                 case D_NUMERIC:                 // Number cell
     153           6 :                     if( nColCnt == SCCOL_MAX )
     154           0 :                         nColCnt = nBaseCol;
     155             : 
     156           6 :                     if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
     157             :                     {
     158           6 :                         pDoc->EnsureTable(nBaseTab);
     159             : 
     160           6 :                         if( DifParser::IsV( aData.getStr() ) )
     161             :                         {
     162           6 :                             pDoc->SetValue(aPos, aDifParser.fVal);
     163           6 :                             if( !bPlain )
     164             :                                 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
     165           6 :                                     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           6 :                     nColCnt++;
     190           6 :                     break;
     191             :                 case D_STRING:                  // Text cell
     192          26 :                     if( nColCnt == SCCOL_MAX )
     193           0 :                         nColCnt = nBaseCol;
     194             : 
     195          26 :                     if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
     196             :                     {
     197          26 :                         if (!aData.isEmpty())
     198             :                         {
     199           2 :                             pDoc->EnsureTable(nBaseTab);
     200           2 :                             pDoc->SetTextCell(aPos, aData);
     201             :                         }
     202             :                     }
     203             :                     else
     204           0 :                         bOverflowWarn = true;
     205             : 
     206          26 :                     nColCnt++;
     207          26 :                     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           1 :         aAttrCache.Apply( *pDoc, nBaseTab );
     218             :     }
     219             :     else
     220           0 :         return eERR_FORMAT;
     221             : 
     222           1 :     if( bSyntErrWarn )
     223             : 
     224             :         // FIXME: Add proper Warnung!
     225           0 :         return eERR_RNGOVRFLW;
     226             : 
     227           1 :     else if( bOverflowWarn )
     228           0 :         return eERR_RNGOVRFLW;
     229             :     else
     230           2 :         return eERR_OK;
     231             : }
     232             : 
     233           1 : 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           1 :     , rIn(rNewIn)
     240             : {
     241           1 :     if ( rIn.GetStreamCharSet() != eCharSet )
     242             :     {
     243             :         OSL_FAIL( "CharSet passed overrides and modifies StreamCharSet" );
     244           1 :         rIn.SetStreamCharSet( eCharSet );
     245             :     }
     246           1 :     rIn.StartReadingUnicodeText( eCharSet );
     247             : 
     248           1 :     bPlain = ( nOption == SC_DIFOPT_PLAIN );
     249             : 
     250           1 :     if( bPlain )
     251           0 :         pNumFormatter = NULL;
     252             :     else
     253           1 :         pNumFormatter = rDoc.GetFormatTable();
     254           1 : }
     255             : 
     256           4 : TOPIC DifParser::GetNextTopic()
     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           4 :     STATE                   eS = S_START;
     308           4 :     OUString           aLine;
     309             : 
     310           4 :     nVector = 0;
     311           4 :     nVal = 0;
     312           4 :     TOPIC eRet = T_UNKNOWN;
     313             : 
     314          20 :     while( eS != S_END )
     315             :     {
     316          12 :         if( !ReadNextLine( aLine ) )
     317             :         {
     318           0 :             eS = S_END;
     319           0 :             eRet = T_END;
     320             :         }
     321             : 
     322          12 :         switch( eS )
     323             :         {
     324             :             case S_START:
     325             :             {
     326             :                 const sal_Unicode*  pRef;
     327           4 :                 sal_uInt16          nCnt = 0;
     328           4 :                 bool            bSearch = true;
     329             : 
     330           4 :                 pRef = ppKeys[ nCnt ];
     331             : 
     332          18 :                 while( bSearch )
     333             :                 {
     334          10 :                     if( aLine == pRef )
     335             :                     {
     336           4 :                         eRet = pTopics[ nCnt ];
     337           4 :                         bSearch = false;
     338             :                     }
     339             :                     else
     340             :                     {
     341           6 :                         nCnt++;
     342           6 :                         pRef = ppKeys[ nCnt ];
     343           6 :                         if( !*pRef )
     344           0 :                             bSearch = false;
     345             :                     }
     346             :                 }
     347             : 
     348           4 :                 if( *pRef )
     349           4 :                     eS = S_VectorVal;
     350             :                 else
     351           0 :                     eS = S_UNKNOWN;
     352             :             }
     353           4 :                 break;
     354             :             case S_VectorVal:
     355             :             {
     356           4 :                 const sal_Unicode*      pCur = aLine.getStr();
     357             : 
     358           4 :                 pCur = ScanIntVal( pCur, nVector );
     359             : 
     360           4 :                 if( pCur && *pCur == ',' )
     361             :                 {
     362           4 :                     pCur++;
     363           4 :                     ScanIntVal( pCur, nVal );
     364           4 :                     eS = S_Data;
     365             :                 }
     366             :                 else
     367           0 :                     eS = S_ERROR_L2;
     368             :             }
     369           4 :                 break;
     370             :             case S_Data:
     371             :                 OSL_ENSURE( aLine.getLength() >= 2,
     372             :                     "+GetNextTopic(): <String> is too short!" );
     373           4 :                 if( aLine.getLength() > 2 )
     374           1 :                     aData = aLine.copy( 1, aLine.getLength() - 2 );
     375             :                 else
     376           3 :                     aData.clear();
     377           4 :                 eS = S_END;
     378           4 :                 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           4 :     return eRet;
     397             : }
     398             : 
     399          26 : 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          26 :     rString = rString.replaceAll("\"\"", "\"");
     407          26 : }
     408             : 
     409             : // Determine if passed in string is numeric data and set fVal/nNumFormat if so
     410          10 : DATASET DifParser::GetNumberDataset( const sal_Unicode* pPossibleNumericData )
     411             : {
     412          10 :     DATASET eRet = D_SYNT_ERROR;
     413          10 :     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          10 :         OUString aTestVal( pPossibleNumericData );
     424          10 :         sal_uInt32 nFormat = 0;
     425             :         double fTmpVal;
     426          10 :         if( pNumFormatter->IsNumberFormat( aTestVal, nFormat, fTmpVal ) )
     427             :         {
     428          10 :             fVal = fTmpVal;
     429          10 :             nNumFormat = nFormat;
     430          10 :             eRet = D_NUMERIC;
     431             :         }
     432             :         else
     433           0 :             eRet = D_SYNT_ERROR;
     434             :     }
     435          10 :     return eRet;
     436             : }
     437             : 
     438          86 : bool DifParser::ReadNextLine( OUString& rStr )
     439             : {
     440          86 :     if( aLookAheadLine.isEmpty() )
     441             :     {
     442          60 :         return rIn.ReadUniOrByteStringLine( rStr, rIn.GetStreamCharSet() );
     443             :     }
     444             :     else
     445             :     {
     446          26 :         rStr = aLookAheadLine;
     447          26 :         aLookAheadLine.clear();
     448          26 :         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          26 : bool DifParser::LookAhead()
     455             : {
     456             :     const sal_Unicode* pAktBuffer;
     457          26 :     bool bValidStructure = false;
     458             : 
     459             :     OSL_ENSURE( aLookAheadLine.isEmpty(), "*DifParser::LookAhead(): LookAhead called twice in a row" );
     460          26 :     rIn.ReadUniOrByteStringLine( aLookAheadLine, rIn.GetStreamCharSet() );
     461             : 
     462          26 :     pAktBuffer = aLookAheadLine.getStr();
     463             : 
     464          26 :     switch( *pAktBuffer )
     465             :     {
     466             :         case '-':                   // Special Datatype
     467           4 :             pAktBuffer++;
     468             : 
     469           4 :             if( Is1_0( pAktBuffer ) )
     470             :             {
     471           4 :                 bValidStructure = true;
     472             :             }
     473           4 :             break;
     474             :         case '0':                   // Numeric Data
     475           4 :             pAktBuffer++;
     476           4 :             if( *pAktBuffer == ',' )
     477             :             {
     478           4 :                 pAktBuffer++;
     479           4 :                 bValidStructure = ( GetNumberDataset(pAktBuffer) != D_SYNT_ERROR );
     480             :             }
     481           4 :             break;
     482             :         case '1':                   // String Data
     483          18 :             if( Is1_0( aLookAheadLine.getStr() ) )
     484             :             {
     485          18 :                 bValidStructure = true;
     486             :             }
     487          18 :             break;
     488             :     }
     489          26 :     return bValidStructure;
     490             : }
     491             : 
     492          37 : DATASET DifParser::GetNextDataset()
     493             : {
     494          37 :     DATASET eRet = D_UNKNOWN;
     495          37 :     OUString aLine;
     496             :     const sal_Unicode* pAktBuffer;
     497             : 
     498          37 :     ReadNextLine( aLine );
     499             : 
     500          37 :     pAktBuffer = aLine.getStr();
     501             : 
     502          37 :     switch( *pAktBuffer )
     503             :     {
     504             :         case '-':                   // Special Datatype
     505           5 :             pAktBuffer++;
     506             : 
     507           5 :             if( Is1_0( pAktBuffer ) )
     508             :             {
     509           5 :                 ReadNextLine( aLine );
     510           5 :                 if( IsBOT( aLine.getStr() ) )
     511           4 :                     eRet = D_BOT;
     512           1 :                 else if( IsEOD( aLine.getStr() ) )
     513           1 :                     eRet = D_EOD;
     514             :             }
     515           5 :             break;
     516             :         case '0':                   // Numeric Data
     517           6 :             pAktBuffer++;           // value in fVal, 2. line in aData
     518           6 :             if( *pAktBuffer == ',' )
     519             :             {
     520           6 :                 pAktBuffer++;
     521           6 :                 eRet = GetNumberDataset(pAktBuffer);
     522           6 :                 OUString aTmpLine;
     523           6 :                 ReadNextLine( aTmpLine );
     524           6 :                 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           6 :                     aData = aTmpLine;
     535           6 :                 }
     536             :             }
     537           6 :             break;
     538             :         case '1':                   // String Data
     539          26 :             if( Is1_0( aLine.getStr() ) )
     540             :             {
     541          26 :                 ReadNextLine( aLine );
     542          26 :                 sal_Int32 nLineLength = aLine.getLength();
     543          26 :                 const sal_Unicode* pLine = aLine.getStr();
     544             : 
     545          26 :                 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          26 :                     if( LookAhead() )
     551             :                     {
     552             :                         // Single line string
     553          26 :                         if( nLineLength >= 2 && pLine[nLineLength - 1] == '"' )
     554             :                         {
     555          26 :                             aData = aLine.copy( 1, nLineLength - 2 );
     556          26 :                             lcl_DeEscapeQuotesDif( aData );
     557          26 :                             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          26 :             break;
     593             :     }
     594             : 
     595          37 :     if( eRet == D_UNKNOWN )
     596           0 :         ReadNextLine( aLine );
     597             : 
     598          37 :     if( rIn.IsEof() )
     599           0 :         eRet = D_EOD;
     600             : 
     601          37 :     return eRet;
     602             : }
     603             : 
     604           8 : 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          16 :     while (*pStart == ' ' || *pStart == '\t')
     608           0 :         ++pStart;
     609             : 
     610           8 :     sal_Unicode     cAkt = *pStart;
     611             : 
     612           8 :     if( IsNumber( cAkt ) )
     613           8 :         rRet = ( sal_uInt32 ) ( cAkt - '0' );
     614             :     else
     615           0 :         return NULL;
     616             : 
     617           8 :     pStart++;
     618           8 :     cAkt = *pStart;
     619             : 
     620          16 :     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           8 :     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           2 : DifColumn::DifColumn ()
     810           2 :     : pAkt(NULL)
     811             : {
     812           2 : }
     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           6 : void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
     839             : {
     840             :     OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row too big!" );
     841             : 
     842           6 :     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           6 :         pAkt = NULL;
     861           6 : }
     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           2 : void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
     879             : {
     880           2 :     ScPatternAttr aAttr( rDoc.GetPool() );
     881           2 :     SfxItemSet &rItemSet = aAttr.GetItemSet();
     882             : 
     883           2 :     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           2 :     }
     894           2 : }
     895             : 
     896           1 : DifAttrCache::DifAttrCache( const bool bNewPlain )
     897             : {
     898           1 :     bPlain = bNewPlain;
     899           1 :     ppCols = new DifColumn *[ MAXCOL + 1 ];
     900        1025 :     for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
     901        1024 :         ppCols[ nCnt ] = NULL;
     902           1 : }
     903             : 
     904           1 : DifAttrCache::~DifAttrCache()
     905             : {
     906        1025 :     for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
     907             :     {
     908        1024 :         if( ppCols[ nCnt ] )
     909           2 :             delete ppCols[ nCnt ];
     910             :     }
     911             : 
     912           1 :     delete[] ppCols;
     913           1 : }
     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           6 : 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           6 :     if( !ppCols[ nCol ] )
     932           2 :         ppCols[ nCol ] = new DifColumn;
     933             : 
     934           6 :     ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
     935           6 : }
     936             : 
     937           1 : void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
     938             : {
     939           1 :     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( css::util::NumberFormat::LOGICAL ) ) );
     952             :                 }
     953             : 
     954           0 :                 ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
     955             :             }
     956           0 :         }
     957             :     }
     958             :     else
     959             :     {
     960        1025 :         for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
     961             :         {
     962        1024 :             if( ppCols[ nCol ] )
     963           2 :                 ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
     964             :         }
     965             :     }
     966          31 : }
     967             : 
     968             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11