xref: /trunk/main/l10ntools/source/merge.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 <stdio.h>
31 #include <tools/fsys.hxx>
32 #include "export.hxx"
33 #include "utf8conv.hxx"
34 #include <iostream>
35 
36 using namespace std;
37 
38 namespace
39 {
40     static ::rtl::OString lcl_NormalizeFilename(const ::rtl::OString& rFilename)
41     {
42         return rFilename.copy(
43             ::std::max(
44                 rFilename.lastIndexOf( "\\" ),
45                 rFilename.lastIndexOf( "/" ))+1);
46     };
47 }
48 
49 extern void ConvertHalfwitdhToFullwidth( String& rString );
50 
51 //
52 // class PFormEntrys
53 //
54 
55 ByteString PFormEntrys::Dump()
56 {
57     ByteString sRet( "PFormEntrys\n" );
58     ByteString a("sText");
59     if(sText.size())
60         Export::DumpMap(a , sText);
61     return sRet;
62 }
63 
64 sal_Bool PFormEntrys::GetTransex3Text( ByteString &rReturn,
65     sal_uInt16 nTyp, const ByteString &nLangIndex, sal_Bool bDel )
66 {
67     sal_Bool rc = GetText( rReturn , nTyp , nLangIndex , bDel );
68     ByteString test( rReturn );
69     for( sal_uInt16 idx = 0; idx < rReturn.Len(); idx++ )
70     {
71         if( rReturn.GetChar( idx ) == '\"' && ( idx >= 1 )  &&  rReturn.GetChar( idx-1 ) == '\\' )
72         {
73             rReturn.Erase( idx-1 , 1 );
74         }
75     }
76     //if( !rReturn.Equals( test ) )
77     //    printf("*CHANGED******************\n%s\n%s\n",test.GetBuffer(),rReturn.GetBuffer());
78     return rc;
79 }
80 /*****************************************************************************/
81 sal_Bool PFormEntrys::GetText( ByteString &rReturn,
82     sal_uInt16 nTyp, const ByteString &nLangIndex, sal_Bool bDel )
83 {
84 
85     sal_Bool bReturn=sal_True;
86     switch ( nTyp ) {
87         case STRING_TYP_TEXT :
88             rReturn = sText[ nLangIndex ];
89             if ( bDel )
90                 sText[ nLangIndex ] = "";
91             bReturn = bTextFirst[ nLangIndex ];
92             bTextFirst[ nLangIndex ] = sal_False;
93             break;
94         case STRING_TYP_HELPTEXT :
95             rReturn = sHelpText;
96             break;
97         case STRING_TYP_QUICKHELPTEXT :
98             rReturn = sQuickHelpText[ nLangIndex ];
99             if ( bDel )
100                 sQuickHelpText[ nLangIndex ] = "";
101             bReturn = bQuickHelpTextFirst[ nLangIndex ];
102             bQuickHelpTextFirst[ nLangIndex ] = sal_False;
103             break;
104         case STRING_TYP_TITLE :
105             rReturn = sTitle[ nLangIndex ];
106             if ( bDel )
107                 sTitle[ nLangIndex ] = "";
108             bReturn = bTitleFirst[ nLangIndex ];
109             bTitleFirst[ nLangIndex ] = sal_False;
110             break;
111     }
112     return bReturn;
113 }
114 
115 
116 //
117 // class MergeData
118 //
119 
120 MergeData::~MergeData()
121 {
122 }
123 
124 PFormEntrys* MergeData::GetPFormEntrys(ResData*)
125 {
126     if( aMap.find( ByteString("HACK") ) != aMap.end() )
127         return aMap[ ByteString("HACK") ];
128     return NULL;
129 }
130 
131 void MergeData::Insert(const ByteString&, PFormEntrys* pfEntrys )
132 {
133     aMap.insert( PFormEntrysHashMap::value_type( ByteString("HACK") , pfEntrys ) );
134 }
135 
136 ByteString MergeData::Dump(){
137     ByteString sRet( "MergeData\n" );
138 
139     printf("MergeData sTyp = %s , sGid = %s , sLid =%s , sFilename = %s\n",sTyp.GetBuffer(),sGID.GetBuffer(),sLID.GetBuffer(), sFilename.GetBuffer() );
140 
141     PFormEntrysHashMap::const_iterator idbg;
142     for( idbg = aMap.begin() ; idbg != aMap.end(); ++idbg )
143     {
144         printf("aMap[ %s ] = " ,idbg->first.GetBuffer());
145         ( (PFormEntrys*)(idbg->second) )->Dump();
146         printf("\n");
147     }
148     printf("\n");
149     return sRet;
150 }
151 
152 PFormEntrys* MergeData::GetPFObject( const ByteString& rPFO ){
153     if( aMap.find( ByteString("HACK") ) != aMap.end() )
154         return aMap[ rPFO ];
155     return NULL;
156 }
157 
158 
159 PFormEntrys *MergeData::InsertEntry( const ByteString &rPForm )
160 {
161     PFormEntrys* pFEntrys = new PFormEntrys( rPForm );
162     aMap.insert( PFormEntrysHashMap::value_type( rPForm , pFEntrys ) );
163     return pFEntrys;
164 }
165 
166 sal_Bool MergeData::operator==( ResData *pData )
167 {
168     ByteString sResTyp_upper( pData->sResTyp );
169     sResTyp_upper.ToUpperAscii();
170     ByteString sTyp_upper( sTyp );
171     sTyp_upper.ToUpperAscii();
172 
173     return (( pData->sId == sLID ) &&
174             ( pData->sGId == sGID ) &&
175             ( sResTyp_upper  ==  sTyp_upper )
176             );
177 }
178 
179 //
180 // class MergeDataFile
181 //
182 
183 #define FFORMAT_UNKNOWN 0x0000
184 #define FFORMAT_NEW     0x0001
185 #define FFORMAT_OLD     0x0002
186 
187 
188 MergeDataFile::MergeDataFile(
189     const ByteString &rFileName,
190     const ByteString& sFile,
191     sal_Bool bErrLog,
192     CharSet aCharSet,
193     bool bCaseSensitive)
194     : bErrorLog( bErrLog )
195 {
196     SvFileStream aInputStream( String( rFileName, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
197     aInputStream.SetStreamCharSet( aCharSet );
198     ByteString sLine;
199     const ByteString sHACK("HACK");
200     const ::rtl::OString sFileNormalized(lcl_NormalizeFilename(sFile));
201     const bool isFileEmpty = sFileNormalized.getLength();
202 
203     if( !aInputStream.IsOpen() )
204     {
205         printf("Warning : Can't open %s\n", rFileName.GetBuffer());
206         return;
207     }
208     while ( !aInputStream.IsEof())
209     {
210         xub_StrLen nToks;
211         aInputStream.ReadLine( sLine );
212         sLine = sLine.Convert( RTL_TEXTENCODING_MS_1252, aCharSet );
213 
214         nToks = sLine.GetTokenCount( '\t' );
215         if ( nToks == 15 )
216         {
217             // Skip all wrong filenames
218             const ::rtl::OString filename = lcl_NormalizeFilename(sLine.GetToken( 1 , '\t' ));
219             if(isFileEmpty || sFileNormalized.equals("") || (!isFileEmpty && filename.equals(sFileNormalized)) )
220             {
221                 xub_StrLen rIdx = 0;
222                 const ByteString sTYP = sLine.GetToken( 3, '\t', rIdx );
223                 const ByteString sGID = sLine.GetToken( 0, '\t', rIdx ); // 4
224                 const ByteString sLID = sLine.GetToken( 0, '\t', rIdx ); // 5
225                 ByteString sPFO = sLine.GetToken( 1, '\t', rIdx ); // 7
226                 sPFO = sHACK;
227                 ByteString nLANG = sLine.GetToken( 1, '\t', rIdx ); // 9
228                 nLANG.EraseLeadingAndTrailingChars();
229                 const ByteString sTEXT = sLine.GetToken( 0, '\t', rIdx ); // 10
230                 const ByteString sQHTEXT = sLine.GetToken( 1, '\t', rIdx ); // 12
231                 const ByteString sTITLE = sLine.GetToken( 0, '\t', rIdx );  // 13
232 
233 
234 #ifdef MERGE_SOURCE_LANGUAGES
235                 if( true )
236 #else
237                 if( !nLANG.EqualsIgnoreCaseAscii("en-US") )
238 #endif
239                 {
240                     aLanguageSet.insert(nLANG);
241                     InsertEntry( sTYP, sGID, sLID, sPFO, nLANG, sTEXT, sQHTEXT, sTITLE, filename, bCaseSensitive );
242                 }
243             }
244         }
245         else if ( nToks == 10 )
246         {
247             printf("ERROR: File format is obsolete and no longer supported!\n");
248         }
249     }
250     aInputStream.Close();
251 }
252 
253 MergeDataFile::~MergeDataFile()
254 {
255 }
256 
257 ByteString MergeDataFile::Dump(){
258     ByteString sRet( "MergeDataFile\n" );
259 
260     printf("MergeDataFile\n");
261     MergeDataHashMap::const_iterator idbg;
262     for( idbg = aMap.begin() ; idbg != aMap.end(); ++idbg )
263     {
264         printf("aMap[ %s ] = ",idbg->first.GetBuffer());
265         ((MergeData*) (idbg->second))->Dump();
266         printf("\n");
267     }
268     printf("\n");
269     return sRet;
270 }
271 
272 void MergeDataFile::WriteError( const ByteString &rLine )
273 {
274     if ( bErrorLog )
275     {
276         if ( !aErrLog.IsOpen())
277             aErrLog.Open( String( sErrorLog, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_WRITE | STREAM_TRUNC );
278         aErrLog.WriteLine( rLine );
279     }
280     else
281         fprintf( stderr, "%s\n", rLine.GetBuffer());
282 }
283 
284 std::vector<ByteString> MergeDataFile::GetLanguages(){
285     return std::vector<ByteString>(aLanguageSet.begin(),aLanguageSet.end());
286 }
287 
288 MergeData *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
289 {
290     ByteString sOldG = pResData->sGId;
291     ByteString sOldL = pResData->sId;
292     ByteString sGID = pResData->sGId;
293     ByteString sLID;
294     if(!sGID.Len())
295         sGID = pResData->sId;
296     else
297         sLID = pResData->sId;
298     pResData->sGId = sGID;
299     pResData->sId = sLID;
300 
301     ByteString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
302 
303     if(aMap.find( sKey ) != aMap.end())
304     {
305         pResData->sGId = sOldG;
306         pResData->sId = sOldL;
307         return aMap[ sKey ];
308     }
309     pResData->sGId = sOldG;
310     pResData->sId = sOldL;
311     return NULL;
312 }
313 
314 
315 PFormEntrys *MergeDataFile::GetPFormEntrys( ResData *pResData )
316 {
317     // search for requested PFormEntrys
318     MergeData *pData = GetMergeData( pResData );
319     if ( pData )
320         return pData->GetPFormEntrys( pResData );
321     return NULL;
322 }
323 
324 PFormEntrys *MergeDataFile::GetPFormEntrysCaseSensitive( ResData *pResData )
325 {
326     // search for requested PFormEntrys
327     MergeData *pData = GetMergeData( pResData , true );
328     if ( pData )
329         return pData->GetPFormEntrys( pResData );
330     return NULL;
331 }
332 
333 void MergeDataFile::InsertEntry(
334     const ByteString &rTYP, const ByteString &rGID,
335     const ByteString &rLID, const ByteString &rPFO,
336     const ByteString &nLANG, const ByteString &rTEXT,
337     const ByteString &rQHTEXT, const ByteString &rTITLE ,
338     const ByteString &rInFilename , bool bCaseSensitive
339     )
340 {
341     MergeData *pData;
342 
343     // search for MergeData
344     ByteString sKey = CreateKey( rTYP , rGID , rLID , rInFilename , bCaseSensitive );
345     MergeDataHashMap::const_iterator mit;
346     mit = aMap.find( sKey );
347     if( mit != aMap.end() )
348     {
349         pData = mit->second;
350     }
351     else
352     {
353         pData = new MergeData( rTYP, rGID, rLID, rInFilename );
354         aMap.insert( MergeDataHashMap::value_type( sKey, pData ) );
355     }
356 
357     PFormEntrys *pFEntrys = 0;
358 
359     // search for PFormEntrys
360     pFEntrys = pData->GetPFObject( rPFO );
361     if( !pFEntrys )
362     {
363         // create new PFormEntrys, cause no one exists with current properties
364         pFEntrys = new PFormEntrys( rPFO );
365         pData->Insert( rPFO , pFEntrys );
366     }
367 
368     // finaly insert the cur string
369     pFEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
370 }
371 
372 ByteString MergeDataFile::CreateKey( const ByteString& rTYP , const ByteString& rGID , const ByteString& rLID , const ByteString& rFilename , bool bCaseSensitive )
373 {
374     static const ::rtl::OString sStroke('-');
375     ::rtl::OString sKey( rTYP );
376     sKey += sStroke;
377     sKey += rGID;
378     sKey += sStroke;
379     sKey += rLID;
380     sKey += sStroke;
381     sKey += lcl_NormalizeFilename(rFilename);
382     OSL_TRACE("created key: %s", sKey.getStr());
383     if(bCaseSensitive)
384         return sKey;         // officecfg case sensitive identifier
385     return sKey.toAsciiUpperCase();
386 }
387