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