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