Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <algorithm>
23 : #include <fstream>
24 : #include <string>
25 : #include <vector>
26 :
27 : #include "export.hxx"
28 : #include "po.hxx"
29 :
30 : namespace
31 : {
32 1273 : static ::rtl::OString lcl_NormalizeFilename(const ::rtl::OString& rFilename)
33 : {
34 : return rFilename.copy(
35 : std::max(
36 1273 : rFilename.lastIndexOf( '\\' ),
37 2546 : rFilename.lastIndexOf( '/' ))+1);
38 : };
39 :
40 0 : static bool lcl_ReadPoChecked(
41 : PoEntry& o_rPoEntry, PoIfstream& rPoFile,
42 : const OString& rFileName)
43 : {
44 : try
45 : {
46 0 : rPoFile.readEntry( o_rPoEntry );
47 : }
48 0 : catch( PoIfstream::Exception& aException )
49 : {
50 0 : if( aException == PoIfstream::INVALIDENTRY )
51 : {
52 : printf(
53 : "Warning : %s contains invalid entry\n",
54 0 : rFileName.getStr() );
55 0 : return false;
56 : }
57 : }
58 0 : return true;
59 : }
60 : }
61 :
62 : //
63 : // class PFormEntrys
64 : //
65 :
66 0 : sal_Bool PFormEntrys::GetTransex3Text( rtl::OString &rReturn,
67 : sal_uInt16 nTyp, const rtl::OString &nLangIndex, sal_Bool bDel )
68 : {
69 0 : sal_Bool rc = GetText( rReturn , nTyp , nLangIndex , bDel );
70 0 : for( sal_Int32 idx = 0; idx < rReturn.getLength(); idx++ )
71 : {
72 0 : if( rReturn[idx] == '\"' && ( idx >= 1 ) && rReturn[idx-1] == '\\' )
73 : {
74 0 : rReturn = rReturn.replaceAt( idx-1, 1, rtl::OString() );
75 : }
76 : }
77 0 : return rc;
78 : }
79 : /*****************************************************************************/
80 0 : sal_Bool PFormEntrys::GetText( rtl::OString &rReturn,
81 : sal_uInt16 nTyp, const rtl::OString &nLangIndex, sal_Bool bDel )
82 : {
83 :
84 0 : sal_Bool bReturn=sal_True;
85 0 : switch ( nTyp ) {
86 : case STRING_TYP_TEXT :
87 0 : rReturn = sText[ nLangIndex ];
88 0 : if ( bDel )
89 0 : sText[ nLangIndex ] = "";
90 0 : bReturn = bTextFirst[ nLangIndex ];
91 0 : bTextFirst[ nLangIndex ] = sal_False;
92 0 : break;
93 : case STRING_TYP_HELPTEXT :
94 0 : rReturn = sHelpText;
95 0 : break;
96 : case STRING_TYP_QUICKHELPTEXT :
97 0 : rReturn = sQuickHelpText[ nLangIndex ];
98 0 : if ( bDel )
99 0 : sQuickHelpText[ nLangIndex ] = "";
100 0 : bReturn = bQuickHelpTextFirst[ nLangIndex ];
101 0 : bQuickHelpTextFirst[ nLangIndex ] = sal_False;
102 0 : break;
103 : case STRING_TYP_TITLE :
104 0 : rReturn = sTitle[ nLangIndex ];
105 0 : if ( bDel )
106 0 : sTitle[ nLangIndex ] = "";
107 0 : bReturn = bTitleFirst[ nLangIndex ];
108 0 : bTitleFirst[ nLangIndex ] = sal_False;
109 0 : break;
110 : }
111 0 : return bReturn;
112 : }
113 :
114 :
115 : //
116 : // class MergeData
117 : //
118 :
119 0 : MergeData::~MergeData()
120 : {
121 0 : }
122 :
123 0 : PFormEntrys* MergeData::GetPFormEntries()
124 : {
125 0 : if( aMap.find( rtl::OString(RTL_CONSTASCII_STRINGPARAM("HACK")) ) != aMap.end() )
126 0 : return aMap[rtl::OString(RTL_CONSTASCII_STRINGPARAM("HACK"))];
127 0 : return NULL;
128 : }
129 :
130 0 : void MergeData::Insert(PFormEntrys* pfEntrys )
131 : {
132 0 : aMap.insert( PFormEntrysHashMap::value_type( rtl::OString(RTL_CONSTASCII_STRINGPARAM("HACK")) , pfEntrys ) );
133 0 : }
134 :
135 0 : PFormEntrys* MergeData::GetPFObject( const rtl::OString& rPFO )
136 : {
137 0 : if( aMap.find( rtl::OString(RTL_CONSTASCII_STRINGPARAM("HACK")) ) != aMap.end() )
138 0 : return aMap[ rPFO ];
139 0 : return NULL;
140 : }
141 :
142 0 : sal_Bool MergeData::operator==( ResData *pData )
143 : {
144 0 : return pData->sId == sLID && pData->sGId == sGID
145 0 : && pData->sResTyp.equalsIgnoreAsciiCase(sTyp);
146 : }
147 :
148 : //
149 : // class MergeDataFile
150 : //
151 :
152 14 : MergeDataFile::MergeDataFile(
153 : const rtl::OString &rFileName, const rtl::OString &rFile,
154 14 : bool bCaseSensitive, bool bWithQtz )
155 : {
156 14 : std::ifstream aInputStream( rFileName.getStr() );
157 14 : if ( !aInputStream.is_open() )
158 : {
159 0 : printf("Warning : Can't open po path container file\n");
160 : return;
161 : }
162 14 : std::string sPoFile;
163 14 : aInputStream >> sPoFile;
164 14 : bool bFirstLang = true;
165 28 : while( !aInputStream.eof() )
166 : {
167 0 : const OString sHack("HACK");
168 0 : const OString sFileName( lcl_NormalizeFilename(rFile) );
169 0 : const bool bReadAll = sFileName.isEmpty();
170 0 : const OString sPoFileName(sPoFile.data(), sPoFile.length());
171 0 : PoIfstream aPoInput;
172 0 : aPoInput.open( sPoFileName );
173 0 : if ( !aPoInput.isOpen() )
174 : {
175 0 : printf( "Warning : Can't open %s\n", sPoFileName.getStr() );
176 : return;
177 : }
178 :
179 0 : OString sLang;
180 : //Get language id from path
181 : {
182 0 : const OString sTransSource("translations/source/");
183 : const sal_Int32 nStart =
184 0 : sPoFileName.indexOf(sTransSource)+sTransSource.getLength();
185 : const sal_Int32 nCount =
186 0 : sPoFileName.indexOf("/",nStart) - nStart;
187 0 : sLang = sPoFileName.copy(nStart,nCount);
188 : }
189 0 : aLanguageSet.insert( sLang );
190 0 : PoEntry aNextPo;
191 0 : do
192 : {
193 0 : if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
194 : {
195 : return;
196 : }
197 0 : } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
198 0 : while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ))
199 : {
200 0 : PoEntry aActPo( aNextPo );
201 :
202 0 : bool bInSameComp = false;
203 0 : OString sText;
204 0 : OString sQHText;
205 0 : OString sTitle;
206 0 : OString sExText;
207 0 : OString sExQHText;
208 0 : OString sExTitle;
209 0 : OString sQTZText;
210 0 : OString sQTZQHText;
211 0 : OString sQTZTitle;
212 0 : do
213 : {
214 0 : if( bInSameComp )
215 0 : aActPo = aNextPo;
216 0 : OString sTemp = aActPo.getMsgStr();
217 0 : if( aActPo.isFuzzy() || sTemp.isEmpty() )
218 0 : sTemp = aActPo.getMsgId();
219 0 : switch( aActPo.getType() )
220 : {
221 : case PoEntry::TTEXT:
222 0 : sText = sTemp;
223 0 : sExText = aActPo.getMsgId();
224 0 : sQTZText = aActPo.getKeyId();
225 0 : break;
226 : case PoEntry::TQUICKHELPTEXT:
227 0 : sQHText = sTemp;
228 0 : sExQHText = aActPo.getMsgId();
229 0 : sQTZQHText = aActPo.getKeyId();
230 0 : break;
231 : case PoEntry::TTITLE:
232 0 : sTitle = sTemp;
233 0 : sExTitle = aActPo.getMsgId();
234 0 : sQTZTitle = aActPo.getKeyId();
235 0 : break;
236 : }
237 0 : if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
238 : {
239 : return;
240 0 : }
241 0 : } while( !aPoInput.eof() &&
242 : ( bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo) ) );
243 :
244 : InsertEntry(
245 : aActPo.getResourceType(), aActPo.getGroupId(),
246 : aActPo.getLocalId(), sHack, sLang, sText,
247 0 : sQHText, sTitle, aActPo.getSourceFile(), bCaseSensitive );
248 :
249 0 : if( bFirstLang && bWithQtz &&
250 0 : ( strcmp(getenv("ENABLE_RELEASE_BUILD"),"TRUE") ) )
251 : {
252 0 : aLanguageSet.insert("qtz");
253 : InsertEntry(
254 : aActPo.getResourceType(), aActPo.getGroupId(),
255 : aActPo.getLocalId(), sHack, "qtz",
256 0 : sQTZText + "||" + sExText, sQTZQHText + "||" + sExQHText,
257 0 : sQTZTitle + "||" + sExTitle, aActPo.getSourceFile(),
258 0 : bCaseSensitive );
259 : }
260 0 : }
261 0 : aPoInput.close();
262 0 : aInputStream >> sPoFile;
263 0 : bFirstLang = false;
264 0 : }
265 14 : aInputStream.close();
266 : }
267 :
268 28 : MergeDataFile::~MergeDataFile()
269 : {
270 14 : for (MergeDataHashMap::iterator aI = aMap.begin(), aEnd = aMap.end(); aI != aEnd; ++aI)
271 0 : delete aI->second;
272 14 : }
273 :
274 14 : std::vector<rtl::OString> MergeDataFile::GetLanguages() const
275 : {
276 14 : return std::vector<rtl::OString>(aLanguageSet.begin(),aLanguageSet.end());
277 : }
278 :
279 1273 : MergeData *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
280 : {
281 1273 : rtl::OString sOldG = pResData->sGId;
282 1273 : rtl::OString sOldL = pResData->sId;
283 1273 : rtl::OString sGID = pResData->sGId;
284 1273 : rtl::OString sLID;
285 1273 : if (sGID.isEmpty())
286 375 : sGID = pResData->sId;
287 : else
288 898 : sLID = pResData->sId;
289 1273 : pResData->sGId = sGID;
290 1273 : pResData->sId = sLID;
291 :
292 1273 : rtl::OString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
293 :
294 1273 : if(aMap.find( sKey ) != aMap.end())
295 : {
296 0 : pResData->sGId = sOldG;
297 0 : pResData->sId = sOldL;
298 0 : return aMap[ sKey ];
299 : }
300 1273 : pResData->sGId = sOldG;
301 1273 : pResData->sId = sOldL;
302 1273 : return NULL;
303 : }
304 :
305 :
306 1273 : PFormEntrys *MergeDataFile::GetPFormEntrys( ResData *pResData )
307 : {
308 : // search for requested PFormEntrys
309 1273 : MergeData *pData = GetMergeData( pResData );
310 1273 : if ( pData )
311 0 : return pData->GetPFormEntries();
312 1273 : return NULL;
313 : }
314 :
315 0 : PFormEntrys *MergeDataFile::GetPFormEntrysCaseSensitive( ResData *pResData )
316 : {
317 : // search for requested PFormEntrys
318 0 : MergeData *pData = GetMergeData( pResData , true );
319 0 : if ( pData )
320 0 : return pData->GetPFormEntries();
321 0 : return NULL;
322 : }
323 :
324 0 : void MergeDataFile::InsertEntry(
325 : const rtl::OString &rTYP, const rtl::OString &rGID,
326 : const rtl::OString &rLID, const rtl::OString &rPFO,
327 : const rtl::OString &nLANG, const rtl::OString &rTEXT,
328 : const rtl::OString &rQHTEXT, const rtl::OString &rTITLE ,
329 : const rtl::OString &rInFilename , bool bCaseSensitive
330 : )
331 : {
332 : MergeData *pData;
333 :
334 : // search for MergeData
335 0 : rtl::OString sKey = CreateKey(rTYP , rGID , rLID , rInFilename , bCaseSensitive);
336 0 : MergeDataHashMap::const_iterator mit;
337 0 : mit = aMap.find( sKey );
338 0 : if( mit != aMap.end() )
339 : {
340 0 : pData = mit->second;
341 : }
342 : else
343 : {
344 0 : pData = new MergeData( rTYP, rGID, rLID, rInFilename );
345 0 : aMap.insert( MergeDataHashMap::value_type( sKey, pData ) );
346 : }
347 :
348 0 : PFormEntrys *pFEntrys = 0;
349 :
350 : // search for PFormEntrys
351 0 : pFEntrys = pData->GetPFObject( rPFO );
352 0 : if( !pFEntrys )
353 : {
354 : // create new PFormEntrys, cause no one exists with current properties
355 0 : pFEntrys = new PFormEntrys( rPFO );
356 0 : pData->Insert( pFEntrys );
357 : }
358 :
359 : // finaly insert the cur string
360 0 : pFEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
361 0 : }
362 :
363 1273 : rtl::OString MergeDataFile::CreateKey(const rtl::OString& rTYP, const rtl::OString& rGID,
364 : const rtl::OString& rLID, const rtl::OString& rFilename, bool bCaseSensitive)
365 : {
366 1273 : static const ::rtl::OString sStroke('-');
367 1273 : ::rtl::OString sKey( rTYP );
368 1273 : sKey += sStroke;
369 1273 : sKey += rGID;
370 1273 : sKey += sStroke;
371 1273 : sKey += rLID;
372 1273 : sKey += sStroke;
373 1273 : sKey += lcl_NormalizeFilename(rFilename);
374 : OSL_TRACE("created key: %s", sKey.getStr());
375 1273 : if(bCaseSensitive)
376 0 : return sKey; // officecfg case sensitive identifier
377 1273 : return sKey.toAsciiUpperCase();
378 : }
379 :
380 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|