fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / l10ntools / source / merge.cxx
bloba8323be6188440cda04826742b45dec1d60f77d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <algorithm>
23 #include <fstream>
24 #include <string>
25 #include <vector>
27 #include "export.hxx"
28 #include "po.hxx"
30 namespace
32 static OString lcl_NormalizeFilename(const OString& rFilename)
34 return rFilename.copy(
35 std::max(
36 rFilename.lastIndexOf( '\\' ),
37 rFilename.lastIndexOf( '/' ))+1);
40 static bool lcl_ReadPoChecked(
41 PoEntry& o_rPoEntry, PoIfstream& rPoFile,
42 const OString& rFileName)
44 try
46 rPoFile.readEntry( o_rPoEntry );
48 catch( PoIfstream::Exception& aException )
50 if( aException == PoIfstream::INVALIDENTRY )
52 printf(
53 "Warning : %s contains invalid entry\n",
54 rFileName.getStr() );
55 return false;
58 return true;
63 // class ResData
66 ResData::ResData( const OString &rGId )
68 nIdLevel( ID_LEVEL_NULL ),
69 bChild( false ),
70 bChildWithText( false ),
71 bText( false ),
72 bQuickHelpText( false ),
73 bTitle( false ),
74 sGId( rGId ),
75 sTextTyp( "Text" )
77 sGId = sGId.replaceAll("\r", OString());
80 ResData::ResData( const OString &rGId, const OString &rFilename)
82 nIdLevel( ID_LEVEL_NULL ),
83 bChild( false ),
84 bChildWithText( false ),
85 bText( false ),
86 bQuickHelpText( false ),
87 bTitle( false ),
88 sGId( rGId ),
89 sFilename( rFilename ),
90 sTextTyp( "Text" )
92 sGId = sGId.replaceAll("\r", OString());
96 // class MergeEntrys
99 bool MergeEntrys::GetText( OString &rReturn,
100 sal_uInt16 nTyp, const OString &nLangIndex, bool bDel )
102 bool bReturn = true;
103 switch ( nTyp ) {
104 case STRING_TYP_TEXT :
105 rReturn = sText[ nLangIndex ];
106 if ( bDel )
107 sText[ nLangIndex ] = "";
108 bReturn = bTextFirst[ nLangIndex ];
109 bTextFirst[ nLangIndex ] = false;
110 break;
111 case STRING_TYP_QUICKHELPTEXT :
112 rReturn = sQuickHelpText[ nLangIndex ];
113 if ( bDel )
114 sQuickHelpText[ nLangIndex ] = "";
115 bReturn = bQuickHelpTextFirst[ nLangIndex ];
116 bQuickHelpTextFirst[ nLangIndex ] = false;
117 break;
118 case STRING_TYP_TITLE :
119 rReturn = sTitle[ nLangIndex ];
120 if ( bDel )
121 sTitle[ nLangIndex ] = "";
122 bReturn = bTitleFirst[ nLangIndex ];
123 bTitleFirst[ nLangIndex ] = false;
124 break;
126 return bReturn;
130 OString MergeEntrys::GetQTZText(const ResData& rResData, const OString& rOrigText)
132 const OString sFilename = rResData.sFilename.copy(rResData.sFilename.lastIndexOf('/')+1);
133 const OString sKey =
134 PoEntry::genKeyId(sFilename + rResData.sGId + rResData.sId + rResData.sResTyp + rOrigText);
135 return sKey + "||" + rOrigText;
139 // class MergeDataHashMap
142 std::pair<MergeDataHashMap::iterator,bool> MergeDataHashMap::insert(const OString& rKey, MergeData* pMergeData)
144 std::pair<iterator,bool> aTemp = m_aHashMap.insert(HashMap_t::value_type( rKey, pMergeData ));
145 if( m_aHashMap.size() == 1 )
147 // When first insert, set an iterator to the first element
148 aFirstInOrder = aTemp.first;
150 else
152 // Define insertion order by setting an iterator to the next element.
153 aLastInsertion->second->m_aNextData = aTemp.first;
155 aLastInsertion = aTemp.first;
156 return aTemp;
159 MergeDataHashMap::iterator MergeDataHashMap::find(const OString& rKey)
161 iterator aHint = m_aHashMap.end();
163 // Add a hint
164 if( bFirstSearch && !m_aHashMap.empty() )
166 aHint = aFirstInOrder;
168 else if( aLastFound == aLastInsertion )
170 // Next to the last element is the first element
171 aHint = aFirstInOrder;
173 else if( aLastFound != m_aHashMap.end() && aLastFound != aLastInsertion )
175 aHint = aLastFound->second->m_aNextData;
178 // If hint works than no need for search
179 if( aHint != m_aHashMap.end() && aHint->first == rKey )
181 aLastFound = aHint;
183 else
185 aLastFound = m_aHashMap.find(rKey);
188 bFirstSearch = false;
189 return aLastFound;
193 // class MergeData
196 MergeData::MergeData(
197 const OString &rTyp, const OString &rGID,
198 const OString &rLID , const OString &rFilename )
199 : sTyp( rTyp ),
200 sGID( rGID ),
201 sLID( rLID ) ,
202 sFilename( rFilename ),
203 pMergeEntrys( new MergeEntrys() )
207 MergeData::~MergeData()
209 delete pMergeEntrys;
213 bool MergeData::operator==( ResData *pData )
215 return pData->sId == sLID && pData->sGId == sGID
216 && pData->sResTyp.equalsIgnoreAsciiCase(sTyp);
220 // class MergeDataFile
223 MergeDataFile::MergeDataFile(
224 const OString &rFileName, const OString &rFile,
225 bool bCaseSensitive, bool bWithQtz )
227 OString sEnableReleaseBuild(getenv("ENABLE_RELEASE_BUILD"));
229 std::ifstream aInputStream( rFileName.getStr() );
230 if ( !aInputStream.is_open() )
232 printf("Warning : Can't open po path container file\n");
233 return;
235 std::string sPoFile;
236 aInputStream >> sPoFile;
237 bool bFirstLang = true;
238 while( !aInputStream.eof() )
240 bool bSkipCurrentPOFile = false;
241 const OString sFileName( lcl_NormalizeFilename(rFile) );
242 const bool bReadAll = sFileName.isEmpty();
243 // coverity[tainted_data] - this is a build time tool
244 const OString sPoFileName(sPoFile.data(), (sal_Int32)sPoFile.length());
245 PoIfstream aPoInput;
246 aPoInput.open( sPoFileName );
247 if ( !aPoInput.isOpen() )
249 printf( "Warning : Can't open %s\n", sPoFileName.getStr() );
250 return;
253 OString sLang;
254 //Get language id from path
256 const OString sTransSource("translations/source/");
257 const sal_Int32 nStart =
258 sPoFileName.indexOf(sTransSource)+sTransSource.getLength();
259 const sal_Int32 nCount =
260 sPoFileName.indexOf('/',nStart) - nStart;
261 sLang = sPoFileName.copy(nStart,nCount);
263 aLanguageSet.insert( sLang );
264 PoEntry aNextPo;
267 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
269 bSkipCurrentPOFile = true;
270 break;
272 } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
273 while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ) && !bSkipCurrentPOFile )
275 PoEntry aActPo( aNextPo );
277 bool bInSameComp = false;
278 OString sText;
279 OString sQHText;
280 OString sTitle;
281 OString sExText;
282 OString sExQHText;
283 OString sExTitle;
286 if( bInSameComp )
287 aActPo = aNextPo;
288 OString sTemp = aActPo.getMsgStr();
289 if( aActPo.isFuzzy() || sTemp.isEmpty() )
290 sTemp = aActPo.getMsgId();
291 switch( aActPo.getType() )
293 case PoEntry::TTEXT:
294 sText = sTemp;
295 sExText = aActPo.getMsgId();
296 break;
297 case PoEntry::TQUICKHELPTEXT:
298 sQHText = sTemp;
299 sExQHText = aActPo.getMsgId();
300 break;
301 case PoEntry::TTITLE:
302 sTitle = sTemp;
303 sExTitle = aActPo.getMsgId();
304 break;
306 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
308 bSkipCurrentPOFile = true;
309 break;
311 } while( !aPoInput.eof() &&
312 ( bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo) ) );
314 InsertEntry(
315 aActPo.getResourceType(), aActPo.getGroupId(),
316 aActPo.getLocalId(), sLang, sText,
317 sQHText, sTitle, aActPo.getSourceFile(),
318 bFirstLang, bCaseSensitive );
320 if( bFirstLang && bWithQtz &&
321 !sEnableReleaseBuild.equals("TRUE") )
323 aLanguageSet.insert("qtz");
324 InsertEntry(
325 aActPo.getResourceType(), aActPo.getGroupId(),
326 aActPo.getLocalId(), "qtz",
327 sExText, sExQHText,
328 sExTitle, aActPo.getSourceFile(),
329 false, bCaseSensitive );
332 aPoInput.close();
333 aInputStream >> sPoFile;
334 bFirstLang = false;
336 aInputStream.close();
339 MergeDataFile::~MergeDataFile()
341 for (MergeDataHashMap::iterator aI = aMap.begin(), aEnd = aMap.end(); aI != aEnd; ++aI)
342 delete aI->second;
345 std::vector<OString> MergeDataFile::GetLanguages() const
347 return std::vector<OString>(aLanguageSet.begin(),aLanguageSet.end());
350 MergeData *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
352 OString sOldG = pResData->sGId;
353 OString sOldL = pResData->sId;
354 OString sGID = pResData->sGId;
355 OString sLID;
356 if (sGID.isEmpty())
357 sGID = pResData->sId;
358 else
359 sLID = pResData->sId;
360 pResData->sGId = sGID;
361 pResData->sId = sLID;
363 OString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
365 MergeDataHashMap::const_iterator mit = aMap.find( sKey );
366 if(mit != aMap.end())
368 pResData->sGId = sOldG;
369 pResData->sId = sOldL;
370 return mit->second;
372 pResData->sGId = sOldG;
373 pResData->sId = sOldL;
374 return NULL;
377 MergeEntrys *MergeDataFile::GetMergeEntrys( ResData *pResData )
379 // search for requested MergeEntrys
380 MergeData *pData = GetMergeData( pResData );
381 if ( pData )
382 return pData->GetMergeEntries();
383 return NULL;
386 MergeEntrys *MergeDataFile::GetMergeEntrysCaseSensitive( ResData *pResData )
388 // search for requested MergeEntrys
389 MergeData *pData = GetMergeData( pResData , true );
390 if ( pData )
391 return pData->GetMergeEntries();
392 return NULL;
395 void MergeDataFile::InsertEntry(
396 const OString &rTYP, const OString &rGID,
397 const OString &rLID, const OString &nLANG,
398 const OString &rTEXT, const OString &rQHTEXT,
399 const OString &rTITLE, const OString &rInFilename,
400 bool bFirstLang, bool bCaseSensitive )
402 MergeData *pData = 0;
404 // search for MergeData
405 OString sKey = CreateKey(rTYP , rGID , rLID , rInFilename , bCaseSensitive);
407 if( !bFirstLang )
409 MergeDataHashMap::const_iterator mit = aMap.find( sKey );
410 if(mit != aMap.end())
411 pData = mit->second;
415 if( !pData )
417 pData = new MergeData( rTYP, rGID, rLID, rInFilename );
418 aMap.insert( sKey, pData );
422 // insert the cur string
423 MergeEntrys *pMergeEntrys = pData->GetMergeEntries();
424 if( nLANG =="qtz" )
426 const OString sTemp = rInFilename + rGID + rLID + rTYP;
427 pMergeEntrys->InsertEntry(
428 nLANG,
429 rTEXT.isEmpty()? rTEXT : PoEntry::genKeyId(sTemp + rTEXT) + "||" + rTEXT,
430 rQHTEXT.isEmpty()? rQHTEXT : PoEntry::genKeyId(sTemp + rQHTEXT) + "||" + rQHTEXT,
431 rTITLE.isEmpty()? rTITLE : PoEntry::genKeyId(sTemp + rTITLE) + "||" + rTITLE );
433 else
435 pMergeEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
439 OString MergeDataFile::CreateKey(const OString& rTYP, const OString& rGID,
440 const OString& rLID, const OString& rFilename, bool bCaseSensitive)
442 static const char sStroke[] = "-";
443 OString sKey( rTYP );
444 sKey += sStroke;
445 sKey += rGID;
446 sKey += sStroke;
447 sKey += rLID;
448 sKey += sStroke;
449 sKey += lcl_NormalizeFilename(rFilename);
450 OSL_TRACE("created key: %s", sKey.getStr());
451 if(bCaseSensitive)
452 return sKey; // officecfg case sensitive identifier
453 return sKey.toAsciiUpperCase();
456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */