blob: f3537c8d9ba4adab4ec32bd754213e87498a2328 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
//------------------------------------------------------------------------
#include "scitems.hxx"
#include <svl/zforlist.hxx>
#include "dif.hxx"
#include "filter.hxx"
#include "fprogressbar.hxx"
#include "scerrors.hxx"
#include "document.hxx"
#include "cell.hxx"
#include "patattr.hxx"
#include "docpool.hxx"
#include "attrib.hxx"
#include "ftools.hxx"
#include <math.h>
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 = sal_False;
sal_Bool bOverflowWarn = sal_False;
String& rData = aDifParser.aData;
sal_Bool bData = sal_False;
SCCOL nNumCols = 0;
SCROW nNumRows = 0;
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 = sal_True;
if( aDifParser.nVal > MAXCOL + 1 )
nNumCols = SCCOL_MAX;
else
nNumCols = static_cast<SCCOL>(aDifParser.nVal);
}
break;
case T_TUPLES:
{
if( aDifParser.nVector != 0 )
bSyntErrWarn = sal_True;
if( aDifParser.nVal > MAXROW + 1 )
nNumRows = SCROW_MAX;
else
nNumRows = static_cast<SCROW>(aDifParser.nVal);
}
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:
DBG_ERROR( "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 = sal_False;
}
else
{
nCnt++;
pRef = ppKeys[ nCnt ];
if( !*pRef )
bSearch = sal_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 = sal_False;
double fFracPos = 1.0;
sal_Int32 nExp = 0;
sal_Bool bExpNeg = sal_False;
sal_Bool bExpOverflow = sal_False;
static const sal_uInt16 nExpLimit = 4096; // ACHTUNG: muss genauer ermittelt werden!
sal_Unicode cAkt;
sal_Bool bRet = sal_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 sal_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( void )
{
ENTRY* pEntry = ( ENTRY* ) List::First();
while( pEntry )
{
delete pEntry;
pEntry = ( ENTRY* ) List::Next();
}
}
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;
List::Insert( pAkt, LIST_APPEND );
}
}
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;
List::Insert( pAkt, LIST_APPEND );
}
void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
{
ENTRY* pEntry = ( ENTRY* ) List::First();
while( pEntry )
{
rDoc.ApplyPatternAreaTab( nCol, pEntry->nStart, nCol, pEntry->nEnd,
nTab, rPattAttr );
pEntry = ( ENTRY* ) List::Next();
}
}
void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
{
ScPatternAttr aAttr( rDoc.GetPool() );
SfxItemSet& rItemSet = aAttr.GetItemSet();
ENTRY* pEntry = ( ENTRY* ) List::First();
while( pEntry )
{
DBG_ASSERT( pEntry->nNumFormat > 0,
"+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, pEntry->nNumFormat ) );
rDoc.ApplyPatternAreaTab( nCol, pEntry->nStart, nCol, pEntry->nEnd, nTab, aAttr );
rItemSet.ClearItem();
pEntry = ( ENTRY* ) List::Next();
}
}
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::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 );
}
}
}