Bump for 3.6-28
[LibreOffice.git] / l10ntools / source / lngmerge.cxx
blob3a7a8d5f731e060e7e4eeb290f0008edc4be7bbc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
31 #include <cstddef>
32 #include <fstream>
33 #include <iterator>
34 #include <string>
36 #include "common.hxx"
37 #include "lngmerge.hxx"
39 namespace {
41 rtl::OString getBracketedContent(rtl::OString text) {
42 return text.getToken(1, '[').getToken(0, ']');
48 // class LngParser
50 LngParser::LngParser(const rtl::OString &rLngFile, sal_Bool bUTF8,
51 sal_Bool bULFFormat)
52 : nError( LNG_OK )
53 , pLines( NULL )
54 , sSource( rLngFile )
55 , bDBIsUTF8( bUTF8 )
56 , bULF( bULFFormat )
58 pLines = new LngLineList();
59 std::ifstream aStream(sSource.getStr());
60 if (aStream.is_open())
62 bool bFirstLine = true;
63 while (!aStream.eof())
65 std::string s;
66 std::getline(aStream, s);
67 rtl::OString sLine(s.data(), s.length());
69 if( bFirstLine )
71 // Always remove UTF8 BOM from the first line
72 Export::RemoveUTF8ByteOrderMarker( sLine );
73 bFirstLine = false;
76 pLines->push_back( new rtl::OString(sLine) );
79 else
80 nError = LNG_COULD_NOT_OPEN;
83 LngParser::~LngParser()
85 for ( size_t i = 0, n = pLines->size(); i < n; ++i )
86 delete (*pLines)[ i ];
87 pLines->clear();
88 delete pLines;
91 sal_Bool LngParser::CreateSDF(const rtl::OString &rSDFFile,
92 const rtl::OString &rPrj, const rtl::OString &rRoot)
95 Export::InitLanguages( false );
96 aLanguages = Export::GetLanguages();
97 std::ofstream aSDFStream(
98 rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc);
99 if (!aSDFStream.is_open()) {
100 nError = SDF_COULD_NOT_OPEN;
102 nError = SDF_OK;
103 rtl::OString sActFileName(
104 common::pathnameToken(sSource.getStr(), rRoot.getStr()));
106 size_t nPos = 0;
107 sal_Bool bStart = true;
108 rtl::OString sGroup, sLine;
109 OStringHashMap Text;
110 rtl::OString sID;
112 while( nPos < pLines->size() ) {
113 sLine = *(*pLines)[ nPos++ ];
114 while( nPos < pLines->size() && !isNextGroup( sGroup , sLine ) ) {
115 ReadLine( sLine , Text );
116 sID = sGroup;
117 sLine = *(*pLines)[ nPos++ ];
119 if( bStart ) {
120 bStart = false;
121 sID = sGroup;
123 else {
124 WriteSDF( aSDFStream , Text , rPrj , rRoot , sActFileName , sID );
127 aSDFStream.close();
128 return true;
131 void LngParser::WriteSDF(std::ofstream &aSDFStream,
132 OStringHashMap &rText_inout, const rtl::OString &rPrj,
133 const rtl::OString &rRoot, const rtl::OString &rActFileName,
134 const rtl::OString &rID)
137 sal_Bool bExport = true;
138 if ( bExport ) {
139 rtl::OString sCur;
140 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
141 sCur = aLanguages[ n ];
142 rtl::OString sAct = rText_inout[ sCur ];
143 if ( sAct.isEmpty() && !sCur.isEmpty() )
144 sAct = rText_inout[ rtl::OString("en-US") ];
146 rtl::OString sOutput( rPrj ); sOutput += "\t";
147 if (rRoot.getLength())
148 sOutput += rActFileName;
149 sOutput += "\t0\t";
150 sOutput += "LngText\t";
151 sOutput += rID; sOutput += "\t\t\t\t0\t";
152 sOutput += sCur; sOutput += "\t";
153 sOutput += sAct; sOutput += "\t\t\t\t";
154 aSDFStream << sOutput.getStr() << '\n';
159 bool LngParser::isNextGroup(rtl::OString &sGroup_out, rtl::OString &sLine_in)
161 sLine_in = sLine_in.trim();
162 if ((sLine_in[0] == '[') && (sLine_in[sLine_in.getLength() - 1] == ']'))
164 sGroup_out = getBracketedContent(sLine_in).trim();
165 return true;
167 return false;
170 void LngParser::ReadLine(const rtl::OString &rLine_in,
171 OStringHashMap &rText_inout)
173 rtl::OString sLang(rLine_in.getToken(0, '=').trim());
174 if (!sLang.isEmpty()) {
175 rtl::OString sText(rLine_in.getToken(1, '"'));
176 rText_inout[sLang] = sText;
180 sal_Bool LngParser::Merge(
181 const rtl::OString &rSDFFile,
182 const rtl::OString &rDestinationFile)
184 Export::InitLanguages( true );
185 std::ofstream aDestination(
186 rDestinationFile.getStr(), std::ios_base::out | std::ios_base::trunc);
187 if (!aDestination.is_open()) {
188 nError = LNG_COULD_NOT_OPEN;
190 nError = LNG_OK;
192 MergeDataFile aMergeDataFile( rSDFFile, sSource, sal_False );
193 rtl::OString sTmp( Export::sLanguages );
194 if( sTmp.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ALL")) )
195 Export::SetLanguages( aMergeDataFile.GetLanguages() );
196 aLanguages = Export::GetLanguages();
198 size_t nPos = 0;
199 sal_Bool bGroup = sal_False;
200 rtl::OString sGroup;
202 // seek to next group
203 while ( nPos < pLines->size() && !bGroup )
205 rtl::OString sLine( *(*pLines)[ nPos ] );
206 sLine = sLine.trim();
207 if (( sLine[0] == '[' ) &&
208 ( sLine[sLine.getLength() - 1] == ']' ))
210 sGroup = getBracketedContent(sLine).trim();
211 bGroup = sal_True;
213 nPos ++;
216 while ( nPos < pLines->size()) {
217 OStringHashMap Text;
218 rtl::OString sID( sGroup );
219 std::size_t nLastLangPos = 0;
221 ResData *pResData = new ResData( "", sID , sSource );
222 pResData->sResTyp = "LngText";
223 PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
224 // read languages
225 bGroup = sal_False;
227 rtl::OString sLanguagesDone;
229 while ( nPos < pLines->size() && !bGroup )
231 rtl::OString sLine( *(*pLines)[ nPos ] );
232 sLine = sLine.trim();
233 if (( sLine[0] == '[' ) &&
234 ( sLine[sLine.getLength() - 1] == ']' ))
236 sGroup = getBracketedContent(sLine).trim();
237 bGroup = sal_True;
238 nPos ++;
239 sLanguagesDone = "";
241 else
243 sal_Int32 n = 0;
244 rtl::OString sLang(sLine.getToken(0, '=', n));
245 if (n == -1)
247 ++nPos;
249 else
251 sLang = sLang.trim();
253 rtl::OString sSearch( ";" );
254 sSearch += sLang;
255 sSearch += ";";
257 if (( sLanguagesDone.indexOf( sSearch ) != -1 )) {
258 LngLineList::iterator it = pLines->begin();
259 std::advance( it, nPos );
260 pLines->erase( it );
262 if( bULF && pEntrys )
264 if( !sLang.isEmpty() )
266 rtl::OString sNewText;
267 pEntrys->GetText( sNewText, STRING_TYP_TEXT, sLang, sal_True );
269 if ( !sNewText.isEmpty()) {
270 rtl::OString *pLine = (*pLines)[ nPos ];
272 rtl::OString sText1( sLang );
273 sText1 += " = \"";
274 // escape quotes, unescape double escaped quotes fdo#56648
275 sText1 += sNewText.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
276 sText1 += "\"";
277 *pLine = sText1;
278 Text[ sLang ] = sNewText;
281 nLastLangPos = nPos;
282 nPos ++;
283 sLanguagesDone += sSearch;
285 else {
286 nLastLangPos = nPos;
287 nPos ++;
288 sLanguagesDone += sSearch;
293 rtl::OString sCur;
294 if ( nLastLangPos )
296 for(size_t n = 0; n < aLanguages.size(); ++n)
298 sCur = aLanguages[ n ];
299 if( !sCur.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) && Text[sCur].isEmpty() && pEntrys )
302 rtl::OString sNewText;
303 pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur, sal_True );
304 if (( !sNewText.isEmpty()) &&
305 !(( sCur.equalsL(RTL_CONSTASCII_STRINGPARAM("x-comment"))) && ( sNewText == "-" )))
307 rtl::OString sLine;
308 sLine += sCur;
309 sLine += " = \"";
310 // escape quotes, unescape double escaped quotes fdo#56648
311 sLine += sNewText.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
312 sLine += "\"";
314 nLastLangPos++;
315 nPos++;
317 if ( nLastLangPos < pLines->size() ) {
318 LngLineList::iterator it = pLines->begin();
319 std::advance( it, nLastLangPos );
320 pLines->insert( it, new rtl::OString(sLine) );
321 } else {
322 pLines->push_back( new rtl::OString(sLine) );
329 delete pResData;
332 for ( size_t i = 0; i < pLines->size(); ++i )
333 aDestination << (*pLines)[i]->getStr() << '\n';
335 aDestination.close();
336 return sal_True;
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */