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"
28 #include "lngmerge.hxx"
32 OString
getBracketedContent(OString text
) {
33 return text
.getToken(1, '[').getToken(0, ']');
36 static void lcl_RemoveUTF8ByteOrderMarker( OString
&rString
)
38 if( rString
.getLength() >= 3 && rString
[0] == '\xEF' &&
39 rString
[1] == '\xBB' && rString
[2] == '\xBF' )
41 rString
= rString
.copy(3);
50 LngParser::LngParser(const OString
&rLngFile
,
57 pLines
= new LngLineList();
58 std::ifstream
aStream(sSource
.getStr());
59 if (aStream
.is_open())
61 bool bFirstLine
= true;
63 std::getline(aStream
, s
);
64 while (!aStream
.eof())
66 OString
sLine(s
.data(), s
.length());
70 // Always remove UTF8 BOM from the first line
71 lcl_RemoveUTF8ByteOrderMarker( sLine
);
75 pLines
->push_back( new OString(sLine
) );
76 std::getline(aStream
, s
);
78 pLines
->push_back( new OString() );
81 nError
= LNG_COULD_NOT_OPEN
;
84 LngParser::~LngParser()
86 for ( size_t i
= 0, n
= pLines
->size(); i
< n
; ++i
)
87 delete (*pLines
)[ i
];
92 sal_Bool
LngParser::CreatePO( const OString
&rPOFile
)
94 PoOfstream
aPOStream( rPOFile
, PoOfstream::APP
);
95 if (!aPOStream
.isOpen()) {
96 std::cerr
<< "Ulfex error: Can't open po file:" << rPOFile
.getStr() << "\n";
100 sal_Bool bStart
= true;
101 OString sGroup
, sLine
;
105 while( nPos
< pLines
->size() ) {
106 sLine
= *(*pLines
)[ nPos
++ ];
107 while( nPos
< pLines
->size() && !isNextGroup( sGroup
, sLine
) ) {
108 ReadLine( sLine
, Text
);
110 sLine
= *(*pLines
)[ nPos
++ ];
117 WritePO( aPOStream
, Text
, sSource
, sID
);
124 void LngParser::WritePO(PoOfstream
&aPOStream
,
125 OStringHashMap
&rText_inout
, const OString
&rActFileName
,
129 sal_Bool bExport
= true;
132 common::writePoEntry(
133 "Ulfex", aPOStream
, rActFileName
, "LngText",
134 rID
, OString(), OString(), rText_inout
["en-US"]);
138 bool LngParser::isNextGroup(OString
&sGroup_out
, const OString
&sLine_in
)
140 const OString sLineTrim
= sLine_in
.trim();
141 if ((sLineTrim
[0] == '[') && (sLineTrim
[sLineTrim
.getLength() - 1] == ']'))
143 sGroup_out
= getBracketedContent(sLineTrim
).trim();
149 void LngParser::ReadLine(const OString
&rLine_in
,
150 OStringHashMap
&rText_inout
)
152 if (!rLine_in
.match(" *") && !rLine_in
.match("/*"))
154 OString
sLang(rLine_in
.getToken(0, '=').trim());
155 if (!sLang
.isEmpty()) {
156 OString
sText(rLine_in
.getToken(1, '"'));
157 rText_inout
[sLang
] = sText
;
162 sal_Bool
LngParser::Merge(
163 const OString
&rPOFile
,
164 const OString
&rDestinationFile
,
165 const OString
&rLanguage
)
167 std::ofstream
aDestination(
168 rDestinationFile
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
169 if (!aDestination
.is_open()) {
170 nError
= LNG_COULD_NOT_OPEN
;
174 MergeDataFile
aMergeDataFile( rPOFile
, sSource
, false, true );
175 if( rLanguage
.equalsIgnoreAsciiCase("ALL") )
176 aLanguages
= aMergeDataFile
.GetLanguages();
179 sal_Bool bGroup
= sal_False
;
182 // seek to next group
183 while ( nPos
< pLines
->size() && !bGroup
)
185 OString
sLine( *(*pLines
)[ nPos
] );
186 sLine
= sLine
.trim();
187 if (!sLine
.isEmpty() &&
188 ( sLine
[0] == '[' ) &&
189 ( sLine
[sLine
.getLength() - 1] == ']' ))
191 sGroup
= getBracketedContent(sLine
).trim();
197 while ( nPos
< pLines
->size()) {
199 OString
sID( sGroup
);
200 std::size_t nLastLangPos
= 0;
202 ResData
*pResData
= new ResData( sID
, sSource
);
203 pResData
->sResTyp
= "LngText";
204 MergeEntrys
*pEntrys
= aMergeDataFile
.GetMergeEntrys( pResData
);
208 OString sLanguagesDone
;
210 while ( nPos
< pLines
->size() && !bGroup
)
212 OString
sLine( *(*pLines
)[ nPos
] );
213 sLine
= sLine
.trim();
214 if (!sLine
.isEmpty() &&
215 ( sLine
[0] == '[' ) &&
216 ( sLine
[sLine
.getLength() - 1] == ']' ))
218 sGroup
= getBracketedContent(sLine
).trim();
226 OString
sLang(sLine
.getToken(0, '=', n
));
227 if (n
== -1 || static_cast<bool>(sLine
.match("/*")))
233 sLang
= sLang
.trim();
235 OString
sSearch( ";" );
239 if (( sLanguagesDone
.indexOf( sSearch
) != -1 )) {
240 LngLineList::iterator it
= pLines
->begin();
241 std::advance( it
, nPos
);
244 if( bULF
&& pEntrys
)
246 if( !sLang
.isEmpty() )
249 pEntrys
->GetText( sNewText
, STRING_TYP_TEXT
, sLang
, sal_True
);
251 sNewText
= sNewText
.copy(sNewText
.indexOf("|") + 2);
253 if ( !sNewText
.isEmpty()) {
254 OString
*pLine
= (*pLines
)[ nPos
];
256 OString
sText1( sLang
);
258 // escape quotes, unescape double escaped quotes fdo#56648
259 sText1
+= sNewText
.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
262 Text
[ sLang
] = sNewText
;
267 sLanguagesDone
+= sSearch
;
272 sLanguagesDone
+= sSearch
;
280 for(size_t n
= 0; n
< aLanguages
.size(); ++n
)
282 sCur
= aLanguages
[ n
];
283 if( !sCur
.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) && Text
[sCur
].isEmpty() && pEntrys
)
287 pEntrys
->GetText( sNewText
, STRING_TYP_TEXT
, sCur
, sal_True
);
289 sNewText
= sNewText
.copy(sNewText
.indexOf("|") + 2);
290 if ( !sNewText
.isEmpty() && sCur
!= "x-comment")
295 // escape quotes, unescape double escaped quotes fdo#56648
296 sLine
+= sNewText
.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
302 if ( nLastLangPos
< pLines
->size() ) {
303 LngLineList::iterator it
= pLines
->begin();
304 std::advance( it
, nLastLangPos
);
305 pLines
->insert( it
, new OString(sLine
) );
307 pLines
->push_back( new OString(sLine
) );
317 for ( size_t i
= 0; i
< pLines
->size(); ++i
)
318 aDestination
<< (*pLines
)[i
]->getStr() << '\n';
320 aDestination
.close();
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */