1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 #include "global.hxx"
30 #include "scresid.hxx"
31 #include "impex.hxx"
32 #include "asciiopt.hxx"
33 #include "asciiopt.hrc"
34 #include <tools/debug.hxx>
35 #include <rtl/tencinfo.h>
36 #include <unotools/transliterationwrapper.hxx>
37 // ause
38 #include "editutil.hxx"
39
40 // ============================================================================
41
42 static const sal_Char __FAR_DATA pStrFix[] = "FIX";
43 static const sal_Char __FAR_DATA pStrMrg[] = "MRG";
44
45
46 // ============================================================================
47
ScAsciiOptions()48 ScAsciiOptions::ScAsciiOptions() :
49 bFixedLen ( sal_False ),
50 aFieldSeps ( ';' ),
51 bMergeFieldSeps ( sal_False ),
52 bQuotedFieldAsText(false),
53 bDetectSpecialNumber(false),
54 cTextSep ( cDefaultTextSep ),
55 eCharSet ( gsl_getSystemTextEncoding() ),
56 eLang ( LANGUAGE_SYSTEM ),
57 bCharSetSystem ( sal_False ),
58 nStartRow ( 1 ),
59 nInfoCount ( 0 ),
60 pColStart ( NULL ),
61 pColFormat ( NULL )
62 {
63 }
64
65
ScAsciiOptions(const ScAsciiOptions & rOpt)66 ScAsciiOptions::ScAsciiOptions(const ScAsciiOptions& rOpt) :
67 bFixedLen ( rOpt.bFixedLen ),
68 aFieldSeps ( rOpt.aFieldSeps ),
69 bMergeFieldSeps ( rOpt.bMergeFieldSeps ),
70 bQuotedFieldAsText(rOpt.bQuotedFieldAsText),
71 bDetectSpecialNumber(rOpt.bDetectSpecialNumber),
72 cTextSep ( rOpt.cTextSep ),
73 eCharSet ( rOpt.eCharSet ),
74 eLang ( rOpt.eLang ),
75 bCharSetSystem ( rOpt.bCharSetSystem ),
76 nStartRow ( rOpt.nStartRow ),
77 nInfoCount ( rOpt.nInfoCount )
78 {
79 if (nInfoCount)
80 {
81 pColStart = new xub_StrLen[nInfoCount];
82 pColFormat = new sal_uInt8[nInfoCount];
83 for (sal_uInt16 i=0; i<nInfoCount; i++)
84 {
85 pColStart[i] = rOpt.pColStart[i];
86 pColFormat[i] = rOpt.pColFormat[i];
87 }
88 }
89 else
90 {
91 pColStart = NULL;
92 pColFormat = NULL;
93 }
94 }
95
96
~ScAsciiOptions()97 ScAsciiOptions::~ScAsciiOptions()
98 {
99 delete[] pColStart;
100 delete[] pColFormat;
101 }
102
103
SetColInfo(sal_uInt16 nCount,const xub_StrLen * pStart,const sal_uInt8 * pFormat)104 void ScAsciiOptions::SetColInfo( sal_uInt16 nCount, const xub_StrLen* pStart, const sal_uInt8* pFormat )
105 {
106 delete[] pColStart;
107 delete[] pColFormat;
108
109 nInfoCount = nCount;
110
111 if (nInfoCount)
112 {
113 pColStart = new xub_StrLen[nInfoCount];
114 pColFormat = new sal_uInt8[nInfoCount];
115 for (sal_uInt16 i=0; i<nInfoCount; i++)
116 {
117 pColStart[i] = pStart[i];
118 pColFormat[i] = pFormat[i];
119 }
120 }
121 else
122 {
123 pColStart = NULL;
124 pColFormat = NULL;
125 }
126 }
127
128
SetColumnInfo(const ScCsvExpDataVec & rDataVec)129 void ScAsciiOptions::SetColumnInfo( const ScCsvExpDataVec& rDataVec )
130 {
131 delete[] pColStart;
132 pColStart = NULL;
133 delete[] pColFormat;
134 pColFormat = NULL;
135
136 nInfoCount = static_cast< sal_uInt16 >( rDataVec.size() );
137 if( nInfoCount )
138 {
139 pColStart = new xub_StrLen[ nInfoCount ];
140 pColFormat = new sal_uInt8[ nInfoCount ];
141 for( sal_uInt16 nIx = 0; nIx < nInfoCount; ++nIx )
142 {
143 pColStart[ nIx ] = rDataVec[ nIx ].mnIndex;
144 pColFormat[ nIx ] = rDataVec[ nIx ].mnType;
145 }
146 }
147 }
148
149
operator =(const ScAsciiOptions & rCpy)150 ScAsciiOptions& ScAsciiOptions::operator=( const ScAsciiOptions& rCpy )
151 {
152 SetColInfo( rCpy.nInfoCount, rCpy.pColStart, rCpy.pColFormat );
153
154 bFixedLen = rCpy.bFixedLen;
155 aFieldSeps = rCpy.aFieldSeps;
156 bMergeFieldSeps = rCpy.bMergeFieldSeps;
157 bQuotedFieldAsText = rCpy.bQuotedFieldAsText;
158 cTextSep = rCpy.cTextSep;
159 eCharSet = rCpy.eCharSet;
160 bCharSetSystem = rCpy.bCharSetSystem;
161 nStartRow = rCpy.nStartRow;
162
163 return *this;
164 }
165
166
operator ==(const ScAsciiOptions & rCmp) const167 sal_Bool ScAsciiOptions::operator==( const ScAsciiOptions& rCmp ) const
168 {
169 if ( bFixedLen == rCmp.bFixedLen &&
170 aFieldSeps == rCmp.aFieldSeps &&
171 bMergeFieldSeps == rCmp.bMergeFieldSeps &&
172 bQuotedFieldAsText == rCmp.bQuotedFieldAsText &&
173 cTextSep == rCmp.cTextSep &&
174 eCharSet == rCmp.eCharSet &&
175 bCharSetSystem == rCmp.bCharSetSystem &&
176 nStartRow == rCmp.nStartRow &&
177 nInfoCount == rCmp.nInfoCount )
178 {
179 DBG_ASSERT( !nInfoCount || (pColStart && pColFormat && rCmp.pColStart && rCmp.pColFormat),
180 "0-Zeiger in ScAsciiOptions" );
181 for (sal_uInt16 i=0; i<nInfoCount; i++)
182 if ( pColStart[i] != rCmp.pColStart[i] ||
183 pColFormat[i] != rCmp.pColFormat[i] )
184 return sal_False;
185
186 return sal_True;
187 }
188 return sal_False;
189 }
190
191 //
192 // Der Options-String darf kein Semikolon mehr enthalten (wegen Pickliste)
193 // darum ab Version 336 Komma stattdessen
194 //
195
196
ReadFromString(const String & rString)197 void ScAsciiOptions::ReadFromString( const String& rString )
198 {
199 xub_StrLen nCount = rString.GetTokenCount(',');
200 String aToken;
201 xub_StrLen nSub;
202 xub_StrLen i;
203
204 //
205 // Feld-Trenner
206 //
207
208 if ( nCount >= 1 )
209 {
210 bFixedLen = bMergeFieldSeps = sal_False;
211 aFieldSeps.Erase();
212
213 aToken = rString.GetToken(0,',');
214 if ( aToken.EqualsAscii(pStrFix) )
215 bFixedLen = sal_True;
216 nSub = aToken.GetTokenCount('/');
217 for ( i=0; i<nSub; i++ )
218 {
219 String aCode = aToken.GetToken( i, '/' );
220 if ( aCode.EqualsAscii(pStrMrg) )
221 bMergeFieldSeps = sal_True;
222 else
223 {
224 sal_Int32 nVal = aCode.ToInt32();
225 if ( nVal )
226 aFieldSeps += (sal_Unicode) nVal;
227 }
228 }
229 }
230
231 //
232 // Text-Trenner
233 //
234
235 if ( nCount >= 2 )
236 {
237 aToken = rString.GetToken(1,',');
238 sal_Int32 nVal = aToken.ToInt32();
239 cTextSep = (sal_Unicode) nVal;
240 }
241
242 //
243 // Zeichensatz
244 //
245
246 if ( nCount >= 3 )
247 {
248 aToken = rString.GetToken(2,',');
249 eCharSet = ScGlobal::GetCharsetValue( aToken );
250 }
251
252 //
253 // Startzeile
254 //
255
256 if ( nCount >= 4 )
257 {
258 aToken = rString.GetToken(3,',');
259 nStartRow = aToken.ToInt32();
260 }
261
262 //
263 // Spalten-Infos
264 //
265
266 if ( nCount >= 5 )
267 {
268 delete[] pColStart;
269 delete[] pColFormat;
270
271 aToken = rString.GetToken(4,',');
272 nSub = aToken.GetTokenCount('/');
273 nInfoCount = nSub / 2;
274 if (nInfoCount)
275 {
276 pColStart = new xub_StrLen[nInfoCount];
277 pColFormat = new sal_uInt8[nInfoCount];
278 for (sal_uInt16 nInfo=0; nInfo<nInfoCount; nInfo++)
279 {
280 pColStart[nInfo] = (xub_StrLen) aToken.GetToken( 2*nInfo, '/' ).ToInt32();
281 pColFormat[nInfo] = (sal_uInt8) aToken.GetToken( 2*nInfo+1, '/' ).ToInt32();
282 }
283 }
284 else
285 {
286 pColStart = NULL;
287 pColFormat = NULL;
288 }
289 }
290
291 // Language
292 if (nCount >= 6)
293 {
294 aToken = rString.GetToken(5, ',');
295 eLang = static_cast<LanguageType>(aToken.ToInt32());
296 }
297
298 // Import quoted field as text.
299 if (nCount >= 7)
300 {
301 aToken = rString.GetToken(6, ',');
302 bQuotedFieldAsText = aToken.EqualsAscii("true") ? true : false;
303 }
304
305 // Detect special numbers.
306 if (nCount >= 8)
307 {
308 aToken = rString.GetToken(7, ',');
309 bDetectSpecialNumber = aToken.EqualsAscii("true") ? true : false;
310 }
311 else
312 bDetectSpecialNumber = sal_True; // default of versions that didn't add the parameter
313
314 // 9th token is used for "Save as shown" in export options
315 }
316
317
WriteToString() const318 String ScAsciiOptions::WriteToString() const
319 {
320 String aOutStr;
321
322 //
323 // Feld-Trenner
324 //
325
326 if ( bFixedLen )
327 aOutStr.AppendAscii(pStrFix);
328 else if ( !aFieldSeps.Len() )
329 aOutStr += '0';
330 else
331 {
332 xub_StrLen nLen = aFieldSeps.Len();
333 for (xub_StrLen i=0; i<nLen; i++)
334 {
335 if (i)
336 aOutStr += '/';
337 aOutStr += String::CreateFromInt32(aFieldSeps.GetChar(i));
338 }
339 if ( bMergeFieldSeps )
340 {
341 aOutStr += '/';
342 aOutStr.AppendAscii(pStrMrg);
343 }
344 }
345
346 aOutStr += ','; // Token-Ende
347
348 //
349 // Text-Trenner
350 //
351
352 aOutStr += String::CreateFromInt32(cTextSep);
353 aOutStr += ','; // Token-Ende
354
355 //
356 // Zeichensatz
357 //
358
359 if ( bCharSetSystem ) // force "SYSTEM"
360 aOutStr += ScGlobal::GetCharsetString( RTL_TEXTENCODING_DONTKNOW );
361 else
362 aOutStr += ScGlobal::GetCharsetString( eCharSet );
363 aOutStr += ','; // Token-Ende
364
365 //
366 // Startzeile
367 //
368
369 aOutStr += String::CreateFromInt32(nStartRow);
370 aOutStr += ','; // Token-Ende
371
372 //
373 // Spalten-Infos
374 //
375
376 DBG_ASSERT( !nInfoCount || (pColStart && pColFormat), "0-Zeiger in ScAsciiOptions" );
377 for (sal_uInt16 nInfo=0; nInfo<nInfoCount; nInfo++)
378 {
379 if (nInfo)
380 aOutStr += '/';
381 aOutStr += String::CreateFromInt32(pColStart[nInfo]);
382 aOutStr += '/';
383 aOutStr += String::CreateFromInt32(pColFormat[nInfo]);
384 }
385
386 // #i112025# the options string is used in macros and linked sheets,
387 // so new options must be added at the end, to remain compatible
388
389 aOutStr += ',';
390
391 // Language
392 aOutStr += String::CreateFromInt32(eLang);
393 aOutStr += ',';
394
395 // Import quoted field as text.
396 aOutStr += String::CreateFromAscii(bQuotedFieldAsText ? "true" : "false");
397 aOutStr += ',';
398
399 // Detect special numbers.
400 aOutStr += String::CreateFromAscii(bDetectSpecialNumber ? "true" : "false");
401
402 // 9th token is used for "Save as shown" in export options
403
404 return aOutStr;
405 }
406
407 #if 0
408 // Code, um die Spalten-Liste aus einem Excel-kompatiblen String zu erzeugen:
409 // (im Moment nicht benutzt)
410
411 void ScAsciiOptions::InterpretColumnList( const String& rString )
412 {
413 // Eingabe ist 1-basiert, pColStart fuer FixedLen ist 0-basiert
414
415 // Kommas durch Semikolon ersetzen
416
417 String aSemiStr = rString;
418 sal_uInt16 nPos = 0;
419 do
420 nPos = aSemiStr.SearchAndReplace( ',', ';', nPos );
421 while ( nPos != STRING_NOTFOUND );
422
423 // Eintraege sortieren
424
425 sal_uInt16 nCount = aSemiStr.GetTokenCount();
426 sal_uInt16* pTemp = new sal_uInt16[nCount+1];
427 pTemp[0] = 1; // erste Spalte faengt immer bei 1 an
428 sal_uInt16 nFound = 1;
429 sal_uInt16 i,j;
430 for (i=0; i<nCount; i++)
431 {
432 sal_uInt16 nVal = (sal_uInt16) aSemiStr.GetToken(i);
433 if (nVal)
434 {
435 sal_Bool bThere = sal_False;
436 nPos = 0;
437 for (j=0; j<nFound; j++)
438 {
439 if ( pTemp[j] == nVal )
440 bThere = sal_True;
441 else if ( pTemp[j] < nVal )
442 nPos = j+1;
443 }
444 if ( !bThere )
445 {
446 if ( nPos < nFound )
447 memmove( &pTemp[nPos+1], &pTemp[nPos], (nFound-nPos)*sizeof(sal_uInt16) );
448 pTemp[nPos] = nVal;
449 ++nFound;
450 }
451 }
452 }
453
454 // Eintraege uebernehmen
455
456 delete[] pColStart;
457 delete[] pColFormat;
458 nInfoCount = nFound;
459 if (nInfoCount)
460 {
461 pColStart = new sal_uInt16[nInfoCount];
462 pColFormat = new sal_uInt8[nInfoCount];
463 for (i=0; i<nInfoCount; i++)
464 {
465 pColStart[i] = pTemp[i] - 1;
466 pColFormat[i] = SC_COL_STANDARD;
467 }
468 }
469 else
470 {
471 pColStart = NULL;
472 pColFormat = NULL;
473 }
474
475 bFixedLen = sal_True; // sonst macht's keinen Sinn
476
477 // aufraeumen
478
479 delete[] pTemp;
480 }
481 #endif
482
483