blob: 37bf41ecfe3275581693bbe6715f10b48c0a0a13 [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 <rtl/math.hxx>
#include <stdio.h>
#include "dif.hxx"
#include "filter.hxx"
#include "document.hxx"
#include "cell.hxx"
#include "globstr.hrc"
#include "global.hxx"
#include "progress.hxx"
#include <rtl/tencinfo.h>
#include "ftools.hxx"
FltError ScFormatFilterPluginImpl::ScExportDif( SvStream& rStream, ScDocument* pDoc,
const ScAddress& rOutPos, const CharSet eNach, sal_uInt32 nDifOption )
{
SCCOL nEndCol;
SCROW nEndRow;
pDoc->GetTableArea( rOutPos.Tab(), nEndCol, nEndRow );
ScAddress aEnd( nEndCol, nEndRow, rOutPos.Tab() );
ScAddress aStart( rOutPos );
aStart.PutInOrder( aEnd );
return ScExportDif( rStream, pDoc, ScRange( aStart, aEnd ), eNach, nDifOption );
}
FltError ScFormatFilterPluginImpl::ScExportDif( SvStream& rOut, ScDocument* pDoc,
const ScRange&rRange, const CharSet eCharSet, sal_uInt32 nDifOption )
{
DBG_ASSERT( rRange.aStart <= rRange.aEnd, "*ScExportDif(): Range unsortiert!" );
DBG_ASSERTWARNING( rRange.aStart.Tab() == rRange.aEnd.Tab(),
"ScExportDif(): nur eine Tabelle bidde!" );
const CharSet eStreamCharSet = rOut.GetStreamCharSet();
if ( eStreamCharSet != eCharSet )
rOut.SetStreamCharSet( eCharSet );
sal_Unicode cStrDelim('"');
ByteString aStrDelimEncoded; // only used if not Unicode
UniString aStrDelimDecoded; // only used if context encoding
sal_Bool bContextOrNotAsciiEncoding;
if ( eCharSet == RTL_TEXTENCODING_UNICODE )
{
rOut.StartWritingUnicodeText();
bContextOrNotAsciiEncoding = sal_False;
}
else
{
aStrDelimEncoded = ByteString( cStrDelim, eCharSet );
rtl_TextEncodingInfo aInfo;
aInfo.StructSize = sizeof(aInfo);
if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
{
bContextOrNotAsciiEncoding =
(((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
if ( bContextOrNotAsciiEncoding )
aStrDelimDecoded = String( aStrDelimEncoded, eCharSet );
}
else
bContextOrNotAsciiEncoding = sal_False;
}
const sal_Char* p2DoubleQuotes_LF = "\"\"\n";
const sal_Char* pSpecDataType_LF = "-1,0\n";
const sal_Char* pEmptyData = "1,0\n\"\"\n";
const sal_Char* pStringData = "1,0\n";
const sal_Char* pNumData = "0,";
const sal_Char* pNumDataERROR = "0,0\nERROR\n";
FltError eRet = eERR_OK;
String aOS;
String aString;
SCCOL nEndCol = rRange.aEnd.Col();
SCROW nEndRow = rRange.aEnd.Row();
SCCOL nNumCols = nEndCol - rRange.aStart.Col() + 1;
SCROW nNumRows = nEndRow - rRange.aStart.Row() + 1;
SCTAB nTab = rRange.aStart.Tab();
double fVal;
const sal_Bool bPlain = ( nDifOption == SC_DIFOPT_PLAIN );
ScProgress aPrgrsBar( pDoc->GetDocumentShell(), ScGlobal::GetRscString( STR_LOAD_DOC ), nNumRows );
aPrgrsBar.SetState( 0 );
// TABLE
DBG_ASSERT( pDoc->HasTable( nTab ), "*ScExportDif(): Tabelle nicht vorhanden!" );
aOS = pKeyTABLE;
aOS.AppendAscii( "\n0,1\n\"" );
pDoc->GetName( nTab, aString );
aOS += aString;
aOS.AppendAscii( "\"\n" );
rOut.WriteUnicodeOrByteText( aOS );
// VECTORS
aOS = pKeyVECTORS;
aOS.AppendAscii( "\n0," );
aOS += String::CreateFromInt32( nNumCols );
aOS += sal_Unicode('\n');
aOS.AppendAscii( p2DoubleQuotes_LF );
rOut.WriteUnicodeOrByteText( aOS );
// TUPLES
aOS = pKeyTUPLES;
aOS.AppendAscii( "\n0," );
aOS += String::CreateFromInt32( nNumRows );
aOS += sal_Unicode('\n');
aOS.AppendAscii( p2DoubleQuotes_LF );
rOut.WriteUnicodeOrByteText( aOS );
// DATA
aOS = pKeyDATA;
aOS.AppendAscii( "\n0,0\n" );
aOS.AppendAscii( p2DoubleQuotes_LF );
rOut.WriteUnicodeOrByteText( aOS );
SCCOL nColCnt;
SCROW nRowCnt;
ScBaseCell* pAkt;
for( nRowCnt = rRange.aStart.Row() ; nRowCnt <= nEndRow ; nRowCnt++ )
{
aOS.AssignAscii( pSpecDataType_LF );
aOS += pKeyBOT;
aOS += sal_Unicode('\n');
rOut.WriteUnicodeOrByteText( aOS );
for( nColCnt = rRange.aStart.Col() ; nColCnt <= nEndCol ; nColCnt++ )
{
bool bWriteStringData = false;
pDoc->GetCell( nColCnt, nRowCnt, nTab, pAkt );
if( pAkt )
{
switch( pAkt->GetCellType() )
{
case CELLTYPE_NONE:
case CELLTYPE_NOTE:
aOS.AssignAscii( pEmptyData );
break;
case CELLTYPE_VALUE:
aOS.AssignAscii( pNumData );
if( bPlain )
{
fVal = ( ( ScValueCell * ) pAkt )->GetValue();
aOS += String( ::rtl::math::doubleToUString(
fVal, rtl_math_StringFormat_G, 14, '.',
sal_True));
}
else
{
pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
aOS += aString;
}
aOS.AppendAscii( "\nV\n" );
break;
case CELLTYPE_EDIT:
( ( ScEditCell* ) pAkt )->GetString( aString );
bWriteStringData = true;
break;
case CELLTYPE_STRING:
( ( ScStringCell* ) pAkt )->GetString( aString );
bWriteStringData = true;
break;
case CELLTYPE_FORMULA:
if ( ((ScFormulaCell*)pAkt)->GetErrCode() )
aOS.AssignAscii( pNumDataERROR );
else if( pAkt->HasValueData() )
{
aOS.AssignAscii( pNumData );
if( bPlain )
{
fVal = ( ( ScFormulaCell * ) pAkt )->GetValue();
aOS += String( ::rtl::math::doubleToUString(
fVal, rtl_math_StringFormat_G, 14,
'.', sal_True));
}
else
{
pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
aOS += aString;
}
aOS.AppendAscii( "\nV\n" );
}
else if( pAkt->HasStringData() )
{
( ( ScFormulaCell * ) pAkt )->GetString( aString );
bWriteStringData = true;
}
else
aOS.AssignAscii( pNumDataERROR );
break;
default:;
}
}
else
aOS.AssignAscii( pEmptyData );
if ( !bWriteStringData )
rOut.WriteUnicodeOrByteText( aOS );
else
{
// for an explanation why this complicated, see
// sc/source/ui/docsh.cxx:ScDocShell::AsciiSave()
// In fact we should create a common method if this would be
// needed just one more time..
aOS.AssignAscii( pStringData );
rOut.WriteUnicodeOrByteText( aOS, eCharSet );
if ( eCharSet == RTL_TEXTENCODING_UNICODE )
{
xub_StrLen nPos = aString.Search( cStrDelim );
while ( nPos != STRING_NOTFOUND )
{
aString.Insert( cStrDelim, nPos );
nPos = aString.Search( cStrDelim, nPos+2 );
}
rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
rOut.WriteUnicodeText( aString );
rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
}
else if ( bContextOrNotAsciiEncoding )
{
// to byte encoding
ByteString aStrEnc( aString, eCharSet );
// back to Unicode
UniString aStrDec( aStrEnc, eCharSet );
// search on re-decoded string
xub_StrLen nPos = aStrDec.Search( aStrDelimDecoded );
while ( nPos != STRING_NOTFOUND )
{
aStrDec.Insert( aStrDelimDecoded, nPos );
nPos = aStrDec.Search( aStrDelimDecoded,
nPos+1+aStrDelimDecoded.Len() );
}
// write byte re-encoded
rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
rOut.WriteUnicodeOrByteText( aStrDec, eCharSet );
rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
}
else
{
ByteString aStrEnc( aString, eCharSet );
// search on encoded string
xub_StrLen nPos = aStrEnc.Search( aStrDelimEncoded );
while ( nPos != STRING_NOTFOUND )
{
aStrEnc.Insert( aStrDelimEncoded, nPos );
nPos = aStrEnc.Search( aStrDelimEncoded,
nPos+1+aStrDelimEncoded.Len() );
}
// write byte encoded
rOut.Write( aStrDelimEncoded.GetBuffer(),
aStrDelimEncoded.Len() );
rOut.Write( aStrEnc.GetBuffer(), aStrEnc.Len() );
rOut.Write( aStrDelimEncoded.GetBuffer(),
aStrDelimEncoded.Len() );
}
rOut.WriteUniOrByteChar( '\n', eCharSet );
}
}
aPrgrsBar.SetState( nRowCnt );
}
aOS.AssignAscii( pSpecDataType_LF );
aOS += pKeyEOD;
aOS += sal_Unicode('\n');
rOut.WriteUnicodeOrByteText( aOS );
// restore original value
rOut.SetStreamCharSet( eStreamCharSet );
return eRet;
}