xref: /trunk/main/sc/source/ui/dbgui/asciiopt.cxx (revision b3f79822)
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 
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 
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 
97 ScAsciiOptions::~ScAsciiOptions()
98 {
99 	delete[] pColStart;
100 	delete[] pColFormat;
101 }
102 
103 
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 
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 
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 
167 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 
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 
318 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