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"
37 #include "lngmerge.hxx"
41 rtl::OString
getBracketedContent(rtl::OString text
) {
42 return text
.getToken(1, '[').getToken(0, ']');
50 LngParser::LngParser(const rtl::OString
&rLngFile
, sal_Bool bUTF8
,
58 pLines
= new LngLineList();
59 std::ifstream
aStream(sSource
.getStr());
60 if (aStream
.is_open())
62 bool bFirstLine
= true;
63 while (!aStream
.eof())
66 std::getline(aStream
, s
);
67 rtl::OString
sLine(s
.data(), s
.length());
71 // Always remove UTF8 BOM from the first line
72 Export::RemoveUTF8ByteOrderMarker( sLine
);
76 pLines
->push_back( new rtl::OString(sLine
) );
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
];
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
;
103 rtl::OString
sActFileName(
104 common::pathnameToken(sSource
.getStr(), rRoot
.getStr()));
107 sal_Bool bStart
= true;
108 rtl::OString sGroup
, sLine
;
112 while( nPos
< pLines
->size() ) {
113 sLine
= *(*pLines
)[ nPos
++ ];
114 while( nPos
< pLines
->size() && !isNextGroup( sGroup
, sLine
) ) {
115 ReadLine( sLine
, Text
);
117 sLine
= *(*pLines
)[ nPos
++ ];
124 WriteSDF( aSDFStream
, Text
, rPrj
, rRoot
, sActFileName
, sID
);
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;
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
;
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();
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
;
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();
199 sal_Bool bGroup
= sal_False
;
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();
216 while ( nPos
< pLines
->size()) {
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
);
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();
244 rtl::OString
sLang(sLine
.getToken(0, '=', n
));
251 sLang
= sLang
.trim();
253 rtl::OString
sSearch( ";" );
257 if (( sLanguagesDone
.indexOf( sSearch
) != -1 )) {
258 LngLineList::iterator it
= pLines
->begin();
259 std::advance( it
, nPos
);
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
);
274 // escape quotes, unescape double escaped quotes fdo#56648
275 sText1
+= sNewText
.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
278 Text
[ sLang
] = sNewText
;
283 sLanguagesDone
+= sSearch
;
288 sLanguagesDone
+= sSearch
;
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
== "-" )))
310 // escape quotes, unescape double escaped quotes fdo#56648
311 sLine
+= sNewText
.replaceAll("\"","\\\"").replaceAll("\\\\\"","\\\"");
317 if ( nLastLangPos
< pLines
->size() ) {
318 LngLineList::iterator it
= pLines
->begin();
319 std::advance( it
, nLastLangPos
);
320 pLines
->insert( it
, new rtl::OString(sLine
) );
322 pLines
->push_back( new rtl::OString(sLine
) );
332 for ( size_t i
= 0; i
< pLines
->size(); ++i
)
333 aDestination
<< (*pLines
)[i
]->getStr() << '\n';
335 aDestination
.close();
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */