xref: /AOO41X/main/sc/source/ui/dbgui/asciiopt.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 nubmers.
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 nubmers.
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