1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
32 static OString
lcl_NormalizeFilename(const OString
& rFilename
)
34 return rFilename
.copy(
36 rFilename
.lastIndexOf( '\\' ),
37 rFilename
.lastIndexOf( '/' ))+1);
40 static bool lcl_ReadPoChecked(
41 PoEntry
& o_rPoEntry
, PoIfstream
& rPoFile
,
42 const OString
& rFileName
)
46 rPoFile
.readEntry( o_rPoEntry
);
48 catch( PoIfstream::Exception
& aException
)
50 if( aException
== PoIfstream::INVALIDENTRY
)
53 "Warning : %s contains invalid entry\n",
66 ResData::ResData( const OString
&rGId
)
68 nIdLevel( ID_LEVEL_NULL
),
70 bChildWithText( false ),
72 bQuickHelpText( false ),
77 sGId
= sGId
.replaceAll("\r", OString());
80 ResData::ResData( const OString
&rGId
, const OString
&rFilename
)
82 nIdLevel( ID_LEVEL_NULL
),
84 bChildWithText( false ),
86 bQuickHelpText( false ),
89 sFilename( rFilename
),
92 sGId
= sGId
.replaceAll("\r", OString());
99 bool MergeEntrys::GetText( OString
&rReturn
,
100 sal_uInt16 nTyp
, const OString
&nLangIndex
, bool bDel
)
104 case STRING_TYP_TEXT
:
105 rReturn
= sText
[ nLangIndex
];
107 sText
[ nLangIndex
] = "";
108 bReturn
= bTextFirst
[ nLangIndex
];
109 bTextFirst
[ nLangIndex
] = false;
111 case STRING_TYP_QUICKHELPTEXT
:
112 rReturn
= sQuickHelpText
[ nLangIndex
];
114 sQuickHelpText
[ nLangIndex
] = "";
115 bReturn
= bQuickHelpTextFirst
[ nLangIndex
];
116 bQuickHelpTextFirst
[ nLangIndex
] = false;
118 case STRING_TYP_TITLE
:
119 rReturn
= sTitle
[ nLangIndex
];
121 sTitle
[ nLangIndex
] = "";
122 bReturn
= bTitleFirst
[ nLangIndex
];
123 bTitleFirst
[ nLangIndex
] = false;
130 OString
MergeEntrys::GetQTZText(const ResData
& rResData
, const OString
& rOrigText
)
132 const OString sFilename
= rResData
.sFilename
.copy(rResData
.sFilename
.lastIndexOf('/')+1);
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
;
152 // Define insertion order by setting an iterator to the next element.
153 aLastInsertion
->second
->m_aNextData
= aTemp
.first
;
155 aLastInsertion
= aTemp
.first
;
159 MergeDataHashMap::iterator
MergeDataHashMap::find(const OString
& rKey
)
161 iterator aHint
= m_aHashMap
.end();
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
)
185 aLastFound
= m_aHashMap
.find(rKey
);
188 bFirstSearch
= false;
196 MergeData::MergeData(
197 const OString
&rTyp
, const OString
&rGID
,
198 const OString
&rLID
, const OString
&rFilename
)
202 sFilename( rFilename
),
203 pMergeEntrys( new MergeEntrys() )
207 MergeData::~MergeData()
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");
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());
246 aPoInput
.open( sPoFileName
);
247 if ( !aPoInput
.isOpen() )
249 printf( "Warning : Can't open %s\n", sPoFileName
.getStr() );
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
);
267 if( !lcl_ReadPoChecked(aNextPo
, aPoInput
, sPoFileName
) )
269 bSkipCurrentPOFile
= true;
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;
288 OString sTemp
= aActPo
.getMsgStr();
289 if( aActPo
.isFuzzy() || sTemp
.isEmpty() )
290 sTemp
= aActPo
.getMsgId();
291 switch( aActPo
.getType() )
295 sExText
= aActPo
.getMsgId();
297 case PoEntry::TQUICKHELPTEXT
:
299 sExQHText
= aActPo
.getMsgId();
301 case PoEntry::TTITLE
:
303 sExTitle
= aActPo
.getMsgId();
306 if( !lcl_ReadPoChecked(aNextPo
, aPoInput
, sPoFileName
) )
308 bSkipCurrentPOFile
= true;
311 } while( !aPoInput
.eof() &&
312 ( bInSameComp
= PoEntry::IsInSameComp(aActPo
, aNextPo
) ) );
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");
325 aActPo
.getResourceType(), aActPo
.getGroupId(),
326 aActPo
.getLocalId(), "qtz",
328 sExTitle
, aActPo
.getSourceFile(),
329 false, bCaseSensitive
);
333 aInputStream
>> sPoFile
;
336 aInputStream
.close();
339 MergeDataFile::~MergeDataFile()
341 for (MergeDataHashMap::iterator aI
= aMap
.begin(), aEnd
= aMap
.end(); aI
!= aEnd
; ++aI
)
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
;
357 sGID
= pResData
->sId
;
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
;
372 pResData
->sGId
= sOldG
;
373 pResData
->sId
= sOldL
;
377 MergeEntrys
*MergeDataFile::GetMergeEntrys( ResData
*pResData
)
379 // search for requested MergeEntrys
380 MergeData
*pData
= GetMergeData( pResData
);
382 return pData
->GetMergeEntries();
386 MergeEntrys
*MergeDataFile::GetMergeEntrysCaseSensitive( ResData
*pResData
)
388 // search for requested MergeEntrys
389 MergeData
*pData
= GetMergeData( pResData
, true );
391 return pData
->GetMergeEntries();
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
);
409 MergeDataHashMap::const_iterator mit
= aMap
.find( sKey
);
410 if(mit
!= aMap
.end())
417 pData
= new MergeData( rTYP
, rGID
, rLID
, rInFilename
);
418 aMap
.insert( sKey
, pData
);
422 // insert the cur string
423 MergeEntrys
*pMergeEntrys
= pData
->GetMergeEntries();
426 const OString sTemp
= rInFilename
+ rGID
+ rLID
+ rTYP
;
427 pMergeEntrys
->InsertEntry(
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
);
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
);
449 sKey
+= lcl_NormalizeFilename(rFilename
);
450 OSL_TRACE("created key: %s", sKey
.getStr());
452 return sKey
; // officecfg case sensitive identifier
453 return sKey
.toAsciiUpperCase();
456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */