CppunitTest_sc_tiledrendering2: move to tiledrendering folder
[LibreOffice.git] / l10ntools / source / xrmmerge.cxx
blobf69b039a44c54da722d5af8d06fa6cce826be652
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 <stdio.h>
24 #include <common.hxx>
25 #include <export.hxx>
26 #include <po.hxx>
27 #include <utility>
28 #include <xrmlex.hxx>
29 #include <xrmmerge.hxx>
30 #include <tokens.h>
31 #include <helper.hxx>
32 #include <iostream>
33 #include <vector>
34 #include <memory>
36 // set of global variables
37 static bool bMergeMode;
38 static bool bDisplayName;
39 static bool bExtensionDescription;
40 static OString sLanguage;
41 static OString sInputFileName;
42 static OString sOutputFile;
43 static OString sMergeSrc;
44 static OString sLangAttribute;
45 static OString sResourceType;
46 static XRMResParser *pParser = nullptr;
48 extern "C" {
49 // the whole interface to lexer is in this extern "C" section
51 extern bool GetOutputFile( int argc, char* argv[])
53 bDisplayName = false;
54 bExtensionDescription = false;
56 common::HandledArgs aArgs;
57 if ( common::handleArguments(argc, argv, aArgs) )
59 bMergeMode = aArgs.m_bMergeMode;
60 sLanguage = aArgs.m_sLanguage;
61 sInputFileName = aArgs.m_sInputFile;
62 sOutputFile = aArgs.m_sOutputFile;
63 sMergeSrc = aArgs.m_sMergeSrc;
64 return true;
66 else
68 // command line is not valid
69 common::writeUsage("xrmex"_ostr,"*.xrm/*.xml"_ostr);
70 return false;
74 int InitXrmExport( const char* pFilename)
76 // instantiate Export
77 OString sFilename( pFilename );
79 if ( bMergeMode )
80 pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
81 else if (!sOutputFile.isEmpty())
82 pParser = new XRMResExport( sOutputFile, sInputFileName );
84 return 1;
87 int EndXrmExport()
89 delete pParser;
90 return 1;
92 extern const char* getFilename()
94 return sInputFileName.getStr();
97 extern FILE *GetXrmFile()
99 // look for valid filename
100 if (!sInputFileName.isEmpty()) {
101 //TODO: explicit BOM handling?
102 FILE * pFile = fopen(sInputFileName.getStr(), "r");
103 if ( !pFile ){
104 fprintf( stderr, "Error: Could not open file %s\n",
105 sInputFileName.getStr());
107 else {
108 return pFile;
111 // this means the file could not be opened
112 return nullptr;
115 int WorkOnTokenSet( int nTyp, char *pTokenText )
117 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
118 pParser->Execute( nTyp, pTokenText );
120 return 1;
123 int SetError()
125 pParser->SetError();
126 return 1;
130 extern "C" {
132 int GetError()
134 return pParser->GetError();
141 XRMResParser::XRMResParser()
142 : bError( false ),
143 bText( false )
147 XRMResParser::~XRMResParser()
151 void XRMResParser::Execute( int nToken, char * pToken )
153 OString rToken( pToken );
155 switch ( nToken ) {
156 case XRM_TEXT_START:{
157 OString sNewGID = GetAttribute( rToken, "id" );
158 if ( sNewGID != sGID ) {
159 sGID = sNewGID;
161 bText = true;
162 sCurrentText = OString();
163 sCurrentOpenTag = rToken;
164 Output( rToken );
166 break;
168 case XRM_TEXT_END: {
169 sCurrentCloseTag = rToken;
170 sResourceType = "readmeitem"_ostr;
171 sLangAttribute = "xml:lang"_ostr;
172 WorkOnText( sCurrentOpenTag, sCurrentText );
173 Output( sCurrentText );
174 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
175 bText = false;
176 rToken = OString();
177 sCurrentText = OString();
179 break;
181 case DESC_DISPLAY_NAME_START:{
182 bDisplayName = true;
184 break;
186 case DESC_DISPLAY_NAME_END:{
187 bDisplayName = false;
189 break;
191 case DESC_TEXT_START:{
192 if (bDisplayName) {
193 sGID = "dispname"_ostr;
194 bText = true;
195 sCurrentText = OString();
196 sCurrentOpenTag = rToken;
197 Output( rToken );
200 break;
202 case DESC_TEXT_END: {
203 if (bDisplayName) {
204 sCurrentCloseTag = rToken;
205 sResourceType = "description"_ostr;
206 sLangAttribute = "lang"_ostr;
207 WorkOnText( sCurrentOpenTag, sCurrentText );
208 Output( sCurrentText );
209 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
210 bText = false;
211 rToken = OString();
212 sCurrentText = OString();
215 break;
217 case DESC_EXTENSION_DESCRIPTION_START: {
218 bExtensionDescription = true;
220 break;
222 case DESC_EXTENSION_DESCRIPTION_END: {
223 bExtensionDescription = false;
225 break;
227 case DESC_EXTENSION_DESCRIPTION_SRC: {
228 if (bExtensionDescription) {
229 sGID = "extdesc"_ostr;
230 sResourceType = "description"_ostr;
231 sLangAttribute = "lang"_ostr;
232 sCurrentOpenTag = rToken;
233 sCurrentText = OString();
234 Output( rToken );
235 WorkOnDesc( sCurrentOpenTag, sCurrentText );
236 sCurrentCloseTag = rToken;
237 Output( sCurrentText );
238 rToken = OString();
239 sCurrentText = OString();
242 break;
244 default:
245 if ( bText ) {
246 sCurrentText += rToken;
248 break;
251 if ( !bText )
253 Output( rToken );
257 OString XRMResParser::GetAttribute( const OString &rToken, std::string_view rAttribute )
259 const OString sSearch{ OString::Concat(" ") + rAttribute + "=" };
260 OString sTmp{ rToken.replace('\t', ' ') };
261 sal_Int32 nPos = sTmp.indexOf( sSearch );
263 if ( nPos<0 )
264 return OString();
266 return sTmp.getToken(1, '"', nPos);
270 void XRMResParser::Error( const OString &rError )
272 yyerror(rError.getStr());
278 XRMResExport::XRMResExport(
279 const OString &rOutputFile, OString _sFilePath )
280 : sPath(std::move( _sFilePath ))
282 pOutputStream.open( rOutputFile, PoOfstream::APP );
283 if (!pOutputStream.isOpen())
285 Error( "Unable to open output file: " + rOutputFile );
289 XRMResExport::~XRMResExport()
291 pOutputStream.close();
294 void XRMResExport::Output( const OString& ) {}
296 void XRMResExport::WorkOnDesc(
297 const OString &rOpenTag,
298 OString &rText )
300 const OString sDescFileName{ sInputFileName.replaceAll("description.xml"_ostr, OString())
301 + GetAttribute( rOpenTag, "xlink:href" ) };
302 std::ifstream file (sDescFileName.getStr(), std::ios::in|std::ios::binary|std::ios::ate);
303 if (file.is_open()) {
304 int size = static_cast<int>(file.tellg());
305 std::unique_ptr<char[]> memblock(new char [size+1]);
306 file.seekg (0, std::ios::beg);
307 file.read (memblock.get(), size);
308 file.close();
309 memblock[size] = '\0';
310 rText = OString(memblock.get());
312 WorkOnText( rOpenTag, rText );
313 EndOfText( rOpenTag, rOpenTag );
316 void XRMResExport::WorkOnText(
317 const OString &rOpenTag,
318 OString &rText )
320 OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
322 if ( !pResData )
324 pResData.reset( new ResData( GetGID() ) );
326 pResData->sText[sLang] = rText;
329 void XRMResExport::EndOfText(
330 const OString &,
331 const OString & )
333 if ( pResData )
335 OString sAct = pResData->sText["en-US"_ostr];
337 if( !sAct.isEmpty() )
338 common::writePoEntry(
339 "Xrmex"_ostr, pOutputStream, sPath, sResourceType,
340 pResData->sGId, OString(), OString(), sAct );
342 pResData.reset();
348 XRMResMerge::XRMResMerge(
349 const OString &rMergeSource, const OString &rOutputFile,
350 OString _sFilename )
351 : sFilename(std::move( _sFilename ))
353 if (!rMergeSource.isEmpty() && sLanguage.equalsIgnoreAsciiCase("ALL"))
355 pMergeDataFile.reset(new MergeDataFile(
356 rMergeSource, sInputFileName, false));
357 aLanguages = pMergeDataFile->GetLanguages();
359 else
360 aLanguages.push_back( sLanguage );
361 pOutputStream.open(
362 rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
363 if (!pOutputStream.is_open()) {
364 Error( "Unable to open output file: " + rOutputFile );
368 XRMResMerge::~XRMResMerge()
370 pOutputStream.close();
373 void XRMResMerge::WorkOnDesc(
374 const OString &rOpenTag,
375 OString &rText )
377 WorkOnText( rOpenTag, rText);
378 if ( pMergeDataFile && pResData ) {
379 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
380 if ( pEntrys ) {
381 OString sCur;
382 OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
383 for( size_t n = 0; n < aLanguages.size(); n++ ){
384 sCur = aLanguages[ n ];
385 OString sText;
386 if ( !sCur.equalsIgnoreAsciiCase("en-US") &&
387 ( pEntrys->GetText( sText, sCur, true )) &&
388 !sText.isEmpty())
390 OString sAdditionalLine{ "\n " + rOpenTag };
391 OString sSearch{ sLangAttribute + "=\"" };
392 OString sReplace( sSearch );
394 sSearch += GetAttribute( rOpenTag, sLangAttribute );
395 sReplace += sCur;
396 sAdditionalLine = sAdditionalLine.replaceFirst(
397 sSearch, sReplace);
399 sSearch = "xlink:href=\""_ostr;
400 sReplace = sSearch;
402 const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US"_ostr, sCur);
404 sSearch += sDescFilename;
405 sReplace += sLocDescFilename;
406 sAdditionalLine = sAdditionalLine.replaceFirst(
407 sSearch, sReplace);
409 Output( sAdditionalLine );
411 sal_Int32 i = sOutputFile.lastIndexOf('/');
412 if (i == -1) {
413 std::cerr
414 << "Error: output file " << sOutputFile
415 << " does not contain any /\n";
416 throw false; //TODO
418 OString sOutputDescFile(
419 sOutputFile.subView(0, i + 1) + sLocDescFilename);
420 std::ofstream file(sOutputDescFile.getStr());
421 if (file.is_open()) {
422 file << sText;
423 file.close();
424 } else {
425 std::cerr
426 << "Error: cannot write "
427 << sOutputDescFile << '\n';
428 throw false; //TODO
434 pResData.reset();
437 void XRMResMerge::WorkOnText(
438 const OString &,
439 OString & )
441 if ( pMergeDataFile && !pResData ) {
442 pResData.reset( new ResData( GetGID(), sFilename ) );
443 pResData->sResTyp = sResourceType;
447 void XRMResMerge::Output( const OString& rOutput )
449 if (!rOutput.isEmpty())
450 pOutputStream << rOutput;
453 void XRMResMerge::EndOfText(
454 const OString &rOpenTag,
455 const OString &rCloseTag )
458 Output( rCloseTag );
459 if ( pMergeDataFile && pResData ) {
460 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
461 if ( pEntrys ) {
462 OString sCur;
463 for( size_t n = 0; n < aLanguages.size(); n++ ){
464 sCur = aLanguages[ n ];
465 OString sContent;
466 if (!sCur.equalsIgnoreAsciiCase("en-US") &&
467 ( pEntrys->GetText( sContent, sCur, true )) &&
468 !sContent.isEmpty() &&
469 helper::isWellFormedXML( sContent ))
471 const OString& sText( sContent );
472 OString sAdditionalLine{ "\n " + rOpenTag };
473 OString sSearch{ sLangAttribute + "=\"" };
474 OString sReplace( sSearch );
476 sSearch += GetAttribute( rOpenTag, sLangAttribute );
477 sReplace += sCur;
479 sAdditionalLine = sAdditionalLine.replaceFirst(
480 sSearch, sReplace) + sText + rCloseTag;
482 Output( sAdditionalLine );
487 pResData.reset();
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */