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