1*3cd96b95SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*3cd96b95SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*3cd96b95SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*3cd96b95SAndrew Rist * distributed with this work for additional information
6*3cd96b95SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*3cd96b95SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*3cd96b95SAndrew Rist * "License"); you may not use this file except in compliance
9*3cd96b95SAndrew Rist * with the License. You may obtain a copy of the License at
10*3cd96b95SAndrew Rist *
11*3cd96b95SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*3cd96b95SAndrew Rist *
13*3cd96b95SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*3cd96b95SAndrew Rist * software distributed under the License is distributed on an
15*3cd96b95SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*3cd96b95SAndrew Rist * KIND, either express or implied. See the License for the
17*3cd96b95SAndrew Rist * specific language governing permissions and limitations
18*3cd96b95SAndrew Rist * under the License.
19*3cd96b95SAndrew Rist *
20*3cd96b95SAndrew Rist *************************************************************/
21*3cd96b95SAndrew Rist
22*3cd96b95SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_l10ntools.hxx"
26cdf0e10cSrcweir #include <tools/fsys.hxx>
27cdf0e10cSrcweir
28cdf0e10cSrcweir // local includes
29cdf0e10cSrcweir #include "lngmerge.hxx"
30cdf0e10cSrcweir #include "utf8conv.hxx"
31cdf0e10cSrcweir #include <iostream>
32cdf0e10cSrcweir using namespace std;
33cdf0e10cSrcweir //
34cdf0e10cSrcweir // class LngParser
35cdf0e10cSrcweir //
36cdf0e10cSrcweir /*****************************************************************************/
LngParser(const ByteString & rLngFile,sal_Bool bUTF8,sal_Bool bULFFormat)37cdf0e10cSrcweir LngParser::LngParser( const ByteString &rLngFile, sal_Bool bUTF8, sal_Bool bULFFormat )
38cdf0e10cSrcweir /*****************************************************************************/
39cdf0e10cSrcweir :
40cdf0e10cSrcweir nError( LNG_OK ),
41cdf0e10cSrcweir pLines( NULL ),
42cdf0e10cSrcweir sSource( rLngFile ),
43cdf0e10cSrcweir bDBIsUTF8( bUTF8 ),
44cdf0e10cSrcweir bULF( bULFFormat )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir pLines = new LngLineList( 100, 100 );
47cdf0e10cSrcweir DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
48cdf0e10cSrcweir if ( aEntry.Exists()) {
49cdf0e10cSrcweir SvFileStream aStream( String( sSource, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
50cdf0e10cSrcweir if ( aStream.IsOpen()) {
51cdf0e10cSrcweir ByteString sLine;
52cdf0e10cSrcweir bool bFirstLine = true;
53cdf0e10cSrcweir while ( !aStream.IsEof()) {
54cdf0e10cSrcweir aStream.ReadLine( sLine );
55cdf0e10cSrcweir
56cdf0e10cSrcweir if( bFirstLine ){ // Always remove UTF8 BOM from the first line
57cdf0e10cSrcweir Export::RemoveUTF8ByteOrderMarker( sLine );
58cdf0e10cSrcweir bFirstLine = false;
59cdf0e10cSrcweir }
60cdf0e10cSrcweir
61cdf0e10cSrcweir pLines->Insert( new ByteString( sLine ), LIST_APPEND );
62cdf0e10cSrcweir }
63cdf0e10cSrcweir }
64cdf0e10cSrcweir else
65cdf0e10cSrcweir nError = LNG_COULD_NOT_OPEN;
66cdf0e10cSrcweir }
67cdf0e10cSrcweir else
68cdf0e10cSrcweir nError = LNG_FILE_NOTFOUND;
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
71cdf0e10cSrcweir /*****************************************************************************/
~LngParser()72cdf0e10cSrcweir LngParser::~LngParser()
73cdf0e10cSrcweir /*****************************************************************************/
74cdf0e10cSrcweir {
75cdf0e10cSrcweir for ( sal_uLong i = 0; i < pLines->Count(); i++ )
76cdf0e10cSrcweir delete pLines->GetObject( i );
77cdf0e10cSrcweir delete pLines;
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
80cdf0e10cSrcweir /*****************************************************************************/
FillInFallbacks(ByteStringHashMap Text)81cdf0e10cSrcweir void LngParser::FillInFallbacks( ByteStringHashMap Text )
82cdf0e10cSrcweir /*****************************************************************************/
83cdf0e10cSrcweir {
84cdf0e10cSrcweir ByteString sCur;
85cdf0e10cSrcweir for( unsigned int n = 0; n < aLanguages.size(); n++ ){
86cdf0e10cSrcweir sCur = aLanguages[ n ];
87cdf0e10cSrcweir
88cdf0e10cSrcweir if( Export::isAllowed( sCur ) ){
89cdf0e10cSrcweir ByteString sFallbackLang = Export::GetFallbackLanguage( sCur );
90cdf0e10cSrcweir if( sFallbackLang.Len() ){
91cdf0e10cSrcweir Text[ sCur ] = Text[ sFallbackLang ];
92cdf0e10cSrcweir }
93cdf0e10cSrcweir }
94cdf0e10cSrcweir }
95cdf0e10cSrcweir }
96cdf0e10cSrcweir
97cdf0e10cSrcweir /*****************************************************************************/
CreateSDF(const ByteString & rSDFFile,const ByteString & rPrj,const ByteString & rRoot)98cdf0e10cSrcweir sal_Bool LngParser::CreateSDF(
99cdf0e10cSrcweir const ByteString &rSDFFile, const ByteString &rPrj,
100cdf0e10cSrcweir const ByteString &rRoot )
101cdf0e10cSrcweir /*****************************************************************************/
102cdf0e10cSrcweir {
103cdf0e10cSrcweir
104cdf0e10cSrcweir Export::InitLanguages( false );
105cdf0e10cSrcweir aLanguages = Export::GetLanguages();
106cdf0e10cSrcweir SvFileStream aSDFStream( String( rSDFFile, RTL_TEXTENCODING_ASCII_US ),
107cdf0e10cSrcweir STREAM_STD_WRITE | STREAM_TRUNC );
108cdf0e10cSrcweir if ( !aSDFStream.IsOpen()) {
109cdf0e10cSrcweir nError = SDF_COULD_NOT_OPEN;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir aSDFStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
112cdf0e10cSrcweir nError = SDF_OK;
113cdf0e10cSrcweir DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
114cdf0e10cSrcweir aEntry.ToAbs();
115cdf0e10cSrcweir String sFullEntry = aEntry.GetFull();
116cdf0e10cSrcweir aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
117cdf0e10cSrcweir aEntry += DirEntry( rRoot );
118cdf0e10cSrcweir ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
119cdf0e10cSrcweir ByteString sActFileName(
120cdf0e10cSrcweir sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
121cdf0e10cSrcweir sActFileName.SearchAndReplaceAll( "/", "\\" );
122cdf0e10cSrcweir
123cdf0e10cSrcweir sal_uLong nPos = 0;
124cdf0e10cSrcweir sal_Bool bStart = true;
125cdf0e10cSrcweir ByteString sGroup;
126cdf0e10cSrcweir ByteStringHashMap Text;
127cdf0e10cSrcweir ByteString sID;
128cdf0e10cSrcweir ByteString sLine;
129cdf0e10cSrcweir
130cdf0e10cSrcweir while( nPos < pLines->Count() ){
131cdf0e10cSrcweir sLine = *pLines->GetObject( nPos++ );
132cdf0e10cSrcweir while( nPos < pLines->Count() && !isNextGroup( sGroup , sLine ) ){
133cdf0e10cSrcweir ReadLine( sLine , Text );
134cdf0e10cSrcweir sID = sGroup;
135cdf0e10cSrcweir sLine = *pLines->GetObject( nPos++ );
136cdf0e10cSrcweir };
137cdf0e10cSrcweir if( bStart ){
138cdf0e10cSrcweir bStart = false;
139cdf0e10cSrcweir sID = sGroup;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir else {
142cdf0e10cSrcweir
143cdf0e10cSrcweir WriteSDF( aSDFStream , Text , rPrj , rRoot , sActFileName , sID );
144cdf0e10cSrcweir }
145cdf0e10cSrcweir }
146cdf0e10cSrcweir aSDFStream.Close();
147cdf0e10cSrcweir return true;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir
WriteSDF(SvFileStream & aSDFStream,ByteStringHashMap & rText_inout,const ByteString & rPrj,const ByteString & rRoot,const ByteString & sActFileName,const ByteString & sID)150cdf0e10cSrcweir void LngParser::WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout ,
151cdf0e10cSrcweir const ByteString &rPrj , const ByteString &rRoot ,
152cdf0e10cSrcweir const ByteString &sActFileName , const ByteString &sID )
153cdf0e10cSrcweir {
154cdf0e10cSrcweir
155cdf0e10cSrcweir sal_Bool bExport = true;
156cdf0e10cSrcweir if ( bExport ) {
157cdf0e10cSrcweir ByteString sTimeStamp( Export::GetTimeStamp());
158cdf0e10cSrcweir ByteString sCur;
159cdf0e10cSrcweir FillInFallbacks( rText_inout );
160cdf0e10cSrcweir for( unsigned int n = 0; n < aLanguages.size(); n++ ){
161cdf0e10cSrcweir sCur = aLanguages[ n ];
162cdf0e10cSrcweir ByteString sAct = rText_inout[ sCur ];
163cdf0e10cSrcweir if ( !sAct.Len() && sCur.Len() )
164cdf0e10cSrcweir sAct = rText_inout[ ByteString("en-US") ];
165cdf0e10cSrcweir
166cdf0e10cSrcweir ByteString sOutput( rPrj ); sOutput += "\t";
167cdf0e10cSrcweir if ( rRoot.Len())
168cdf0e10cSrcweir sOutput += sActFileName;
169cdf0e10cSrcweir sOutput += "\t0\t";
170cdf0e10cSrcweir sOutput += "LngText\t";
171cdf0e10cSrcweir sOutput += sID; sOutput += "\t\t\t\t0\t";
172cdf0e10cSrcweir sOutput += sCur; sOutput += "\t";
173cdf0e10cSrcweir sOutput += sAct; sOutput += "\t\t\t\t";
174cdf0e10cSrcweir sOutput += sTimeStamp;
175cdf0e10cSrcweir //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( rPrj ) ) )
176cdf0e10cSrcweir aSDFStream.WriteLine( sOutput );
177cdf0e10cSrcweir }
178cdf0e10cSrcweir }
179cdf0e10cSrcweir }
isNextGroup(ByteString & sGroup_out,ByteString & sLine_in)180cdf0e10cSrcweir bool LngParser::isNextGroup( ByteString &sGroup_out , ByteString &sLine_in ){
181cdf0e10cSrcweir sLine_in.EraseLeadingChars( ' ' );
182cdf0e10cSrcweir sLine_in.EraseTrailingChars( ' ' );
183cdf0e10cSrcweir if (( sLine_in.GetChar( 0 ) == '[' ) &&
184cdf0e10cSrcweir ( sLine_in.GetChar( sLine_in.Len() - 1 ) == ']' )){
185cdf0e10cSrcweir sGroup_out = sLine_in.GetToken( 1, '[' ).GetToken( 0, ']' );
186cdf0e10cSrcweir sGroup_out.EraseLeadingChars( ' ' );
187cdf0e10cSrcweir sGroup_out.EraseTrailingChars( ' ' );
188cdf0e10cSrcweir return true;
189cdf0e10cSrcweir }
190cdf0e10cSrcweir return false;
191cdf0e10cSrcweir }
ReadLine(const ByteString & sLine_in,ByteStringHashMap & rText_inout)192cdf0e10cSrcweir void LngParser::ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout){
193cdf0e10cSrcweir //printf("sLine -> '%s'\n",sLine_in.GetBuffer());
194cdf0e10cSrcweir ByteString sLang = sLine_in.GetToken( 0, '=' );
195cdf0e10cSrcweir sLang.EraseLeadingChars( ' ' );
196cdf0e10cSrcweir sLang.EraseTrailingChars( ' ' );
197cdf0e10cSrcweir ByteString sText = sLine_in.GetToken( 1, '\"' ).GetToken( 0, '\"' );
198cdf0e10cSrcweir if( sLang.Len() )
199cdf0e10cSrcweir rText_inout[ sLang ] = sText;
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
202cdf0e10cSrcweir /*****************************************************************************/
Merge(const ByteString & rSDFFile,const ByteString & rDestinationFile,const ByteString & rPrj)203cdf0e10cSrcweir sal_Bool LngParser::Merge(
204cdf0e10cSrcweir const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString& rPrj )
205cdf0e10cSrcweir /*****************************************************************************/
206cdf0e10cSrcweir {
207cdf0e10cSrcweir (void) rPrj;
208cdf0e10cSrcweir Export::InitLanguages( true );
209cdf0e10cSrcweir SvFileStream aDestination(
210cdf0e10cSrcweir String( rDestinationFile, RTL_TEXTENCODING_ASCII_US ),
211cdf0e10cSrcweir STREAM_STD_WRITE | STREAM_TRUNC );
212cdf0e10cSrcweir if ( !aDestination.IsOpen()) {
213cdf0e10cSrcweir nError = LNG_COULD_NOT_OPEN;
214cdf0e10cSrcweir }
215cdf0e10cSrcweir nError = LNG_OK;
216cdf0e10cSrcweir // MergeDataFile( const ByteString &rFileName, const ByteString& rFile , sal_Bool bErrLog, CharSet aCharSet, sal_Bool bUTF8 );
217cdf0e10cSrcweir
218cdf0e10cSrcweir MergeDataFile aMergeDataFile( rSDFFile, sSource , sal_False, RTL_TEXTENCODING_MS_1252);//, bDBIsUTF8 );
219cdf0e10cSrcweir ByteString sTmp( Export::sLanguages );
220cdf0e10cSrcweir if( sTmp.ToUpperAscii().Equals("ALL") )
221cdf0e10cSrcweir Export::SetLanguages( aMergeDataFile.GetLanguages() );
222cdf0e10cSrcweir aLanguages = Export::GetLanguages();
223cdf0e10cSrcweir
224cdf0e10cSrcweir sal_uLong nPos = 0;
225cdf0e10cSrcweir sal_Bool bGroup = sal_False;
226cdf0e10cSrcweir ByteString sGroup;
227cdf0e10cSrcweir
228cdf0e10cSrcweir // seek to next group
229cdf0e10cSrcweir while ( nPos < pLines->Count() && !bGroup ) {
230cdf0e10cSrcweir ByteString sLine( *pLines->GetObject( nPos ));
231cdf0e10cSrcweir sLine.EraseLeadingChars( ' ' );
232cdf0e10cSrcweir sLine.EraseTrailingChars( ' ' );
233cdf0e10cSrcweir if (( sLine.GetChar( 0 ) == '[' ) &&
234cdf0e10cSrcweir ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
235cdf0e10cSrcweir {
236cdf0e10cSrcweir sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
237cdf0e10cSrcweir sGroup.EraseLeadingChars( ' ' );
238cdf0e10cSrcweir sGroup.EraseTrailingChars( ' ' );
239cdf0e10cSrcweir bGroup = sal_True;
240cdf0e10cSrcweir }
241cdf0e10cSrcweir nPos ++;
242cdf0e10cSrcweir }
243cdf0e10cSrcweir
244cdf0e10cSrcweir while ( nPos < pLines->Count()) {
245cdf0e10cSrcweir ByteStringHashMap Text;
246cdf0e10cSrcweir ByteString sID( sGroup );
247cdf0e10cSrcweir sal_uLong nLastLangPos = 0;
248cdf0e10cSrcweir
249cdf0e10cSrcweir ResData *pResData = new ResData( "", sID , sSource );
250cdf0e10cSrcweir pResData->sResTyp = "LngText";
251cdf0e10cSrcweir PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
252cdf0e10cSrcweir // read languages
253cdf0e10cSrcweir bGroup = sal_False;
254cdf0e10cSrcweir
255cdf0e10cSrcweir ByteString sLanguagesDone;
256cdf0e10cSrcweir
257cdf0e10cSrcweir while ( nPos < pLines->Count() && !bGroup ) {
258cdf0e10cSrcweir ByteString sLine( *pLines->GetObject( nPos ));
259cdf0e10cSrcweir sLine.EraseLeadingChars( ' ' );
260cdf0e10cSrcweir sLine.EraseTrailingChars( ' ' );
261cdf0e10cSrcweir if (( sLine.GetChar( 0 ) == '[' ) &&
262cdf0e10cSrcweir ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
263cdf0e10cSrcweir {
264cdf0e10cSrcweir sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
265cdf0e10cSrcweir sGroup.EraseLeadingChars( ' ' );
266cdf0e10cSrcweir sGroup.EraseTrailingChars( ' ' );
267cdf0e10cSrcweir bGroup = sal_True;
268cdf0e10cSrcweir nPos ++;
269cdf0e10cSrcweir sLanguagesDone = "";
270cdf0e10cSrcweir }
271cdf0e10cSrcweir else if ( sLine.GetTokenCount( '=' ) > 1 ) {
272cdf0e10cSrcweir ByteString sLang = sLine.GetToken( 0, '=' );
273cdf0e10cSrcweir sLang.EraseLeadingChars( ' ' );
274cdf0e10cSrcweir sLang.EraseTrailingChars( ' ' );
275cdf0e10cSrcweir
276cdf0e10cSrcweir ByteString sSearch( ";" );
277cdf0e10cSrcweir sSearch += sLang;
278cdf0e10cSrcweir sSearch += ";";
279cdf0e10cSrcweir
280cdf0e10cSrcweir if (( sLanguagesDone.Search( sSearch ) != STRING_NOTFOUND )) {
281cdf0e10cSrcweir pLines->Remove( nPos );
282cdf0e10cSrcweir }
283cdf0e10cSrcweir if( bULF && pEntrys )
284cdf0e10cSrcweir {
285cdf0e10cSrcweir // this is a valid text line
286cdf0e10cSrcweir ByteString sText = sLine.GetToken( 1, '\"' ).GetToken( 0, '\"' );
287cdf0e10cSrcweir if( sLang.Len() ){
288cdf0e10cSrcweir ByteString sNewText;
289cdf0e10cSrcweir pEntrys->GetText( sNewText, STRING_TYP_TEXT, sLang, sal_True );
290cdf0e10cSrcweir
291cdf0e10cSrcweir if ( sNewText.Len()) {
292cdf0e10cSrcweir ByteString *pLine = pLines->GetObject( nPos );
293cdf0e10cSrcweir
294cdf0e10cSrcweir ByteString sText1( sLang );
295cdf0e10cSrcweir sText1 += " = \"";
296cdf0e10cSrcweir sText1 += sNewText;
297cdf0e10cSrcweir sText1 += "\"";
298cdf0e10cSrcweir *pLine = sText1;
299cdf0e10cSrcweir //}
300cdf0e10cSrcweir Text[ sLang ] = sNewText;
301cdf0e10cSrcweir }
302cdf0e10cSrcweir }
303cdf0e10cSrcweir nLastLangPos = nPos;
304cdf0e10cSrcweir nPos ++;
305cdf0e10cSrcweir sLanguagesDone += sSearch;
306cdf0e10cSrcweir }
307cdf0e10cSrcweir else {
308cdf0e10cSrcweir nLastLangPos = nPos;
309cdf0e10cSrcweir nPos ++;
310cdf0e10cSrcweir sLanguagesDone += sSearch;
311cdf0e10cSrcweir }
312cdf0e10cSrcweir }
313cdf0e10cSrcweir else
314cdf0e10cSrcweir nPos++;
315cdf0e10cSrcweir }
316cdf0e10cSrcweir ByteString sCur;
317cdf0e10cSrcweir if ( nLastLangPos ) {
318cdf0e10cSrcweir for( unsigned int n = 0; n < aLanguages.size(); n++ ){
319cdf0e10cSrcweir sCur = aLanguages[ n ];
320cdf0e10cSrcweir if( //( !sCur.EqualsIgnoreCaseAscii("de") ||
321cdf0e10cSrcweir //( sCur.EqualsIgnoreCaseAscii("de") && Export::isMergingGermanAllowed( rPrj ) ) )
322cdf0e10cSrcweir !sCur.EqualsIgnoreCaseAscii("en-US") && !Text[ sCur ].Len() && pEntrys ){
323cdf0e10cSrcweir
324cdf0e10cSrcweir ByteString sNewText;
325cdf0e10cSrcweir pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur, sal_True );
326cdf0e10cSrcweir if (( sNewText.Len()) &&
327cdf0e10cSrcweir !(( sCur.Equals("x-comment") ) && ( sNewText == "-" )))
328cdf0e10cSrcweir {
329cdf0e10cSrcweir ByteString sLine;
330cdf0e10cSrcweir sLine += sCur;
331cdf0e10cSrcweir sLine += " = \"";
332cdf0e10cSrcweir sLine += sNewText;
333cdf0e10cSrcweir sLine += "\"";
334cdf0e10cSrcweir
335cdf0e10cSrcweir nLastLangPos++;
336cdf0e10cSrcweir nPos++;
337cdf0e10cSrcweir
338cdf0e10cSrcweir pLines->Insert( new ByteString( sLine ), nLastLangPos );
339cdf0e10cSrcweir }
340cdf0e10cSrcweir }
341cdf0e10cSrcweir }
342cdf0e10cSrcweir }
343cdf0e10cSrcweir
344cdf0e10cSrcweir delete pResData;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir
347cdf0e10cSrcweir for ( sal_uLong i = 0; i < pLines->Count(); i++ )
348cdf0e10cSrcweir aDestination.WriteLine( *pLines->GetObject( i ));
349cdf0e10cSrcweir
350cdf0e10cSrcweir aDestination.Close();
351cdf0e10cSrcweir return sal_True;
352cdf0e10cSrcweir }
353