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