summaryrefslogtreecommitdiff
path: root/sc/source/filter/dif/difimp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/dif/difimp.cxx')
-rw-r--r--sc/source/filter/dif/difimp.cxx994
1 files changed, 994 insertions, 0 deletions
diff --git a/sc/source/filter/dif/difimp.cxx b/sc/source/filter/dif/difimp.cxx
new file mode 100644
index 000000000000..18d0c532fff9
--- /dev/null
+++ b/sc/source/filter/dif/difimp.cxx
@@ -0,0 +1,994 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#include <math.h>
+
+#include <svl/zforlist.hxx>
+#include <tools/debug.hxx>
+
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "dif.hxx"
+#include "docpool.hxx"
+#include "document.hxx"
+#include "filter.hxx"
+#include "fprogressbar.hxx"
+#include "ftools.hxx"
+#include "patattr.hxx"
+#include "scerrors.hxx"
+#include "scitems.hxx"
+
+const sal_Unicode pKeyTABLE[] = { 'T', 'A', 'B', 'L', 'E', 0 };
+const sal_Unicode pKeyVECTORS[] = { 'V', 'E', 'C', 'T', 'O', 'R', 'S', 0 };
+const sal_Unicode pKeyTUPLES[] = { 'T', 'U', 'P', 'L', 'E', 'S', 0 };
+const sal_Unicode pKeyDATA[] = { 'D', 'A', 'T', 'A', 0 };
+const sal_Unicode pKeyBOT[] = { 'B', 'O', 'T', 0 };
+const sal_Unicode pKeyEOD[] = { 'E', 'O', 'D', 0 };
+const sal_Unicode pKeyERROR[] = { 'E', 'R', 'R', 'O', 'R', 0 };
+const sal_Unicode pKeyTRUE[] = { 'T', 'R', 'U', 'E', 0 };
+const sal_Unicode pKeyFALSE[] = { 'F', 'A', 'L', 'S', 'E', 0 };
+const sal_Unicode pKeyNA[] = { 'N', 'A', 0 };
+const sal_Unicode pKeyV[] = { 'V', 0 };
+const sal_Unicode pKey1_0[] = { '1', ',', '0', 0 };
+
+
+FltError ScFormatFilterPluginImpl::ScImportDif( SvStream& rIn, ScDocument* pDoc, const ScAddress& rInsPos,
+ const CharSet eVon, sal_uInt32 nDifOption )
+{
+ DifParser aDifParser( rIn, nDifOption, *pDoc, eVon );
+
+ const sal_Bool bPlain = aDifParser.IsPlain();
+
+ SCTAB nBaseTab = rInsPos.Tab();
+
+ TOPIC eTopic = T_UNKNOWN;
+ sal_Bool bSyntErrWarn = false;
+ sal_Bool bOverflowWarn = false;
+
+ String& rData = aDifParser.aData;
+ sal_Bool bData = false;
+
+ rIn.Seek( 0 );
+
+ ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
+
+ while( eTopic != T_DATA && eTopic != T_END )
+ {
+ eTopic = aDifParser.GetNextTopic();
+
+ aPrgrsBar.Progress();
+
+ bData = rData.Len() > 0;
+
+ switch( eTopic )
+ {
+ case T_TABLE:
+ {
+ if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
+ bSyntErrWarn = sal_True;
+ if( bData )
+ pDoc->RenameTab( nBaseTab, rData );
+ }
+ break;
+ case T_VECTORS:
+ {
+ if( aDifParser.nVector != 0 )
+ bSyntErrWarn = true;
+ }
+ break;
+ case T_TUPLES:
+ {
+ if( aDifParser.nVector != 0 )
+ bSyntErrWarn = true;
+ }
+ break;
+ case T_DATA:
+ {
+ if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
+ bSyntErrWarn = sal_True;
+ }
+ break;
+ case T_LABEL:
+ case T_COMMENT:
+ case T_SIZE:
+ case T_PERIODICITY:
+ case T_MAJORSTART:
+ case T_MINORSTART:
+ case T_TRUELENGTH:
+ case T_UINITS:
+ case T_DISPLAYUNITS:
+ case T_END:
+ case T_UNKNOWN:
+ break;
+ default:
+ DBG_ERRORFILE( "ScImportDif - missing enum" );
+ }
+
+ }
+
+
+ if( eTopic == T_DATA )
+ { // Ab hier kommen die Daten
+ SCCOL nBaseCol = rInsPos.Col();
+
+ SCCOL nColCnt = SCCOL_MAX;
+ SCROW nRowCnt = rInsPos.Row();
+ DifAttrCache aAttrCache( bPlain );
+
+ DATASET eAkt = D_UNKNOWN;
+
+ while( eAkt != D_EOD )
+ {
+ eAkt = aDifParser.GetNextDataset();
+
+ aPrgrsBar.Progress();
+
+ switch( eAkt )
+ {
+ case D_BOT:
+ if( nColCnt < SCCOL_MAX )
+ nRowCnt++;
+ nColCnt = nBaseCol;
+ break;
+ case D_EOD:
+ break;
+ case D_NUMERIC: // Numbercell
+ if( nColCnt == SCCOL_MAX )
+ nColCnt = nBaseCol;
+
+ if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
+ {
+ ScBaseCell* pCell;
+ if( DifParser::IsV( rData.GetBuffer() ) )
+ {
+ pCell = new ScValueCell( aDifParser.fVal );
+ if( !bPlain )
+ aAttrCache.SetNumFormat( nColCnt, nRowCnt,
+ aDifParser.nNumFormat );
+ }
+ else if( rData == pKeyTRUE || rData == pKeyFALSE )
+ {
+ pCell = new ScValueCell( aDifParser.fVal );
+ if( bPlain )
+ aAttrCache.SetLogical( nColCnt, nRowCnt );
+ else
+ aAttrCache.SetNumFormat( nColCnt, nRowCnt,
+ aDifParser.nNumFormat );
+ }
+ else if( rData == pKeyNA || rData == pKeyERROR )
+ pCell = new ScStringCell( rData );
+ else
+ {
+ String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#IND: " ));
+ aTmp += rData;
+ aTmp += sal_Unicode('?');
+ pCell = new ScStringCell( aTmp );
+ }
+
+ pDoc->PutCell( nColCnt, nRowCnt, nBaseTab, pCell, ( sal_Bool ) sal_True );
+ }
+ else
+ bOverflowWarn = sal_True;
+
+ nColCnt++;
+ break;
+ case D_STRING: // Textcell
+ if( nColCnt == SCCOL_MAX )
+ nColCnt = nBaseCol;
+
+ if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
+ {
+ if( rData.Len() > 0 )
+ {
+ pDoc->PutCell( nColCnt, nRowCnt, nBaseTab,
+ ScBaseCell::CreateTextCell( rData, pDoc ), ( sal_Bool ) sal_True );
+ }
+ }
+ else
+ bOverflowWarn = sal_True;
+
+ nColCnt++;
+ break;
+ case D_UNKNOWN:
+ break;
+ case D_SYNT_ERROR:
+ break;
+ default:
+ OSL_FAIL( "ScImportDif - missing enum" );
+ }
+ }
+
+ aAttrCache.Apply( *pDoc, nBaseTab );
+ }
+ else
+ return eERR_FORMAT;
+
+ if( bSyntErrWarn )
+ //###############################################
+ // ACHTUNG: Hier fehlt noch die richtige Warnung!
+ return eERR_RNGOVRFLW;
+ //###############################################
+ else if( bOverflowWarn )
+ return eERR_RNGOVRFLW;
+ else
+ return eERR_OK;
+}
+
+
+DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, CharSet e ) :
+ rIn( rNewIn )
+{
+ eCharSet = e;
+ if ( rIn.GetStreamCharSet() != eCharSet )
+ {
+ DBG_ERRORFILE( "CharSet passed overrides and modifies StreamCharSet" );
+ rIn.SetStreamCharSet( eCharSet );
+ }
+ rIn.StartReadingUnicodeText( eCharSet );
+
+ bPlain = ( nOption == SC_DIFOPT_PLAIN );
+
+ if( bPlain )
+ pNumFormatter = NULL;
+ else
+ pNumFormatter = rDoc.GetFormatTable();
+}
+
+
+TOPIC DifParser::GetNextTopic( void )
+{
+ enum STATE { S_VectorVal, S_Data, S_END, S_START, S_UNKNOWN, S_ERROR_L2 };
+
+ static const sal_Unicode pKeyLABEL[] = { 'L', 'A', 'B', 'E', 'L', 0 };
+ static const sal_Unicode pKeyCOMMENT[] = { 'C', 'O', 'M', 'M', 'E', 'N', 'T', 0 };
+ static const sal_Unicode pKeySIZE[] = { 'S', 'I', 'Z', 'E', 0 };
+ static const sal_Unicode pKeyPERIODICITY[] = { 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', 'I', 'T', 'Y', 0 };
+ static const sal_Unicode pKeyMAJORSTART[] = { 'M', 'A', 'J', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
+ static const sal_Unicode pKeyMINORSTART[] = { 'M', 'I', 'N', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
+ static const sal_Unicode pKeyTRUELENGTH[] = { 'T', 'R', 'U', 'E', 'L', 'E', 'N', 'G', 'T', 'H', 0 };
+ static const sal_Unicode pKeyUINITS[] = { 'U', 'I', 'N', 'I', 'T', 'S', 0 };
+ static const sal_Unicode pKeyDISPLAYUNITS[] = { 'D', 'I', 'S', 'P', 'L', 'A', 'Y', 'U', 'N', 'I', 'T', 'S', 0 };
+ static const sal_Unicode pKeyUNKNOWN[] = { 0 };
+
+ static const sal_Unicode* ppKeys[] =
+ {
+ pKeyTABLE, // 0
+ pKeyVECTORS,
+ pKeyTUPLES,
+ pKeyDATA,
+ pKeyLABEL,
+ pKeyCOMMENT, // 5
+ pKeySIZE,
+ pKeyPERIODICITY,
+ pKeyMAJORSTART,
+ pKeyMINORSTART,
+ pKeyTRUELENGTH, // 10
+ pKeyUINITS,
+ pKeyDISPLAYUNITS,
+ pKeyUNKNOWN // 13
+ };
+
+ static const TOPIC pTopics[] =
+ {
+ T_TABLE, // 0
+ T_VECTORS,
+ T_TUPLES,
+ T_DATA,
+ T_LABEL,
+ T_COMMENT, // 5
+ T_SIZE,
+ T_PERIODICITY,
+ T_MAJORSTART,
+ T_MINORSTART,
+ T_TRUELENGTH, // 10
+ T_UINITS,
+ T_DISPLAYUNITS,
+ T_UNKNOWN // 13
+ };
+
+ STATE eS = S_START;
+ String aLine;
+
+ nVector = 0;
+ nVal = 0;
+ TOPIC eRet = T_UNKNOWN;
+
+ while( eS != S_END )
+ {
+ if( !ReadNextLine( aLine ) )
+ {
+ eS = S_END;
+ eRet = T_END;
+ }
+
+ switch( eS )
+ {
+ case S_START:
+ {
+ const sal_Unicode* pRef;
+ sal_uInt16 nCnt = 0;
+ sal_Bool bSearch = sal_True;
+
+ pRef = ppKeys[ nCnt ];
+
+ while( bSearch )
+ {
+ if( aLine == pRef )
+ {
+ eRet = pTopics[ nCnt ];
+ bSearch = false;
+ }
+ else
+ {
+ nCnt++;
+ pRef = ppKeys[ nCnt ];
+ if( !*pRef )
+ bSearch = false;
+ }
+ }
+
+ if( *pRef )
+ eS = S_VectorVal;
+ else
+ eS = S_UNKNOWN;
+ }
+ break;
+ case S_VectorVal:
+ {
+ const sal_Unicode* pCur = aLine.GetBuffer();
+
+ pCur = ScanIntVal( pCur, nVector );
+
+ if( pCur && *pCur == ',' )
+ {
+ pCur++;
+ ScanIntVal( pCur, nVal );
+ eS = S_Data;
+ }
+ else
+ eS = S_ERROR_L2;
+ }
+ break;
+ case S_Data:
+ DBG_ASSERT( aLine.Len() >= 2,
+ "+GetNextTopic(): <String> ist zu kurz!" );
+ if( aLine.Len() > 2 )
+ aData = aLine.Copy( 1, aLine.Len() - 2 );
+ else
+ aData.Erase();
+ eS = S_END;
+ break;
+ case S_END:
+ DBG_ERRORFILE( "DifParser::GetNextTopic - unexpected state" );
+ break;
+ case S_UNKNOWN:
+ // 2 Zeilen ueberlesen
+ ReadNextLine( aLine );
+ case S_ERROR_L2: // Fehler in Line 2 aufgetreten
+ // eine Zeile ueberlesen
+ ReadNextLine( aLine );
+ eS = S_END;
+ break;
+ default:
+ DBG_ERRORFILE( "DifParser::GetNextTopic - missing enum" );
+ }
+ }
+
+ return eRet;
+}
+
+
+static void lcl_DeEscapeQuotesDif( String& rString )
+{
+ // Special handling for DIF import: Escaped (duplicated) quotes are resolved.
+ // Single quote characters are left in place because older versions didn't
+ // escape quotes in strings (and Excel doesn't when using the clipboard).
+ // The quotes around the string are removed before this function is called.
+
+ static const sal_Unicode aDQ[] = { '"', '"', 0 };
+ xub_StrLen nPos = 0;
+ while ( (nPos = rString.Search( aDQ, nPos )) != STRING_NOTFOUND )
+ {
+ rString.Erase( nPos, 1 );
+ ++nPos;
+ }
+}
+
+// Determine if passed in string is numeric data and set fVal/nNumFormat if so
+DATASET DifParser::GetNumberDataset( const sal_Unicode* pPossibleNumericData )
+{
+ DATASET eRet = D_SYNT_ERROR;
+ if( bPlain )
+ {
+ if( ScanFloatVal( pPossibleNumericData ) )
+ eRet = D_NUMERIC;
+ else
+ eRet = D_SYNT_ERROR;
+ }
+ else
+ { // ...und zur Strafe mit'm Numberformatter...
+ DBG_ASSERT( pNumFormatter, "-DifParser::GetNextDataset(): No Formatter, more fun!" );
+ String aTestVal( pPossibleNumericData );
+ sal_uInt32 nFormat = 0;
+ double fTmpVal;
+ if( pNumFormatter->IsNumberFormat( aTestVal, nFormat, fTmpVal ) )
+ {
+ fVal = fTmpVal;
+ nNumFormat = nFormat;
+ eRet = D_NUMERIC;
+ }
+ else
+ eRet = D_SYNT_ERROR;
+ }
+ return eRet;
+}
+
+bool DifParser::ReadNextLine( String& rStr )
+{
+ if( aLookAheadLine.Len() == 0 )
+ {
+ return rIn.ReadUniOrByteStringLine( rStr );
+ }
+ else
+ {
+ rStr = aLookAheadLine;
+ aLookAheadLine.Erase();
+ return true;
+ }
+}
+
+// Look ahead in the stream to determine if the next line is the first line of
+// a valid data record structure
+bool DifParser::LookAhead()
+{
+ const sal_Unicode* pAktBuffer;
+ bool bValidStructure = false;
+
+ DBG_ASSERT( aLookAheadLine.Len() == 0, "*DifParser::LookAhead(): LookAhead called twice in a row" );
+ rIn.ReadUniOrByteStringLine( aLookAheadLine );
+
+ pAktBuffer = aLookAheadLine.GetBuffer();
+
+ switch( *pAktBuffer )
+ {
+ case '-': // Special Datatype
+ pAktBuffer++;
+
+ if( Is1_0( pAktBuffer ) )
+ {
+ bValidStructure = true;
+ }
+ break;
+ case '0': // Numeric Data
+ pAktBuffer++;
+ if( *pAktBuffer == ',' )
+ {
+ pAktBuffer++;
+ bValidStructure = ( GetNumberDataset(pAktBuffer) != D_SYNT_ERROR );
+ }
+ break;
+ case '1': // String Data
+ if( Is1_0( aLookAheadLine.GetBuffer() ) )
+ {
+ bValidStructure = true;
+ }
+ break;
+ }
+ return bValidStructure;
+}
+
+DATASET DifParser::GetNextDataset( void )
+{
+ DATASET eRet = D_UNKNOWN;
+ String aLine;
+ const sal_Unicode* pAktBuffer;
+
+ ReadNextLine( aLine );
+
+ pAktBuffer = aLine.GetBuffer();
+
+ switch( *pAktBuffer )
+ {
+ case '-': // Special Datatype
+ pAktBuffer++;
+
+ if( Is1_0( pAktBuffer ) )
+ {
+ ReadNextLine( aLine );
+ if( IsBOT( aLine.GetBuffer() ) )
+ eRet = D_BOT;
+ else if( IsEOD( aLine.GetBuffer() ) )
+ eRet = D_EOD;
+ }
+ break;
+ case '0': // Numeric Data
+ pAktBuffer++; // Wert in fVal, 2. Zeile in aData
+ if( *pAktBuffer == ',' )
+ {
+ pAktBuffer++;
+ eRet = GetNumberDataset(pAktBuffer);
+ ReadNextLine( aData );
+ if ( eRet == D_SYNT_ERROR )
+ { // for broken records write "#ERR: data" to cell
+ String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#ERR: " ));
+ aTmp += pAktBuffer;
+ aTmp.AppendAscii( " (" );
+ aTmp += aData;
+ aTmp += sal_Unicode(')');
+ aData = aTmp;
+ eRet = D_STRING;
+ }
+ }
+ break;
+ case '1': // String Data
+ if( Is1_0( aLine.GetBuffer() ) )
+ {
+ ReadNextLine( aLine );
+ xub_StrLen nLineLength = aLine.Len();
+ const sal_Unicode* pLine = aLine.GetBuffer();
+
+ if( nLineLength >= 1 && *pLine == '"' )
+ {
+ // Quotes are not always escaped (duplicated), see lcl_DeEscapeQuotesDif
+ // A look ahead into the next line is needed in order to deal with
+ // multiline strings containing quotes
+ if( LookAhead() )
+ {
+ // Single line string
+ if( nLineLength >= 2 && pLine[nLineLength - 1] == '"' )
+ {
+ aData = aLine.Copy( 1, nLineLength - 2 );
+ lcl_DeEscapeQuotesDif( aData );
+ eRet = D_STRING;
+ }
+ }
+ else
+ {
+ // Multiline string
+ aData = aLine.Copy( 1 );
+ bool bContinue = true;
+ while ( bContinue )
+ {
+ aData.Append( '\n' );
+ bContinue = !rIn.IsEof() && ReadNextLine( aLine );
+ if( bContinue )
+ {
+ nLineLength = aLine.Len();
+ if( nLineLength >= 1 )
+ {
+ pLine = aLine.GetBuffer();
+ bContinue = !LookAhead();
+ if( bContinue )
+ {
+ aData.Append( aLine );
+ }
+ else if( pLine[nLineLength - 1] == '"' )
+ {
+ aData.Append( pLine, nLineLength - 1 );
+ lcl_DeEscapeQuotesDif( aData );
+ eRet = D_STRING;
+ }
+ }
+ }
+ };
+ }
+ }
+ }
+ break;
+ }
+
+ if( eRet == D_UNKNOWN )
+ ReadNextLine( aLine );
+
+ if( rIn.IsEof() )
+ eRet = D_EOD;
+
+ return eRet;
+}
+
+
+const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
+{
+ // eat leading whitespace, not specified, but seen in the wild
+ while (*pStart == ' ' || *pStart == '\t')
+ ++pStart;
+
+ sal_Unicode cAkt = *pStart;
+
+ if( IsNumber( cAkt ) )
+ rRet = ( sal_uInt32 ) ( cAkt - '0' );
+ else
+ return NULL;
+
+ pStart++;
+ cAkt = *pStart;
+
+ while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
+ {
+ rRet *= 10;
+ rRet += ( sal_uInt32 ) ( cAkt - '0' );
+
+ pStart++;
+ cAkt = *pStart;
+ }
+
+ return pStart;
+}
+
+
+sal_Bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
+ {
+ double fNewVal = 0.0;
+ sal_Bool bNeg = false;
+ double fFracPos = 1.0;
+ sal_Int32 nExp = 0;
+ sal_Bool bExpNeg = false;
+ sal_Bool bExpOverflow = false;
+ static const sal_uInt16 nExpLimit = 4096; // ACHTUNG: muss genauer ermittelt werden!
+
+ sal_Unicode cAkt;
+ sal_Bool bRet = false;
+
+ enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
+
+ STATE eS = S_FIRST;
+
+ fNewVal = 0.0;
+
+ while( eS != S_END )
+ {
+ cAkt = *pStart;
+ switch( eS )
+ {
+ case S_FIRST:
+ if( IsNumber( cAkt ) )
+ {
+ fNewVal *= 10;
+ fNewVal += cAkt - '0';
+ eS = S_PRE;
+ }
+ else
+ {
+ switch( cAkt )
+ {
+ case ' ':
+ case '\t':
+ case '+':
+ break;
+ case '-':
+ bNeg = !bNeg;
+ break;
+ case '.':
+ case ',': //!
+ eS = S_POST;
+ fFracPos = 0.1;
+ break;
+ default:
+ eS = S_END;
+ }
+ }
+ break;
+ case S_PRE:
+ if( IsNumber( cAkt ) )
+ {
+ fNewVal *= 10;
+ fNewVal += cAkt - '0';
+ }
+ else
+ {
+ switch( cAkt )
+ {
+ case '.':
+ case ',': //!
+ eS = S_POST;
+ fFracPos = 0.1;
+ break;
+ case 'e':
+ case 'E':
+ eS = S_EXP;
+ break;
+ case 0x00: // IsNumberEnding( cAkt )
+ bRet = sal_True; // no
+ default: // break!
+ eS = S_END;
+ }
+ }
+ break;
+ case S_POST:
+ if( IsNumber( cAkt ) )
+ {
+ fNewVal += fFracPos * ( cAkt - '0' );
+ fFracPos /= 10.0;
+ }
+ else
+ {
+ switch( cAkt )
+ {
+ case 'e':
+ case 'E':
+ eS = S_EXP_FIRST;
+ break;
+ case 0x00: // IsNumberEnding( cAkt )
+ bRet = sal_True; // no
+ default: // break!
+ eS = S_END;
+ }
+ }
+ break;
+ case S_EXP_FIRST:
+ if( IsNumber( cAkt ) )
+ {
+ if( nExp < nExpLimit )
+ {
+ nExp *= 10;
+ nExp += ( sal_uInt16 ) ( cAkt - '0' );
+ }
+ eS = S_EXP;
+ }
+ else
+ {
+ switch( cAkt )
+ {
+ case '+':
+ break;
+ case '-':
+ bExpNeg = !bExpNeg;
+ break;
+ default:
+ eS = S_END;
+ }
+ }
+ break;
+ case S_EXP:
+ if( IsNumber( cAkt ) )
+ {
+ if( nExp < ( 0xFFFF / 10 ) )
+ {
+ nExp *= 10;
+ nExp += ( sal_uInt16 ) ( cAkt - '0' );
+ }
+ else
+ {
+ bExpOverflow = sal_True;
+ eS = S_FINDEND;
+ }
+ }
+ else
+ {
+ bRet = IsNumberEnding( cAkt );
+ eS = S_END;
+ }
+ break;
+ case S_FINDEND:
+ if( IsNumberEnding( cAkt ) )
+ {
+ bRet = sal_True; // damit sinnvoll weitergeparst werden kann
+ eS = S_END;
+ }
+ break;
+ case S_END:
+ DBG_ERRORFILE( "DifParser::ScanFloatVal - unexpected state" );
+ break;
+ default:
+ DBG_ERRORFILE( "DifParser::ScanFloatVal - missing enum" );
+ }
+ pStart++;
+ }
+
+ if( bRet )
+ {
+ if( bExpOverflow )
+ return false; // ACHTUNG: hier muss noch differenziert werden
+
+ if( bNeg )
+ fNewVal *= 1.0;
+
+ if( bExpNeg )
+ nExp *= -1;
+
+ if( nExp != 0 )
+ fNewVal *= pow( 10.0, ( double ) nExp );
+ fVal = fNewVal;
+ }
+
+ return bRet;
+}
+
+DifColumn::DifColumn ()
+ : pAkt(NULL)
+{
+}
+
+void DifColumn::SetLogical( SCROW nRow )
+{
+ DBG_ASSERT( ValidRow(nRow), "*DifColumn::SetLogical(): Row zu gross!" );
+
+ if( pAkt )
+ {
+ DBG_ASSERT( nRow > 0, "*DifColumn::SetLogical(): weitere koennen nicht 0 sein!" );
+
+ nRow--;
+
+ if( pAkt->nEnd == nRow )
+ pAkt->nEnd++;
+ else
+ pAkt = NULL;
+ }
+ else
+ {
+ pAkt = new ENTRY;
+ pAkt->nStart = pAkt->nEnd = nRow;
+
+ aEntries.push_back(pAkt);
+ }
+}
+
+
+void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
+{
+ DBG_ASSERT( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row zu gross!" );
+
+ if( nNumFormat > 0 )
+ {
+ if(pAkt)
+ {
+ DBG_ASSERT( nRow > 0,
+ "*DifColumn::SetNumFormat(): weitere koennen nicht 0 sein!" );
+ DBG_ASSERT( nRow > pAkt->nEnd,
+ "*DifColumn::SetNumFormat(): Noch 'mal von vorne?" );
+
+ if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
+ pAkt->nEnd = nRow;
+ else
+ NewEntry( nRow, nNumFormat );
+ }
+ else
+ NewEntry(nRow,nNumFormat );
+ }
+ else
+ pAkt = NULL;
+}
+
+
+void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
+{
+ pAkt = new ENTRY;
+ pAkt->nStart = pAkt->nEnd = nPos;
+ pAkt->nNumFormat = nNumFormat;
+
+ aEntries.push_back(pAkt);
+}
+
+
+void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
+{
+ for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
+ rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, rPattAttr );
+}
+
+
+void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
+{
+ ScPatternAttr aAttr( rDoc.GetPool() );
+ SfxItemSet &rItemSet = aAttr.GetItemSet();
+
+ for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
+ {
+ DBG_ASSERT( it->nNumFormat > 0,
+ "+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
+
+ rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, it->nNumFormat ) );
+
+ rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, aAttr );
+
+ rItemSet.ClearItem();
+ }
+}
+
+
+DifAttrCache::DifAttrCache( const sal_Bool bNewPlain )
+{
+ bPlain = bNewPlain;
+ ppCols = new DifColumn *[ MAXCOL + 1 ];
+ for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
+ ppCols[ nCnt ] = NULL;
+}
+
+
+DifAttrCache::~DifAttrCache()
+{
+ for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
+ {
+ if( ppCols[ nCnt ] )
+ delete ppCols[ nCnt ];
+ }
+}
+
+void DifAttrCache::SetLogical( const SCCOL nCol, const SCROW nRow )
+{
+ DBG_ASSERT( ValidCol(nCol), "-DifAttrCache::SetLogical(): Col zu gross!" );
+ DBG_ASSERT( bPlain, "*DifAttrCache::SetLogical(): muss Plain sein!" );
+
+ if( !ppCols[ nCol ] )
+ ppCols[ nCol ] = new DifColumn;
+
+ ppCols[ nCol ]->SetLogical( nRow );
+}
+
+void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
+{
+ DBG_ASSERT( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col zu gross!" );
+ DBG_ASSERT( !bPlain, "*DifAttrCache::SetNumFormat(): sollte nicht Plain sein!" );
+
+ if( !ppCols[ nCol ] )
+ ppCols[ nCol ] = new DifColumn;
+
+ ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
+}
+
+
+void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
+{
+ if( bPlain )
+ {
+ ScPatternAttr* pPatt = NULL;
+
+ for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
+ {
+ if( ppCols[ nCol ] )
+ {
+ if( !pPatt )
+ {
+ pPatt = new ScPatternAttr( rDoc.GetPool() );
+ pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
+ rDoc.GetFormatTable()->GetStandardFormat( NUMBERFORMAT_LOGICAL ) ) );
+ }
+
+ ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
+ }
+ }
+
+ if( pPatt )
+ delete pPatt;
+ }
+ else
+ {
+ for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
+ {
+ if( ppCols[ nCol ] )
+ ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
+ }
+ }
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */