Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / dif / difexp.cxx
blob84179282a6500fb8b054fdb7a9317dd42f814d29
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <dif.hxx>
21 #include <document.hxx>
22 #include <formulacell.hxx>
23 #include <globstr.hrc>
24 #include <scresid.hxx>
25 #include <global.hxx>
26 #include <progress.hxx>
27 #include <rtl/tencinfo.h>
28 #include <ftools.hxx>
29 #include <cellvalue.hxx>
30 #include <rtl/strbuf.hxx>
31 #include <osl/diagnose.h>
32 #include <formula/errorcodes.hxx>
33 #include <tools/stream.hxx>
35 void ScFormatFilterPluginImpl::ScExportDif( SvStream& rStream, ScDocument* pDoc,
36 const ScAddress& rOutPos, const rtl_TextEncoding eNach )
38 SCCOL nEndCol;
39 SCROW nEndRow;
40 pDoc->GetTableArea( rOutPos.Tab(), nEndCol, nEndRow );
41 ScAddress aEnd( nEndCol, nEndRow, rOutPos.Tab() );
42 ScAddress aStart( rOutPos );
44 aStart.PutInOrder( aEnd );
46 ScExportDif( rStream, pDoc, ScRange( aStart, aEnd ), eNach );
49 void ScFormatFilterPluginImpl::ScExportDif( SvStream& rOut, ScDocument* pDoc,
50 const ScRange&rRange, const rtl_TextEncoding eCharSet )
52 OSL_ENSURE( rRange.aStart <= rRange.aEnd, "*ScExportDif(): Range not sorted!" );
53 OSL_ENSURE( rRange.aStart.Tab() == rRange.aEnd.Tab(),
54 "ScExportDif(): only one table please!" );
56 const rtl_TextEncoding eStreamCharSet = rOut.GetStreamCharSet();
57 if ( eStreamCharSet != eCharSet )
58 rOut.SetStreamCharSet( eCharSet );
60 sal_Unicode cStrDelim('"');
61 OString aStrDelimEncoded; // only used if not Unicode
62 OUString aStrDelimDecoded; // only used if context encoding
63 bool bContextOrNotAsciiEncoding;
64 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
66 rOut.StartWritingUnicodeText();
67 bContextOrNotAsciiEncoding = false;
69 else
71 aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
72 rtl_TextEncodingInfo aInfo;
73 aInfo.StructSize = sizeof(aInfo);
74 if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
76 bContextOrNotAsciiEncoding =
77 (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
78 ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
79 if ( bContextOrNotAsciiEncoding )
80 aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet);
82 else
83 bContextOrNotAsciiEncoding = false;
86 const sal_Char p2DoubleQuotes_LF[] = "\"\"\n";
87 const sal_Char pSpecDataType_LF[] = "-1,0\n";
88 const sal_Char pEmptyData[] = "1,0\n\"\"\n";
89 const sal_Char pStringData[] = "1,0\n";
90 const sal_Char pNumData[] = "0,";
91 const sal_Char pNumDataERROR[] = "0,0\nERROR\n";
93 OUStringBuffer aOS;
94 OUString aString;
95 SCCOL nEndCol = rRange.aEnd.Col();
96 SCROW nEndRow = rRange.aEnd.Row();
97 SCCOL nNumCols = nEndCol - rRange.aStart.Col() + 1;
98 SCROW nNumRows = nEndRow - rRange.aStart.Row() + 1;
99 SCTAB nTab = rRange.aStart.Tab();
101 ScProgress aPrgrsBar( pDoc->GetDocumentShell(), ScResId( STR_LOAD_DOC ), nNumRows, true );
103 aPrgrsBar.SetState( 0 );
105 // TABLE
106 OSL_ENSURE( pDoc->HasTable( nTab ), "*ScExportDif(): Table not existent!" );
108 aOS.append(pKeyTABLE);
109 aOS.append("\n0,1\n\"");
111 pDoc->GetName( nTab, aString );
112 aOS.append(aString);
113 aOS.append("\"\n");
114 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
116 // VECTORS
117 aOS.append(pKeyVECTORS);
118 aOS.append("\n0,");
119 aOS.append(static_cast<sal_Int32>(nNumCols));
120 aOS.append('\n');
121 aOS.append(p2DoubleQuotes_LF);
122 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
124 // TUPLES
125 aOS.append(pKeyTUPLES);
126 aOS.append("\n0,");
127 aOS.append(static_cast<sal_Int32>(nNumRows));
128 aOS.append('\n');
129 aOS.append(p2DoubleQuotes_LF);
130 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
132 // DATA
133 aOS.append(pKeyDATA);
134 aOS.append("\n0,0\n");
135 aOS.append(p2DoubleQuotes_LF);
136 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
138 SCCOL nColCnt;
139 SCROW nRowCnt;
141 for( nRowCnt = rRange.aStart.Row() ; nRowCnt <= nEndRow ; nRowCnt++ )
143 assert( aOS.isEmpty() && "aOS should be empty");
144 aOS.append(pSpecDataType_LF);
145 aOS.append(pKeyBOT);
146 aOS.append('\n');
147 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
148 for( nColCnt = rRange.aStart.Col() ; nColCnt <= nEndCol ; nColCnt++ )
150 assert( aOS.isEmpty() && "aOS should be empty");
151 bool bWriteStringData = false;
152 ScRefCellValue aCell(*pDoc, ScAddress(nColCnt, nRowCnt, nTab));
154 switch (aCell.meType)
156 case CELLTYPE_NONE:
157 aOS.append(pEmptyData);
158 break;
159 case CELLTYPE_VALUE:
160 aOS.append(pNumData);
161 pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
162 aOS.append(aString);
163 aOS.append("\nV\n");
164 break;
165 case CELLTYPE_EDIT:
166 case CELLTYPE_STRING:
167 aString = aCell.getString(pDoc);
168 bWriteStringData = true;
169 break;
170 case CELLTYPE_FORMULA:
171 if (aCell.mpFormula->GetErrCode() != FormulaError::NONE)
172 aOS.append(pNumDataERROR);
173 else if (aCell.mpFormula->IsValue())
175 aOS.append(pNumData);
176 pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
177 aOS.append(aString);
178 aOS.append("\nV\n");
180 else
182 aString = aCell.mpFormula->GetString().getString();
183 bWriteStringData = true;
186 break;
187 default:;
190 if ( !bWriteStringData )
191 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
192 else
194 // for an explanation why this complicated, see
195 // sc/source/ui/docsh.cxx:ScDocShell::AsciiSave()
196 // In fact we should create a common method if this would be
197 // needed just one more time...
198 assert( aOS.isEmpty() && "aOS should be empty");
199 OUString aTmpStr = aString;
200 aOS.append(pStringData);
201 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear(), eCharSet);
202 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
204 sal_Int32 nPos = aTmpStr.indexOf( cStrDelim );
205 while ( nPos != -1 )
207 aTmpStr = aTmpStr.replaceAt( nPos, 0, OUString(cStrDelim) );
208 nPos = aTmpStr.indexOf( cStrDelim, nPos+2 );
210 rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
211 write_uInt16s_FromOUString(rOut, aTmpStr);
212 rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
214 else if ( bContextOrNotAsciiEncoding )
216 // to byte encoding
217 OString aStrEnc = OUStringToOString(aTmpStr, eCharSet);
218 // back to Unicode
219 OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
220 // search on re-decoded string
221 sal_Int32 nPos = aStrDec.indexOf(aStrDelimDecoded);
222 while (nPos >= 0)
224 OUStringBuffer aBuf(aStrDec);
225 aBuf.insert(nPos, aStrDelimDecoded);
226 aStrDec = aBuf.makeStringAndClear();
227 nPos = aStrDec.indexOf(
228 aStrDelimDecoded, nPos+1+aStrDelimDecoded.getLength());
230 // write byte re-encoded
231 rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
232 rOut.WriteUnicodeOrByteText( aStrDec, eCharSet );
233 rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
235 else
237 OString aStrEnc = OUStringToOString(aTmpStr, eCharSet);
238 // search on encoded string
239 sal_Int32 nPos = aStrEnc.indexOf(aStrDelimEncoded);
240 while (nPos >= 0)
242 OStringBuffer aBuf(aStrEnc);
243 aBuf.insert(nPos, aStrDelimEncoded);
244 aStrEnc = aBuf.makeStringAndClear();
245 nPos = aStrEnc.indexOf(
246 aStrDelimEncoded, nPos+1+aStrDelimEncoded.getLength());
248 // write byte encoded
249 rOut.WriteBytes(aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
250 rOut.WriteBytes(aStrEnc.getStr(), aStrEnc.getLength());
251 rOut.WriteBytes(aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
253 rOut.WriteUniOrByteChar( '\n', eCharSet );
256 aPrgrsBar.SetState( nRowCnt );
259 assert( aOS.isEmpty() && "aOS should be empty");
260 aOS.append(pSpecDataType_LF);
261 aOS.append(pKeyEOD);
262 aOS.append('\n');
263 rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
265 // restore original value
266 rOut.SetStreamCharSet( eStreamCharSet );
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */