xref: /trunk/main/l10ntools/source/lngmerge.cxx (revision cdf0e10c)
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