xref: /trunk/main/sc/source/filter/dif/difexp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 //------------------------------------------------------------------------
34 
35 #include <rtl/math.hxx>
36 
37 #include <stdio.h>
38 
39 #include "dif.hxx"
40 #include "filter.hxx"
41 #include "document.hxx"
42 #include "cell.hxx"
43 #include "globstr.hrc"
44 #include "global.hxx"
45 #include "progress.hxx"
46 #include <rtl/tencinfo.h>
47 #include "ftools.hxx"
48 
49 FltError ScFormatFilterPluginImpl::ScExportDif( SvStream& rStream, ScDocument* pDoc,
50 	const ScAddress& rOutPos, const CharSet eNach, sal_uInt32 nDifOption )
51 {
52 	SCCOL		nEndCol;
53 	SCROW		nEndRow;
54 	pDoc->GetTableArea( rOutPos.Tab(), nEndCol, nEndRow );
55 	ScAddress	aEnd( nEndCol, nEndRow, rOutPos.Tab() );
56 	ScAddress	aStart( rOutPos );
57 
58 	aStart.PutInOrder( aEnd );
59 
60 	return ScExportDif( rStream, pDoc, ScRange( aStart, aEnd ), eNach, nDifOption );
61 }
62 
63 
64 FltError ScFormatFilterPluginImpl::ScExportDif( SvStream& rOut, ScDocument* pDoc,
65 	const ScRange&rRange, const CharSet eCharSet, sal_uInt32 nDifOption )
66 {
67 	DBG_ASSERT( rRange.aStart <= rRange.aEnd, "*ScExportDif(): Range unsortiert!" );
68 	DBG_ASSERTWARNING( rRange.aStart.Tab() == rRange.aEnd.Tab(),
69 		"ScExportDif(): nur eine Tabelle bidde!" );
70 
71     const CharSet eStreamCharSet = rOut.GetStreamCharSet();
72     if ( eStreamCharSet != eCharSet )
73         rOut.SetStreamCharSet( eCharSet );
74 
75     sal_Unicode cStrDelim('"');
76     ByteString aStrDelimEncoded;    // only used if not Unicode
77     UniString aStrDelimDecoded;     // only used if context encoding
78     sal_Bool bContextOrNotAsciiEncoding;
79 	if ( eCharSet == RTL_TEXTENCODING_UNICODE )
80     {
81 		rOut.StartWritingUnicodeText();
82         bContextOrNotAsciiEncoding = sal_False;
83     }
84     else
85     {
86         aStrDelimEncoded = ByteString( cStrDelim, eCharSet );
87         rtl_TextEncodingInfo aInfo;
88         aInfo.StructSize = sizeof(aInfo);
89         if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
90         {
91             bContextOrNotAsciiEncoding =
92                 (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
93                  ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
94             if ( bContextOrNotAsciiEncoding )
95                 aStrDelimDecoded = String( aStrDelimEncoded, eCharSet );
96         }
97         else
98             bContextOrNotAsciiEncoding = sal_False;
99     }
100 
101 	const sal_Char*		p2DoubleQuotes_LF = "\"\"\n";
102 	const sal_Char*		pSpecDataType_LF = "-1,0\n";
103 	const sal_Char*		pEmptyData = "1,0\n\"\"\n";
104 	const sal_Char*		pStringData = "1,0\n";
105 	const sal_Char*		pNumData = "0,";
106 	const sal_Char*		pNumDataERROR = "0,0\nERROR\n";
107 
108 	FltError			eRet = eERR_OK;
109 	String			    aOS;
110 	String				aString;
111 	SCCOL				nEndCol = rRange.aEnd.Col();
112 	SCROW				nEndRow = rRange.aEnd.Row();
113 	SCCOL				nNumCols = nEndCol - rRange.aStart.Col() + 1;
114 	SCROW				nNumRows = nEndRow - rRange.aStart.Row() + 1;
115 	SCTAB				nTab = rRange.aStart.Tab();
116 
117 	double				fVal;
118 
119 	const sal_Bool			bPlain = ( nDifOption == SC_DIFOPT_PLAIN );
120 
121     ScProgress          aPrgrsBar( pDoc->GetDocumentShell(), ScGlobal::GetRscString( STR_LOAD_DOC ), nNumRows );
122 
123 	aPrgrsBar.SetState( 0 );
124 
125 	// TABLE
126 	DBG_ASSERT( pDoc->HasTable( nTab ), "*ScExportDif(): Tabelle nicht vorhanden!" );
127 
128 	aOS = pKeyTABLE;
129 	aOS.AppendAscii( "\n0,1\n\"" );
130 
131 	pDoc->GetName( nTab, aString );
132 	aOS += aString;
133 	aOS.AppendAscii( "\"\n" );
134     rOut.WriteUnicodeOrByteText( aOS );
135 
136 	// VECTORS
137 	aOS = pKeyVECTORS;
138 	aOS.AppendAscii( "\n0," );
139 	aOS += String::CreateFromInt32( nNumCols );
140 	aOS += sal_Unicode('\n');
141 	aOS.AppendAscii( p2DoubleQuotes_LF );
142     rOut.WriteUnicodeOrByteText( aOS );
143 
144 	// TUPLES
145 	aOS = pKeyTUPLES;
146 	aOS.AppendAscii( "\n0," );
147 	aOS += String::CreateFromInt32( nNumRows );
148 	aOS += sal_Unicode('\n');
149 	aOS.AppendAscii( p2DoubleQuotes_LF );
150     rOut.WriteUnicodeOrByteText( aOS );
151 
152 	// DATA
153     aOS = pKeyDATA;
154 	aOS.AppendAscii( "\n0,0\n" );
155 	aOS.AppendAscii( p2DoubleQuotes_LF );
156     rOut.WriteUnicodeOrByteText( aOS );
157 
158 	SCCOL				nColCnt;
159 	SCROW				nRowCnt;
160 	ScBaseCell*			pAkt;
161 
162 	for( nRowCnt = rRange.aStart.Row() ; nRowCnt <= nEndRow ; nRowCnt++ )
163 	{
164         aOS.AssignAscii( pSpecDataType_LF );
165         aOS += pKeyBOT;
166         aOS += sal_Unicode('\n');
167         rOut.WriteUnicodeOrByteText( aOS );
168 		for( nColCnt = rRange.aStart.Col() ; nColCnt <= nEndCol ; nColCnt++ )
169 		{
170             bool bWriteStringData = false;
171 			pDoc->GetCell( nColCnt, nRowCnt, nTab, pAkt );
172 			if( pAkt )
173 			{
174 				switch( pAkt->GetCellType() )
175 				{
176 					case CELLTYPE_NONE:
177 					case CELLTYPE_NOTE:
178 						aOS.AssignAscii( pEmptyData );
179 						break;
180 					case CELLTYPE_VALUE:
181 						aOS.AssignAscii( pNumData );
182 						if( bPlain )
183 						{
184 							fVal = ( ( ScValueCell * ) pAkt )->GetValue();
185                             aOS += String( ::rtl::math::doubleToUString(
186                                         fVal, rtl_math_StringFormat_G, 14, '.',
187                                         sal_True));
188 						}
189 						else
190 						{
191 							pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
192 							aOS += aString;
193 						}
194 						aOS.AppendAscii( "\nV\n" );
195 						break;
196 					case CELLTYPE_EDIT:
197 						( ( ScEditCell* ) pAkt )->GetString( aString );
198                         bWriteStringData = true;
199 						break;
200 					case CELLTYPE_STRING:
201 						( ( ScStringCell* ) pAkt )->GetString( aString );
202                         bWriteStringData = true;
203 						break;
204 					case CELLTYPE_FORMULA:
205                         if ( ((ScFormulaCell*)pAkt)->GetErrCode() )
206 							aOS.AssignAscii( pNumDataERROR );
207                         else if( pAkt->HasValueData() )
208 						{
209 							aOS.AssignAscii( pNumData );
210 							if( bPlain )
211 							{
212 								fVal = ( ( ScFormulaCell * ) pAkt )->GetValue();
213                                 aOS += String( ::rtl::math::doubleToUString(
214                                             fVal, rtl_math_StringFormat_G, 14,
215                                             '.', sal_True));
216 							}
217 							else
218 							{
219 								pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
220 								aOS += aString;
221 							}
222 							aOS.AppendAscii( "\nV\n" );
223 						}
224 						else if( pAkt->HasStringData() )
225 						{
226 							( ( ScFormulaCell * ) pAkt )->GetString( aString );
227                             bWriteStringData = true;
228 						}
229 						else
230 							aOS.AssignAscii( pNumDataERROR );
231 
232 						break;
233                     default:;
234 				}
235 			}
236 			else
237 				aOS.AssignAscii( pEmptyData );
238 
239             if ( !bWriteStringData )
240                 rOut.WriteUnicodeOrByteText( aOS );
241             else
242             {
243                 // for an explanation why this complicated, see
244                 // sc/source/ui/docsh.cxx:ScDocShell::AsciiSave()
245                 // In fact we should create a common method if this would be
246                 // needed just one more time..
247                 aOS.AssignAscii( pStringData );
248                 rOut.WriteUnicodeOrByteText( aOS, eCharSet );
249                 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
250                 {
251                     xub_StrLen nPos = aString.Search( cStrDelim );
252                     while ( nPos != STRING_NOTFOUND )
253                     {
254                         aString.Insert( cStrDelim, nPos );
255                         nPos = aString.Search( cStrDelim, nPos+2 );
256                     }
257                     rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
258                     rOut.WriteUnicodeText( aString );
259                     rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
260                 }
261                 else if ( bContextOrNotAsciiEncoding )
262                 {
263                     // to byte encoding
264                     ByteString aStrEnc( aString, eCharSet );
265                     // back to Unicode
266                     UniString aStrDec( aStrEnc, eCharSet );
267                     // search on re-decoded string
268                     xub_StrLen nPos = aStrDec.Search( aStrDelimDecoded );
269                     while ( nPos != STRING_NOTFOUND )
270                     {
271                         aStrDec.Insert( aStrDelimDecoded, nPos );
272                         nPos = aStrDec.Search( aStrDelimDecoded,
273                                 nPos+1+aStrDelimDecoded.Len() );
274                     }
275                     // write byte re-encoded
276                     rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
277                     rOut.WriteUnicodeOrByteText( aStrDec, eCharSet );
278                     rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
279                 }
280                 else
281                 {
282                     ByteString aStrEnc( aString, eCharSet );
283                     // search on encoded string
284                     xub_StrLen nPos = aStrEnc.Search( aStrDelimEncoded );
285                     while ( nPos != STRING_NOTFOUND )
286                     {
287                         aStrEnc.Insert( aStrDelimEncoded, nPos );
288                         nPos = aStrEnc.Search( aStrDelimEncoded,
289                                 nPos+1+aStrDelimEncoded.Len() );
290                     }
291                     // write byte encoded
292                     rOut.Write( aStrDelimEncoded.GetBuffer(),
293                             aStrDelimEncoded.Len() );
294                     rOut.Write( aStrEnc.GetBuffer(), aStrEnc.Len() );
295                     rOut.Write( aStrDelimEncoded.GetBuffer(),
296                             aStrDelimEncoded.Len() );
297                 }
298                 rOut.WriteUniOrByteChar( '\n', eCharSet );
299             }
300 		}
301 		aPrgrsBar.SetState( nRowCnt );
302 	}
303 
304     aOS.AssignAscii( pSpecDataType_LF );
305     aOS += pKeyEOD;
306     aOS += sal_Unicode('\n');
307     rOut.WriteUnicodeOrByteText( aOS );
308 
309     // restore original value
310     rOut.SetStreamCharSet( eStreamCharSet );
311 
312 	return eRet;
313 }
314 
315 
316 
317 
318