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