nss: upgrade to release 3.73
[LibreOffice.git] / l10ntools / source / lngmerge.cxx
blobf0cdaa3ffb251f3b415a2d61e86c503e37892209
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 <cstddef>
23 #include <fstream>
24 #include <iterator>
25 #include <memory>
26 #include <string>
28 #include <po.hxx>
29 #include <lngmerge.hxx>
31 namespace {
33 bool lcl_isNextGroup(OString &sGroup_out, const OString &sLineTrim)
35 if (sLineTrim.startsWith("[") && sLineTrim.endsWith("]"))
37 sGroup_out = sLineTrim.getToken(1, '[').getToken(0, ']').trim();
38 return true;
40 return false;
43 void lcl_RemoveUTF8ByteOrderMarker( OString &rString )
45 if( rString.getLength() >= 3 && rString[0] == '\xEF' &&
46 rString[1] == '\xBB' && rString[2] == '\xBF' )
48 rString = rString.copy(3);
56 LngParser::LngParser(const OString &rLngFile)
57 : sSource( rLngFile )
59 std::ifstream aStream(sSource.getStr());
60 if (!aStream.is_open())
61 return;
63 bool bFirstLine = true;
64 std::string s;
65 std::getline(aStream, s);
66 while (!aStream.eof())
68 OString sLine(s.data(), s.length());
70 if( bFirstLine )
72 // Always remove UTF8 BOM from the first line
73 lcl_RemoveUTF8ByteOrderMarker( sLine );
74 bFirstLine = false;
77 mvLines.push_back( sLine );
78 std::getline(aStream, s);
80 mvLines.push_back( OString() );
83 LngParser::~LngParser()
87 void LngParser::CreatePO( const OString &rPOFile )
89 PoOfstream aPOStream( rPOFile, PoOfstream::APP );
90 if (!aPOStream.isOpen()) {
91 std::cerr << "Ulfex error: Can't open po file:" << rPOFile << "\n";
94 size_t nPos = 0;
95 bool bStart = true;
96 OString sGroup, sLine;
97 OStringHashMap Text;
98 OString sID;
100 while( nPos < mvLines.size() ) {
101 sLine = mvLines[ nPos++ ];
102 while( nPos < mvLines.size() && !isNextGroup( sGroup , sLine ) ) {
103 ReadLine( sLine , Text );
104 sID = sGroup;
105 sLine = mvLines[ nPos++ ];
107 if( bStart ) {
108 bStart = false;
109 sID = sGroup;
111 else {
112 WritePO( aPOStream , Text , sSource , sID );
114 Text.erase("x-comment");
116 aPOStream.close();
119 void LngParser::WritePO(PoOfstream &aPOStream,
120 OStringHashMap &rText_inout, const OString &rActFileName,
121 const OString &rID)
123 common::writePoEntry(
124 "Ulfex", aPOStream, rActFileName, "LngText",
125 rID, OString(), rText_inout.count("x-comment") ? rText_inout["x-comment"] : OString(), rText_inout["en-US"]);
128 bool LngParser::isNextGroup(OString &sGroup_out, const OString &sLine_in)
130 return lcl_isNextGroup(sGroup_out, sLine_in.trim());
133 void LngParser::ReadLine(const OString &rLine_in,
134 OStringHashMap &rText_inout)
136 if (!rLine_in.match(" *") && !rLine_in.match("/*"))
138 OString sLang(rLine_in.getToken(0, '=').trim());
139 if (!sLang.isEmpty()) {
140 OString sText(rLine_in.getToken(1, '"'));
141 rText_inout[sLang] = sText;
146 void LngParser::Merge(
147 const OString &rPOFile,
148 const OString &rDestinationFile,
149 const OString &rLanguage )
151 std::ofstream aDestination(
152 rDestinationFile.getStr(), std::ios_base::out | std::ios_base::trunc);
154 MergeDataFile aMergeDataFile( rPOFile, sSource, false, true );
155 if( rLanguage.equalsIgnoreAsciiCase("ALL") )
156 aLanguages = aMergeDataFile.GetLanguages();
158 size_t nPos = 0;
159 bool bGroup = false;
160 OString sGroup;
162 // seek to next group
163 while ( nPos < mvLines.size() && !bGroup )
164 bGroup = lcl_isNextGroup(sGroup, mvLines[nPos++].trim());
166 while ( nPos < mvLines.size()) {
167 OStringHashMap Text;
168 OString sID( sGroup );
169 std::size_t nLastLangPos = 0;
171 std::unique_ptr<ResData> pResData( new ResData( sID, sSource ) );
172 pResData->sResTyp = "LngText";
173 MergeEntrys *pEntrys = aMergeDataFile.GetMergeEntrys( pResData.get() );
174 // read languages
175 bGroup = false;
177 OString sLanguagesDone;
179 while ( nPos < mvLines.size() && !bGroup )
181 const OString sLine{ mvLines[nPos].trim() };
182 if ( lcl_isNextGroup(sGroup, sLine) )
184 bGroup = true;
185 nPos ++;
186 sLanguagesDone = "";
188 else
190 sal_Int32 n = 0;
191 OString sLang(sLine.getToken(0, '=', n));
192 if (n == -1 || static_cast<bool>(sLine.match("/*")))
194 ++nPos;
196 else
198 sLang = sLang.trim();
200 OString sSearch{ ";" + sLang + ";" };
202 if ( sLanguagesDone.indexOf( sSearch ) != -1 ) {
203 mvLines.erase( mvLines.begin() + nPos );
205 if( pEntrys )
207 if( !sLang.isEmpty() )
209 OString sNewText;
210 pEntrys->GetText( sNewText, sLang, true );
211 if( sLang == "qtz" )
212 continue;
214 if ( !sNewText.isEmpty()) {
215 mvLines[ nPos ] = sLang
216 + " = \""
217 // escape quotes, unescape double escaped quotes fdo#56648
218 + sNewText.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"")
219 + "\"";
220 Text[ sLang ] = sNewText;
223 nLastLangPos = nPos;
224 nPos ++;
225 sLanguagesDone += sSearch;
227 else {
228 nLastLangPos = nPos;
229 nPos ++;
230 sLanguagesDone += sSearch;
235 OString sCur;
236 if ( nLastLangPos )
238 for(size_t n = 0; n < aLanguages.size(); ++n)
240 sCur = aLanguages[ n ];
241 if( !sCur.equalsIgnoreAsciiCase("en-US") && Text[sCur].isEmpty() && pEntrys )
244 OString sNewText;
245 pEntrys->GetText( sNewText, sCur, true );
246 if( sCur == "qtz" )
247 continue;
248 if ( !sNewText.isEmpty() && sCur != "x-comment")
250 const OString sLine { sCur
251 + " = \""
252 // escape quotes, unescape double escaped quotes fdo#56648
253 + sNewText.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"")
254 + "\"" };
256 nLastLangPos++;
257 nPos++;
259 if ( nLastLangPos < mvLines.size() ) {
260 mvLines.insert( mvLines.begin() + nLastLangPos, sLine );
261 } else {
262 mvLines.push_back( sLine );
270 for ( size_t i = 0; i < mvLines.size(); ++i )
271 aDestination << mvLines[i] << '\n';
273 aDestination.close();
276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */