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