nss: upgrade to release 3.73
[LibreOffice.git] / l10ntools / source / merge.cxx
blob75afdf77b9a6538e6ac539d77da783b358896afc
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>
21 #include <sal/log.hxx>
23 #include <algorithm>
24 #include <fstream>
25 #include <string>
26 #include <vector>
28 #include <export.hxx>
29 #include <po.hxx>
31 namespace
33 OString lcl_NormalizeFilename(const OString& rFilename)
35 return rFilename.copy(
36 std::max(
37 rFilename.lastIndexOf( '\\' ),
38 rFilename.lastIndexOf( '/' ))+1);
41 bool lcl_ReadPoChecked(
42 PoEntry& o_rPoEntry, PoIfstream& rPoFile,
43 const OString& rFileName)
45 try
47 rPoFile.readEntry( o_rPoEntry );
49 catch (const PoIfstream::Exception&)
51 SAL_WARN("l10ntools", rFileName << " contains invalid entry");
52 return false;
54 return true;
61 ResData::ResData( const OString &rGId )
63 sGId( rGId )
65 sGId = sGId.replaceAll("\r", OString());
68 ResData::ResData( const OString &rGId, const OString &rFilename)
70 sGId( rGId ),
71 sFilename( rFilename )
73 sGId = sGId.replaceAll("\r", OString());
79 bool MergeEntrys::GetText( OString &rReturn,
80 const OString &nLangIndex, bool bDel )
82 bool bReturn = true;
83 rReturn = sText[ nLangIndex ];
84 if ( bDel )
85 sText[ nLangIndex ] = "";
86 bReturn = bTextFirst[ nLangIndex ];
87 bTextFirst[ nLangIndex ] = false;
88 return bReturn;
91 namespace
93 OString GetDoubleBars()
95 //DOUBLE VERTICAL LINE instead of || because the translations make their
96 //way into action_names under gtk3 where || is illegal
97 return OUStringToOString(OUString(u'\x2016'), RTL_TEXTENCODING_UTF8);
101 OString MergeEntrys::GetQTZText(const ResData& rResData, const OString& rOrigText)
103 const OString sFilename = rResData.sFilename.copy(rResData.sFilename.lastIndexOf('/')+1);
104 const OString sKey =
105 PoEntry::genKeyId(sFilename + rResData.sGId + rResData.sId + rResData.sResTyp + rOrigText);
106 return sKey + GetDoubleBars() + rOrigText;
111 MergeDataFile::MergeDataFile(
112 const OString &rFileName, const OString &rFile,
113 bool bCaseSensitive, bool bWithQtz )
115 OString sEnableReleaseBuild(getenv("ENABLE_RELEASE_BUILD"));
117 std::ifstream aInputStream( rFileName.getStr() );
118 if ( !aInputStream.is_open() )
120 SAL_WARN("l10ntools", "Can't open po path container file for " << rFileName);
121 return;
123 std::string sPoFile;
124 aInputStream >> sPoFile;
125 bool bFirstLang = true;
126 while( !aInputStream.eof() )
128 bool bSkipCurrentPOFile = false;
129 const OString sFileName( lcl_NormalizeFilename(rFile) );
130 const bool bReadAll = sFileName.isEmpty();
131 // coverity[tainted_data] - this is a build time tool
132 const OString sPoFileName(sPoFile.data(), static_cast<sal_Int32>(sPoFile.length()));
133 PoIfstream aPoInput;
134 aPoInput.open( sPoFileName );
135 if ( !aPoInput.isOpen() )
137 SAL_WARN("l10ntools", "Can't open file: " << sPoFileName);
138 return;
141 OString sLang;
142 //Get language id from path
144 const OString sTransSource("translations/source/");
145 const sal_Int32 nStart =
146 sPoFileName.indexOf(sTransSource)+sTransSource.getLength();
147 const sal_Int32 nCount =
148 sPoFileName.indexOf('/',nStart) - nStart;
149 sLang = sPoFileName.copy(nStart,nCount);
151 aLanguageSet.insert( sLang );
152 PoEntry aNextPo;
155 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
157 bSkipCurrentPOFile = true;
158 break;
160 } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
161 while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ) && !bSkipCurrentPOFile )
163 PoEntry aActPo( aNextPo );
165 bool bInSameComp = false;
166 OString sText;
167 OString sQHText;
168 OString sTitle;
169 OString sExText;
170 OString sExQHText;
171 OString sExTitle;
174 if( bInSameComp )
175 aActPo = aNextPo;
176 OString sTemp = aActPo.getMsgStr();
177 if( aActPo.isFuzzy() || sTemp.isEmpty() )
178 sTemp = aActPo.getMsgId();
179 switch( aActPo.getType() )
181 case PoEntry::TTEXT:
182 sText = sTemp;
183 sExText = aActPo.getMsgId();
184 break;
185 case PoEntry::TQUICKHELPTEXT:
186 sQHText = sTemp;
187 sExQHText = aActPo.getMsgId();
188 break;
189 case PoEntry::TTITLE:
190 sTitle = sTemp;
191 sExTitle = aActPo.getMsgId();
192 break;
194 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
196 bSkipCurrentPOFile = true;
197 break;
199 if (aPoInput.eof())
200 break;
201 bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo);
202 } while( bInSameComp );
204 InsertEntry(
205 aActPo.getResourceType(), aActPo.getGroupId(),
206 aActPo.getLocalId(), sLang, sText,
207 sQHText, sTitle, aActPo.getSourceFile(),
208 bFirstLang, bCaseSensitive );
210 if( bFirstLang && bWithQtz &&
211 sEnableReleaseBuild != "TRUE" )
213 aLanguageSet.insert("qtz");
214 InsertEntry(
215 aActPo.getResourceType(), aActPo.getGroupId(),
216 aActPo.getLocalId(), "qtz",
217 sExText, sExQHText,
218 sExTitle, aActPo.getSourceFile(),
219 false, bCaseSensitive );
222 aPoInput.close();
223 aInputStream >> sPoFile;
224 bFirstLang = false;
226 aInputStream.close();
229 MergeDataFile::~MergeDataFile()
233 std::vector<OString> MergeDataFile::GetLanguages() const
235 return std::vector<OString>(aLanguageSet.begin(),aLanguageSet.end());
238 MergeEntrys *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
240 OString sOldG = pResData->sGId;
241 OString sOldL = pResData->sId;
242 OString sGID = pResData->sGId;
243 OString sLID;
244 if (sGID.isEmpty())
245 sGID = pResData->sId;
246 else
247 sLID = pResData->sId;
248 pResData->sGId = sGID;
249 pResData->sId = sLID;
251 OString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
253 auto mit = aMap.find( sKey );
254 if(mit != aMap.end())
256 pResData->sGId = sOldG;
257 pResData->sId = sOldL;
258 return mit->second.get();
260 pResData->sGId = sOldG;
261 pResData->sId = sOldL;
262 return nullptr;
265 MergeEntrys *MergeDataFile::GetMergeEntrys( ResData *pResData )
267 // search for requested MergeEntrys
268 return GetMergeData( pResData );
271 MergeEntrys *MergeDataFile::GetMergeEntrysCaseSensitive( ResData *pResData )
273 // search for requested MergeEntrys
274 return GetMergeData( pResData , true );
277 void MergeDataFile::InsertEntry(
278 const OString &rTYP, const OString &rGID,
279 const OString &rLID, const OString &nLANG,
280 const OString &rTEXT, const OString &rQHTEXT,
281 const OString &rTITLE, const OString &rInFilename,
282 bool bFirstLang, bool bCaseSensitive )
284 MergeEntrys *pMergeEntrys = nullptr;
286 // search for MergeData
287 OString sKey = CreateKey(rTYP , rGID , rLID , rInFilename , bCaseSensitive);
289 if( !bFirstLang )
291 auto mit = aMap.find( sKey );
292 if(mit != aMap.end())
293 pMergeEntrys = mit->second.get();
297 if( !pMergeEntrys )
299 pMergeEntrys = new MergeEntrys;
300 aMap.emplace( sKey, std::unique_ptr<MergeEntrys>(pMergeEntrys) );
304 // insert the cur string
305 if( nLANG =="qtz" )
307 const OString sTemp = rInFilename + rGID + rLID + rTYP;
308 pMergeEntrys->InsertEntry(
309 nLANG,
310 rTEXT.isEmpty()? rTEXT : PoEntry::genKeyId(sTemp + rTEXT) + GetDoubleBars() + rTEXT,
311 rQHTEXT.isEmpty()? rQHTEXT : PoEntry::genKeyId(sTemp + rQHTEXT) + GetDoubleBars() + rQHTEXT,
312 rTITLE.isEmpty()? rTITLE : PoEntry::genKeyId(sTemp + rTITLE) + GetDoubleBars() + rTITLE );
314 else
316 pMergeEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
320 OString MergeDataFile::CreateKey(const OString& rTYP, const OString& rGID,
321 const OString& rLID, const OString& rFilename, bool bCaseSensitive)
323 static const char sStroke[] = "-";
324 OString sKey = rTYP + sStroke + rGID + sStroke + rLID + sStroke +
325 lcl_NormalizeFilename(rFilename);
326 if(bCaseSensitive)
327 return sKey; // officecfg case sensitive identifier
328 return sKey.toAsciiUpperCase();
331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */