LCOV - code coverage report
Current view: top level - sc/source/filter/dif - difimp.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 229 422 54.3 %
Date: 2014-04-11 Functions: 16 21 76.2 %
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             : 
      21             : #include <math.h>
      22             : 
      23             : #include <svl/zforlist.hxx>
      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             : 
      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             : 
      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           1 :     bool        bData = false;
      65             : 
      66           1 :     rIn.Seek( 0 );
      67             : 
      68           2 :     ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
      69             : 
      70           6 :     while( eTopic != T_DATA && eTopic != T_END )
      71             :     {
      72           4 :         eTopic = aDifParser.GetNextTopic();
      73             : 
      74           4 :         aPrgrsBar.Progress();
      75             : 
      76           4 :         bData = !aData.isEmpty();
      77             : 
      78           4 :         switch( eTopic )
      79             :         {
      80             :             case T_TABLE:
      81             :             {
      82           1 :                 if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
      83           0 :                     bSyntErrWarn = true;
      84           1 :                 if( bData )
      85           1 :                     pDoc->RenameTab( nBaseTab, aData );
      86             :             }
      87           1 :                 break;
      88             :             case T_VECTORS:
      89             :             {
      90           1 :                 if( aDifParser.nVector != 0 )
      91           0 :                     bSyntErrWarn = true;
      92             :             }
      93           1 :                 break;
      94             :             case T_TUPLES:
      95             :             {
      96           1 :                 if( aDifParser.nVector != 0 )
      97           0 :                     bSyntErrWarn = true;
      98             :             }
      99           1 :                 break;
     100             :             case T_DATA:
     101             :             {
     102           1 :                 if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
     103           0 :                     bSyntErrWarn = true;
     104             :             }
     105           1 :                 break;
     106             :             case T_LABEL:
     107             :             case T_COMMENT:
     108             :             case T_SIZE:
     109             :             case T_PERIODICITY:
     110             :             case T_MAJORSTART:
     111             :             case T_MINORSTART:
     112             :             case T_TRUELENGTH:
     113             :             case T_UINITS:
     114             :             case T_DISPLAYUNITS:
     115             :             case T_END:
     116             :             case T_UNKNOWN:
     117           0 :                 break;
     118             :             default:
     119             :                 OSL_FAIL( "ScImportDif - missing enum" );
     120             :         }
     121             : 
     122             :     }
     123             : 
     124             : 
     125           1 :     if( eTopic == T_DATA )
     126             :     {   // Ab hier kommen die Daten
     127           1 :         SCCOL               nBaseCol = rInsPos.Col();
     128             : 
     129           1 :         SCCOL               nColCnt = SCCOL_MAX;
     130           1 :         SCROW               nRowCnt = rInsPos.Row();
     131           1 :         DifAttrCache        aAttrCache( bPlain );
     132             : 
     133           1 :         DATASET             eAkt = D_UNKNOWN;
     134             : 
     135           1 :         ScSetStringParam aStrParam; // used to set string value without number detection.
     136           1 :         aStrParam.setTextInput();
     137             : 
     138          39 :         while( eAkt != D_EOD )
     139             :         {
     140          37 :             eAkt = aDifParser.GetNextDataset();
     141             : 
     142          37 :             aPrgrsBar.Progress();
     143          37 :             ScAddress aPos(nColCnt, nRowCnt, nBaseTab);
     144             : 
     145          37 :             switch( eAkt )
     146             :             {
     147             :                 case D_BOT:
     148           4 :                     if( nColCnt < SCCOL_MAX )
     149           3 :                         nRowCnt++;
     150           4 :                     nColCnt = nBaseCol;
     151           4 :                     break;
     152             :                 case D_EOD:
     153           1 :                     break;
     154             :                 case D_NUMERIC:                 // Numbercell
     155           6 :                     if( nColCnt == SCCOL_MAX )
     156           0 :                         nColCnt = nBaseCol;
     157             : 
     158           6 :                     if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
     159             :                     {
     160           6 :                         pDoc->EnsureTable(nBaseTab);
     161             : 
     162           6 :                         if( DifParser::IsV( aData.getStr() ) )
     163             :                         {
     164           6 :                             pDoc->SetValue(aPos, aDifParser.fVal);
     165           6 :                             if( !bPlain )
     166             :                                 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
     167           6 :                                     aDifParser.nNumFormat );
     168             :                         }
     169           0 :                         else if( aData == pKeyTRUE || aData == pKeyFALSE )
     170             :                         {
     171           0 :                             pDoc->SetValue(aPos, aDifParser.fVal);
     172           0 :                             if( bPlain )
     173           0 :                                 aAttrCache.SetLogical( nColCnt, nRowCnt );
     174             :                             else
     175             :                                 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
     176           0 :                                     aDifParser.nNumFormat );
     177             :                         }
     178           0 :                         else if( aData == pKeyNA || aData == pKeyERROR  )
     179             :                         {
     180           0 :                             pDoc->SetString(aPos, aData, &aStrParam);
     181             :                         }
     182             :                         else
     183             :                         {
     184           0 :                             OUString aTmp = "#IND:" + aData + "?";
     185           0 :                             pDoc->SetString(aPos, aTmp, &aStrParam);
     186             :                         }
     187             :                     }
     188             :                     else
     189           0 :                         bOverflowWarn = true;
     190             : 
     191           6 :                     nColCnt++;
     192           6 :                     break;
     193             :                 case D_STRING:                  // Textcell
     194          26 :                     if( nColCnt == SCCOL_MAX )
     195           0 :                         nColCnt = nBaseCol;
     196             : 
     197          26 :                     if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
     198             :                     {
     199          26 :                         if (!aData.isEmpty())
     200             :                         {
     201           2 :                             pDoc->EnsureTable(nBaseTab);
     202           2 :                             pDoc->SetTextCell(aPos, aData);
     203             :                         }
     204             :                     }
     205             :                     else
     206           0 :                         bOverflowWarn = true;
     207             : 
     208          26 :                     nColCnt++;
     209          26 :                     break;
     210             :                 case D_UNKNOWN:
     211           0 :                     break;
     212             :                 case D_SYNT_ERROR:
     213           0 :                     break;
     214             :                 default:
     215             :                     OSL_FAIL( "ScImportDif - missing enum" );
     216             :             }
     217             :         }
     218             : 
     219           1 :         aAttrCache.Apply( *pDoc, nBaseTab );
     220             :     }
     221             :     else
     222           0 :         return eERR_FORMAT;
     223             : 
     224           1 :     if( bSyntErrWarn )
     225             : 
     226             :         // ACHTUNG: Hier fehlt noch die richtige Warnung!
     227           0 :         return eERR_RNGOVRFLW;
     228             : 
     229           1 :     else if( bOverflowWarn )
     230           0 :         return eERR_RNGOVRFLW;
     231             :     else
     232           2 :         return eERR_OK;
     233             : }
     234             : 
     235             : 
     236           1 : DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, rtl_TextEncoding e ) :
     237           1 :     rIn( rNewIn )
     238             : {
     239           1 :     eCharSet = e;
     240           1 :     if ( rIn.GetStreamCharSet() != eCharSet )
     241             :     {
     242             :         OSL_FAIL( "CharSet passed overrides and modifies StreamCharSet" );
     243           1 :         rIn.SetStreamCharSet( eCharSet );
     244             :     }
     245           1 :     rIn.StartReadingUnicodeText( eCharSet );
     246             : 
     247           1 :     bPlain = ( nOption == SC_DIFOPT_PLAIN );
     248             : 
     249           1 :     if( bPlain )
     250           0 :         pNumFormatter = NULL;
     251             :     else
     252           1 :         pNumFormatter = rDoc.GetFormatTable();
     253           1 : }
     254             : 
     255             : 
     256           4 : 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           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 :                 sal_Bool            bSearch = sal_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> ist zu kurz!" );
     373           4 :                 if( aLine.getLength() > 2 )
     374           1 :                     aData = aLine.copy( 1, aLine.getLength() - 2 );
     375             :                 else
     376           3 :                     aData = OUString();
     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             :                 // 2 Zeilen ueberlesen
     384           0 :                 ReadNextLine( aLine );
     385             :             case S_ERROR_L2:                // Fehler in Line 2 aufgetreten
     386             :                 // eine Zeile ueberlesen
     387           0 :                 ReadNextLine( aLine );
     388           0 :                 eS = S_END;
     389           0 :                 break;
     390             :             default:
     391             :                 OSL_FAIL( "DifParser::GetNextTopic - missing enum" );
     392             :         }
     393             :     }
     394             : 
     395           4 :     return eRet;
     396             : }
     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             :     {   // ...und zur Strafe mit'm Numberformatter...
     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 = OUString();
     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( void )
     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++;           // Wert in fVal, 2. Zeile 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             : 
     605           8 : const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
     606             : {
     607             :     // eat leading whitespace, not specified, but seen in the wild
     608          16 :     while (*pStart == ' ' || *pStart == '\t')
     609           0 :         ++pStart;
     610             : 
     611           8 :     sal_Unicode     cAkt = *pStart;
     612             : 
     613           8 :     if( IsNumber( cAkt ) )
     614           8 :         rRet = ( sal_uInt32 ) ( cAkt - '0' );
     615             :     else
     616           0 :         return NULL;
     617             : 
     618           8 :     pStart++;
     619           8 :     cAkt = *pStart;
     620             : 
     621          16 :     while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
     622             :     {
     623           0 :         rRet *= 10;
     624           0 :         rRet += ( sal_uInt32 ) ( cAkt - '0' );
     625             : 
     626           0 :         pStart++;
     627           0 :         cAkt = *pStart;
     628             :     }
     629             : 
     630           8 :     return pStart;
     631             : }
     632             : 
     633             : 
     634           0 : bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
     635             : {
     636           0 :     sal_Bool                    bNeg = false;
     637           0 :     double                      fFracPos = 1.0;
     638           0 :     sal_Int32                   nExp = 0;
     639           0 :     sal_Bool                    bExpNeg = false;
     640           0 :     sal_Bool                    bExpOverflow = false;
     641             :     static const sal_uInt16     nExpLimit = 4096;   // ACHTUNG: muss genauer ermittelt werden!
     642             : 
     643             :     sal_Unicode             cAkt;
     644           0 :     bool                    bRet = false;
     645             : 
     646             :     enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
     647             : 
     648           0 :     STATE   eS = S_FIRST;
     649             : 
     650           0 :     double fNewVal = 0.0;
     651             : 
     652           0 :     while( eS != S_END )
     653             :     {
     654           0 :         cAkt = *pStart;
     655           0 :         switch( eS )
     656             :         {
     657             :             case S_FIRST:
     658           0 :                 if( IsNumber( cAkt ) )
     659             :                 {
     660           0 :                     fNewVal *= 10;
     661           0 :                     fNewVal += cAkt - '0';
     662           0 :                     eS = S_PRE;
     663             :                 }
     664             :                 else
     665             :                 {
     666           0 :                     switch( cAkt )
     667             :                     {
     668             :                         case ' ':
     669             :                         case '\t':
     670             :                         case '+':
     671           0 :                             break;
     672             :                         case '-':
     673           0 :                             bNeg = !bNeg;
     674           0 :                             break;
     675             :                         case '.':
     676             :                         case ',':                   //!
     677           0 :                             eS = S_POST;
     678           0 :                             fFracPos = 0.1;
     679           0 :                             break;
     680             :                         default:
     681           0 :                             eS = S_END;
     682             :                     }
     683             :                 }
     684           0 :                 break;
     685             :             case S_PRE:
     686           0 :                 if( IsNumber( cAkt ) )
     687             :                 {
     688           0 :                     fNewVal *= 10;
     689           0 :                     fNewVal += cAkt - '0';
     690             :                 }
     691             :                 else
     692             :                 {
     693           0 :                     switch( cAkt )
     694             :                     {
     695             :                         case '.':
     696             :                         case ',':                   //!
     697           0 :                             eS = S_POST;
     698           0 :                             fFracPos = 0.1;
     699           0 :                             break;
     700             :                         case 'e':
     701             :                         case 'E':
     702           0 :                             eS = S_EXP;
     703           0 :                             break;
     704             :                         case 0x00:              // IsNumberEnding( cAkt )
     705           0 :                             bRet = true;        // no
     706             :                         default:                // break!
     707           0 :                             eS = S_END;
     708             :                     }
     709             :                 }
     710           0 :                 break;
     711             :             case S_POST:
     712           0 :                 if( IsNumber( cAkt ) )
     713             :                 {
     714           0 :                     fNewVal += fFracPos * ( cAkt - '0' );
     715           0 :                     fFracPos /= 10.0;
     716             :                 }
     717             :                 else
     718             :                 {
     719           0 :                     switch( cAkt )
     720             :                     {
     721             :                         case 'e':
     722             :                         case 'E':
     723           0 :                             eS = S_EXP_FIRST;
     724           0 :                             break;
     725             :                         case 0x00:              // IsNumberEnding( cAkt )
     726           0 :                             bRet = true;        // no
     727             :                         default:                // break!
     728           0 :                             eS = S_END;
     729             :                     }
     730             :                 }
     731           0 :                 break;
     732             :             case S_EXP_FIRST:
     733           0 :                 if( IsNumber( cAkt ) )
     734             :                 {
     735           0 :                     if( nExp < nExpLimit )
     736             :                     {
     737           0 :                         nExp *= 10;
     738           0 :                         nExp += ( sal_uInt16 ) ( cAkt - '0' );
     739             :                     }
     740           0 :                     eS = S_EXP;
     741             :                 }
     742             :                 else
     743             :                 {
     744           0 :                     switch( cAkt )
     745             :                     {
     746             :                         case '+':
     747           0 :                             break;
     748             :                         case '-':
     749           0 :                             bExpNeg = !bExpNeg;
     750           0 :                             break;
     751             :                         default:
     752           0 :                             eS = S_END;
     753             :                     }
     754             :                 }
     755           0 :                 break;
     756             :             case S_EXP:
     757           0 :                 if( IsNumber( cAkt ) )
     758             :                 {
     759           0 :                     if( nExp < ( 0xFFFF / 10 ) )
     760             :                     {
     761           0 :                         nExp *= 10;
     762           0 :                         nExp += ( sal_uInt16 ) ( cAkt - '0' );
     763             :                     }
     764             :                     else
     765             :                     {
     766           0 :                         bExpOverflow = sal_True;
     767           0 :                         eS = S_FINDEND;
     768             :                     }
     769             :                 }
     770             :                 else
     771             :                 {
     772           0 :                     bRet = IsNumberEnding( cAkt );
     773           0 :                     eS = S_END;
     774             :                 }
     775           0 :                 break;
     776             :             case S_FINDEND:
     777           0 :                 if( IsNumberEnding( cAkt ) )
     778             :                 {
     779           0 :                     bRet = true;        // damit sinnvoll weitergeparst werden kann
     780           0 :                     eS = S_END;
     781             :                 }
     782           0 :                 break;
     783             :             case S_END:
     784             :                 OSL_FAIL( "DifParser::ScanFloatVal - unexpected state" );
     785           0 :                 break;
     786             :             default:
     787             :                 OSL_FAIL( "DifParser::ScanFloatVal - missing enum" );
     788             :         }
     789           0 :         pStart++;
     790             :     }
     791             : 
     792           0 :     if( bRet )
     793             :     {
     794           0 :         if( bExpOverflow )
     795           0 :             return false;       // ACHTUNG: hier muss noch differenziert werden
     796             : 
     797           0 :         if( bNeg )
     798           0 :             fNewVal *= 1.0;
     799             : 
     800           0 :         if( bExpNeg )
     801           0 :             nExp *= -1;
     802             : 
     803           0 :         if( nExp != 0 )
     804           0 :             fNewVal *= pow( 10.0, ( double ) nExp );
     805           0 :         fVal = fNewVal;
     806             :     }
     807             : 
     808           0 :     return bRet;
     809             : }
     810             : 
     811           2 : DifColumn::DifColumn ()
     812           2 :     : pAkt(NULL)
     813             : {
     814           2 : }
     815             : 
     816           0 : void DifColumn::SetLogical( SCROW nRow )
     817             : {
     818             :     OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetLogical(): Row too big!" );
     819             : 
     820           0 :     if( pAkt )
     821             :     {
     822             :         OSL_ENSURE( nRow > 0, "*DifColumn::SetLogical(): more cannot be zero!" );
     823             : 
     824           0 :         nRow--;
     825             : 
     826           0 :         if( pAkt->nEnd == nRow )
     827           0 :             pAkt->nEnd++;
     828             :         else
     829           0 :             pAkt = NULL;
     830             :     }
     831             :     else
     832             :     {
     833           0 :         pAkt = new ENTRY;
     834           0 :         pAkt->nStart = pAkt->nEnd = nRow;
     835             : 
     836           0 :         aEntries.push_back(pAkt);
     837             :     }
     838           0 : }
     839             : 
     840             : 
     841           6 : void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
     842             : {
     843             :     OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row too big!" );
     844             : 
     845           6 :     if( nNumFormat > 0 )
     846             :     {
     847           0 :         if(pAkt)
     848             :         {
     849             :             OSL_ENSURE( nRow > 0,
     850             :                 "*DifColumn::SetNumFormat(): more cannot be zero!" );
     851             :             OSL_ENSURE( nRow > pAkt->nEnd,
     852             :                 "*DifColumn::SetNumFormat(): start from scratch?" );
     853             : 
     854           0 :             if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
     855           0 :                 pAkt->nEnd = nRow;
     856             :             else
     857           0 :                 NewEntry( nRow, nNumFormat );
     858             :         }
     859             :         else
     860           0 :             NewEntry(nRow,nNumFormat );
     861             :     }
     862             :     else
     863           6 :         pAkt = NULL;
     864           6 : }
     865             : 
     866             : 
     867           0 : void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
     868             : {
     869           0 :     pAkt = new ENTRY;
     870           0 :     pAkt->nStart = pAkt->nEnd = nPos;
     871           0 :     pAkt->nNumFormat = nNumFormat;
     872             : 
     873           0 :     aEntries.push_back(pAkt);
     874           0 : }
     875             : 
     876             : 
     877           0 : void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
     878             : {
     879           0 :     for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
     880           0 :         rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, rPattAttr );
     881           0 : }
     882             : 
     883             : 
     884           2 : void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
     885             : {
     886           2 :     ScPatternAttr aAttr( rDoc.GetPool() );
     887           2 :     SfxItemSet &rItemSet = aAttr.GetItemSet();
     888             : 
     889           2 :     for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
     890             :     {
     891             :         OSL_ENSURE( it->nNumFormat > 0,
     892             :             "+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
     893             : 
     894           0 :         rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, it->nNumFormat ) );
     895             : 
     896           0 :         rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, aAttr );
     897             : 
     898           0 :         rItemSet.ClearItem();
     899           2 :     }
     900           2 : }
     901             : 
     902             : 
     903           1 : DifAttrCache::DifAttrCache( const bool bNewPlain )
     904             : {
     905           1 :     bPlain = bNewPlain;
     906           1 :     ppCols = new DifColumn *[ MAXCOL + 1 ];
     907        1025 :     for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
     908        1024 :         ppCols[ nCnt ] = NULL;
     909           1 : }
     910             : 
     911             : 
     912           1 : DifAttrCache::~DifAttrCache()
     913             : {
     914        1025 :     for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
     915             :     {
     916        1024 :         if( ppCols[ nCnt ] )
     917           2 :             delete ppCols[ nCnt ];
     918             :     }
     919             : 
     920           1 :     delete[] ppCols;
     921           1 : }
     922             : 
     923           0 : void DifAttrCache::SetLogical( const SCCOL nCol, const SCROW nRow )
     924             : {
     925             :     OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetLogical(): Col too big!" );
     926             :     OSL_ENSURE( bPlain, "*DifAttrCache::SetLogical(): has to be Plain!" );
     927             : 
     928           0 :     if( !ppCols[ nCol ] )
     929           0 :         ppCols[ nCol ] = new DifColumn;
     930             : 
     931           0 :     ppCols[ nCol ]->SetLogical( nRow );
     932           0 : }
     933             : 
     934           6 : void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
     935             : {
     936             :     OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col too big!" );
     937             :     OSL_ENSURE( !bPlain, "*DifAttrCache::SetNumFormat(): should not be Plain!" );
     938             : 
     939           6 :     if( !ppCols[ nCol ] )
     940           2 :         ppCols[ nCol ] = new DifColumn;
     941             : 
     942           6 :     ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
     943           6 : }
     944             : 
     945             : 
     946           1 : void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
     947             : {
     948           1 :     if( bPlain )
     949             :     {
     950           0 :         ScPatternAttr*  pPatt = NULL;
     951             : 
     952           0 :         for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
     953             :         {
     954           0 :             if( ppCols[ nCol ] )
     955             :             {
     956           0 :                 if( !pPatt )
     957             :                 {
     958           0 :                     pPatt = new ScPatternAttr( rDoc.GetPool() );
     959           0 :                     pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
     960           0 :                         rDoc.GetFormatTable()->GetStandardFormat( NUMBERFORMAT_LOGICAL ) ) );
     961             :                 }
     962             : 
     963           0 :                 ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
     964             :             }
     965             :         }
     966             : 
     967           0 :         if( pPatt )
     968           0 :             delete pPatt;
     969             :     }
     970             :     else
     971             :     {
     972        1025 :         for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
     973             :         {
     974        1024 :             if( ppCols[ nCol ] )
     975           2 :                 ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
     976             :         }
     977             :     }
     978           1 : }
     979             : 
     980             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10