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_l10ntools.hxx" 30 #include <tools/fsys.hxx> 31 32 // local includes 33 #include "lngmerge.hxx" 34 #include "utf8conv.hxx" 35 #include <iostream> 36 using namespace std; 37 // 38 // class LngParser 39 // 40 /*****************************************************************************/ 41 LngParser::LngParser( const ByteString &rLngFile, sal_Bool bUTF8, sal_Bool bULFFormat ) 42 /*****************************************************************************/ 43 : 44 nError( LNG_OK ), 45 pLines( NULL ), 46 sSource( rLngFile ), 47 bDBIsUTF8( bUTF8 ), 48 bULF( bULFFormat ) 49 { 50 pLines = new LngLineList( 100, 100 ); 51 DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US )); 52 if ( aEntry.Exists()) { 53 SvFileStream aStream( String( sSource, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ ); 54 if ( aStream.IsOpen()) { 55 ByteString sLine; 56 bool bFirstLine = true; 57 while ( !aStream.IsEof()) { 58 aStream.ReadLine( sLine ); 59 60 if( bFirstLine ){ // Always remove UTF8 BOM from the first line 61 Export::RemoveUTF8ByteOrderMarker( sLine ); 62 bFirstLine = false; 63 } 64 65 pLines->Insert( new ByteString( sLine ), LIST_APPEND ); 66 } 67 } 68 else 69 nError = LNG_COULD_NOT_OPEN; 70 } 71 else 72 nError = LNG_FILE_NOTFOUND; 73 } 74 75 /*****************************************************************************/ 76 LngParser::~LngParser() 77 /*****************************************************************************/ 78 { 79 for ( sal_uLong i = 0; i < pLines->Count(); i++ ) 80 delete pLines->GetObject( i ); 81 delete pLines; 82 } 83 84 /*****************************************************************************/ 85 void LngParser::FillInFallbacks( ByteStringHashMap Text ) 86 /*****************************************************************************/ 87 { 88 ByteString sCur; 89 for( unsigned int n = 0; n < aLanguages.size(); n++ ){ 90 sCur = aLanguages[ n ]; 91 92 if( Export::isAllowed( sCur ) ){ 93 ByteString sFallbackLang = Export::GetFallbackLanguage( sCur ); 94 if( sFallbackLang.Len() ){ 95 Text[ sCur ] = Text[ sFallbackLang ]; 96 } 97 } 98 } 99 } 100 101 /*****************************************************************************/ 102 sal_Bool LngParser::CreateSDF( 103 const ByteString &rSDFFile, const ByteString &rPrj, 104 const ByteString &rRoot ) 105 /*****************************************************************************/ 106 { 107 108 Export::InitLanguages( false ); 109 aLanguages = Export::GetLanguages(); 110 SvFileStream aSDFStream( String( rSDFFile, RTL_TEXTENCODING_ASCII_US ), 111 STREAM_STD_WRITE | STREAM_TRUNC ); 112 if ( !aSDFStream.IsOpen()) { 113 nError = SDF_COULD_NOT_OPEN; 114 } 115 aSDFStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 ); 116 nError = SDF_OK; 117 DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US )); 118 aEntry.ToAbs(); 119 String sFullEntry = aEntry.GetFull(); 120 aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US )); 121 aEntry += DirEntry( rRoot ); 122 ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding()); 123 ByteString sActFileName( 124 sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding()); 125 sActFileName.SearchAndReplaceAll( "/", "\\" ); 126 127 sal_uLong nPos = 0; 128 sal_Bool bStart = true; 129 ByteString sGroup; 130 ByteStringHashMap Text; 131 ByteString sID; 132 ByteString sLine; 133 134 while( nPos < pLines->Count() ){ 135 sLine = *pLines->GetObject( nPos++ ); 136 while( nPos < pLines->Count() && !isNextGroup( sGroup , sLine ) ){ 137 ReadLine( sLine , Text ); 138 sID = sGroup; 139 sLine = *pLines->GetObject( nPos++ ); 140 }; 141 if( bStart ){ 142 bStart = false; 143 sID = sGroup; 144 } 145 else { 146 147 WriteSDF( aSDFStream , Text , rPrj , rRoot , sActFileName , sID ); 148 } 149 } 150 aSDFStream.Close(); 151 return true; 152 } 153 154 void LngParser::WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout , 155 const ByteString &rPrj , const ByteString &rRoot , 156 const ByteString &sActFileName , const ByteString &sID ) 157 { 158 159 sal_Bool bExport = true; 160 if ( bExport ) { 161 ByteString sTimeStamp( Export::GetTimeStamp()); 162 ByteString sCur; 163 FillInFallbacks( rText_inout ); 164 for( unsigned int n = 0; n < aLanguages.size(); n++ ){ 165 sCur = aLanguages[ n ]; 166 ByteString sAct = rText_inout[ sCur ]; 167 if ( !sAct.Len() && sCur.Len() ) 168 sAct = rText_inout[ ByteString("en-US") ]; 169 170 ByteString sOutput( rPrj ); sOutput += "\t"; 171 if ( rRoot.Len()) 172 sOutput += sActFileName; 173 sOutput += "\t0\t"; 174 sOutput += "LngText\t"; 175 sOutput += sID; sOutput += "\t\t\t\t0\t"; 176 sOutput += sCur; sOutput += "\t"; 177 sOutput += sAct; sOutput += "\t\t\t\t"; 178 sOutput += sTimeStamp; 179 //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( rPrj ) ) ) 180 aSDFStream.WriteLine( sOutput ); 181 } 182 } 183 } 184 bool LngParser::isNextGroup( ByteString &sGroup_out , ByteString &sLine_in ){ 185 sLine_in.EraseLeadingChars( ' ' ); 186 sLine_in.EraseTrailingChars( ' ' ); 187 if (( sLine_in.GetChar( 0 ) == '[' ) && 188 ( sLine_in.GetChar( sLine_in.Len() - 1 ) == ']' )){ 189 sGroup_out = sLine_in.GetToken( 1, '[' ).GetToken( 0, ']' ); 190 sGroup_out.EraseLeadingChars( ' ' ); 191 sGroup_out.EraseTrailingChars( ' ' ); 192 return true; 193 } 194 return false; 195 } 196 void LngParser::ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout){ 197 //printf("sLine -> '%s'\n",sLine_in.GetBuffer()); 198 ByteString sLang = sLine_in.GetToken( 0, '=' ); 199 sLang.EraseLeadingChars( ' ' ); 200 sLang.EraseTrailingChars( ' ' ); 201 ByteString sText = sLine_in.GetToken( 1, '\"' ).GetToken( 0, '\"' ); 202 if( sLang.Len() ) 203 rText_inout[ sLang ] = sText; 204 } 205 206 /*****************************************************************************/ 207 sal_Bool LngParser::Merge( 208 const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString& rPrj ) 209 /*****************************************************************************/ 210 { 211 (void) rPrj; 212 Export::InitLanguages( true ); 213 SvFileStream aDestination( 214 String( rDestinationFile, RTL_TEXTENCODING_ASCII_US ), 215 STREAM_STD_WRITE | STREAM_TRUNC ); 216 if ( !aDestination.IsOpen()) { 217 nError = LNG_COULD_NOT_OPEN; 218 } 219 nError = LNG_OK; 220 // MergeDataFile( const ByteString &rFileName, const ByteString& rFile , sal_Bool bErrLog, CharSet aCharSet, sal_Bool bUTF8 ); 221 222 MergeDataFile aMergeDataFile( rSDFFile, sSource , sal_False, RTL_TEXTENCODING_MS_1252);//, bDBIsUTF8 ); 223 ByteString sTmp( Export::sLanguages ); 224 if( sTmp.ToUpperAscii().Equals("ALL") ) 225 Export::SetLanguages( aMergeDataFile.GetLanguages() ); 226 aLanguages = Export::GetLanguages(); 227 228 sal_uLong nPos = 0; 229 sal_Bool bGroup = sal_False; 230 ByteString sGroup; 231 232 // seek to next group 233 while ( nPos < pLines->Count() && !bGroup ) { 234 ByteString sLine( *pLines->GetObject( nPos )); 235 sLine.EraseLeadingChars( ' ' ); 236 sLine.EraseTrailingChars( ' ' ); 237 if (( sLine.GetChar( 0 ) == '[' ) && 238 ( sLine.GetChar( sLine.Len() - 1 ) == ']' )) 239 { 240 sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' ); 241 sGroup.EraseLeadingChars( ' ' ); 242 sGroup.EraseTrailingChars( ' ' ); 243 bGroup = sal_True; 244 } 245 nPos ++; 246 } 247 248 while ( nPos < pLines->Count()) { 249 ByteStringHashMap Text; 250 ByteString sID( sGroup ); 251 sal_uLong nLastLangPos = 0; 252 253 ResData *pResData = new ResData( "", sID , sSource ); 254 pResData->sResTyp = "LngText"; 255 PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData ); 256 // read languages 257 bGroup = sal_False; 258 259 ByteString sLanguagesDone; 260 261 while ( nPos < pLines->Count() && !bGroup ) { 262 ByteString sLine( *pLines->GetObject( nPos )); 263 sLine.EraseLeadingChars( ' ' ); 264 sLine.EraseTrailingChars( ' ' ); 265 if (( sLine.GetChar( 0 ) == '[' ) && 266 ( sLine.GetChar( sLine.Len() - 1 ) == ']' )) 267 { 268 sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' ); 269 sGroup.EraseLeadingChars( ' ' ); 270 sGroup.EraseTrailingChars( ' ' ); 271 bGroup = sal_True; 272 nPos ++; 273 sLanguagesDone = ""; 274 } 275 else if ( sLine.GetTokenCount( '=' ) > 1 ) { 276 ByteString sLang = sLine.GetToken( 0, '=' ); 277 sLang.EraseLeadingChars( ' ' ); 278 sLang.EraseTrailingChars( ' ' ); 279 280 ByteString sSearch( ";" ); 281 sSearch += sLang; 282 sSearch += ";"; 283 284 if (( sLanguagesDone.Search( sSearch ) != STRING_NOTFOUND )) { 285 pLines->Remove( nPos ); 286 } 287 if( bULF && pEntrys ) 288 { 289 // this is a valid text line 290 ByteString sText = sLine.GetToken( 1, '\"' ).GetToken( 0, '\"' ); 291 if( sLang.Len() ){ 292 ByteString sNewText; 293 pEntrys->GetText( sNewText, STRING_TYP_TEXT, sLang, sal_True ); 294 295 if ( sNewText.Len()) { 296 ByteString *pLine = pLines->GetObject( nPos ); 297 298 ByteString sText1( sLang ); 299 sText1 += " = \""; 300 sText1 += sNewText; 301 sText1 += "\""; 302 *pLine = sText1; 303 //} 304 Text[ sLang ] = sNewText; 305 } 306 } 307 nLastLangPos = nPos; 308 nPos ++; 309 sLanguagesDone += sSearch; 310 } 311 else { 312 nLastLangPos = nPos; 313 nPos ++; 314 sLanguagesDone += sSearch; 315 } 316 } 317 else 318 nPos++; 319 } 320 ByteString sCur; 321 if ( nLastLangPos ) { 322 for( unsigned int n = 0; n < aLanguages.size(); n++ ){ 323 sCur = aLanguages[ n ]; 324 if( //( !sCur.EqualsIgnoreCaseAscii("de") || 325 //( sCur.EqualsIgnoreCaseAscii("de") && Export::isMergingGermanAllowed( rPrj ) ) ) 326 !sCur.EqualsIgnoreCaseAscii("en-US") && !Text[ sCur ].Len() && pEntrys ){ 327 328 ByteString sNewText; 329 pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur, sal_True ); 330 if (( sNewText.Len()) && 331 !(( sCur.Equals("x-comment") ) && ( sNewText == "-" ))) 332 { 333 ByteString sLine; 334 sLine += sCur; 335 sLine += " = \""; 336 sLine += sNewText; 337 sLine += "\""; 338 339 nLastLangPos++; 340 nPos++; 341 342 pLines->Insert( new ByteString( sLine ), nLastLangPos ); 343 } 344 } 345 } 346 } 347 348 delete pResData; 349 } 350 351 for ( sal_uLong i = 0; i < pLines->Count(); i++ ) 352 aDestination.WriteLine( *pLines->GetObject( i )); 353 354 aDestination.Close(); 355 return sal_True; 356 } 357