xref: /trunk/main/l10ntools/source/lngmerge.cxx (revision 3cd96b95)
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 /*****************************************************************************/
LngParser(const ByteString & rLngFile,sal_Bool bUTF8,sal_Bool bULFFormat)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 /*****************************************************************************/
~LngParser()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 /*****************************************************************************/
FillInFallbacks(ByteStringHashMap Text)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 /*****************************************************************************/
CreateSDF(const ByteString & rSDFFile,const ByteString & rPrj,const ByteString & rRoot)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 
WriteSDF(SvFileStream & aSDFStream,ByteStringHashMap & rText_inout,const ByteString & rPrj,const ByteString & rRoot,const ByteString & sActFileName,const ByteString & sID)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  }
isNextGroup(ByteString & sGroup_out,ByteString & sLine_in)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  }
ReadLine(const ByteString & sLine_in,ByteStringHashMap & rText_inout)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 /*****************************************************************************/
Merge(const ByteString & rSDFFile,const ByteString & rDestinationFile,const ByteString & rPrj)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