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