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>
30 #include <xrmmerge.hxx>
40 // set of global variables
41 static bool bMergeMode
;
42 static bool bDisplayName
;
43 static bool bExtensionDescription
;
44 static OString sLanguage
;
45 static OString sInputFileName
;
46 static OString sOutputFile
;
47 static OString sMergeSrc
;
48 static OString sLangAttribute
;
49 static OString sResourceType
;
50 static XRMResParser
*pParser
= nullptr;
53 // the whole interface to lexer is in this extern "C" section
55 extern bool GetOutputFile( int argc
, char* argv
[])
58 bExtensionDescription
= false;
60 common::HandledArgs aArgs
;
61 if ( common::handleArguments(argc
, argv
, aArgs
) )
63 bMergeMode
= aArgs
.m_bMergeMode
;
64 sLanguage
= aArgs
.m_sLanguage
;
65 sInputFileName
= aArgs
.m_sInputFile
;
66 sOutputFile
= aArgs
.m_sOutputFile
;
67 sMergeSrc
= aArgs
.m_sMergeSrc
;
72 // command line is not valid
73 common::writeUsage("xrmex","*.xrm/*.xml");
78 int InitXrmExport( const char* pFilename
)
81 OString
sFilename( pFilename
);
84 pParser
= new XRMResMerge( sMergeSrc
, sOutputFile
, sFilename
);
85 else if (!sOutputFile
.isEmpty())
86 pParser
= new XRMResExport( sOutputFile
, sInputFileName
);
96 extern const char* getFilename()
98 return sInputFileName
.getStr();
101 extern FILE *GetXrmFile()
103 // look for valid filename
104 if (!sInputFileName
.isEmpty()) {
105 //TODO: explicit BOM handling?
106 FILE * pFile
= fopen(sInputFileName
.getStr(), "r");
108 fprintf( stderr
, "Error: Could not open file %s\n",
109 sInputFileName
.getStr());
115 // this means the file could not be opened
119 int WorkOnTokenSet( int nTyp
, char *pTokenText
)
121 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
122 pParser
->Execute( nTyp
, pTokenText
);
138 return pParser
->GetError();
145 XRMResParser::XRMResParser()
151 XRMResParser::~XRMResParser()
155 void XRMResParser::Execute( int nToken
, char * pToken
)
157 OString
rToken( pToken
);
160 case XRM_TEXT_START
:{
161 OString sNewGID
= GetAttribute( rToken
, "id" );
162 if ( sNewGID
!= sGID
) {
166 sCurrentText
= OString();
167 sCurrentOpenTag
= rToken
;
173 sCurrentCloseTag
= rToken
;
174 sResourceType
= OString ( "readmeitem" );
175 sLangAttribute
= OString ( "xml:lang" );
176 WorkOnText( sCurrentOpenTag
, sCurrentText
);
177 Output( sCurrentText
);
178 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
181 sCurrentText
= OString();
185 case DESC_DISPLAY_NAME_START
:{
190 case DESC_DISPLAY_NAME_END
:{
191 bDisplayName
= false;
195 case DESC_TEXT_START
:{
197 sGID
= OString("dispname");
199 sCurrentText
= OString();
200 sCurrentOpenTag
= rToken
;
206 case DESC_TEXT_END
: {
208 sCurrentCloseTag
= rToken
;
209 sResourceType
= OString ( "description" );
210 sLangAttribute
= OString ( "lang" );
211 WorkOnText( sCurrentOpenTag
, sCurrentText
);
212 Output( sCurrentText
);
213 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
216 sCurrentText
= OString();
221 case DESC_EXTENSION_DESCRIPTION_START
: {
222 bExtensionDescription
= true;
226 case DESC_EXTENSION_DESCRIPTION_END
: {
227 bExtensionDescription
= false;
231 case DESC_EXTENSION_DESCRIPTION_SRC
: {
232 if (bExtensionDescription
) {
233 sGID
= OString("extdesc");
234 sResourceType
= OString ( "description" );
235 sLangAttribute
= OString ( "lang" );
236 sCurrentOpenTag
= rToken
;
237 sCurrentText
= OString();
239 WorkOnDesc( sCurrentOpenTag
, sCurrentText
);
240 sCurrentCloseTag
= rToken
;
241 Output( sCurrentText
);
243 sCurrentText
= OString();
250 sCurrentText
+= rToken
;
261 OString
XRMResParser::GetAttribute( const OString
&rToken
, const OString
&rAttribute
)
263 const OString sSearch
{ " " + rAttribute
+ "=" };
264 OString sTmp
{ rToken
.replace('\t', ' ') };
265 sal_Int32 nPos
= sTmp
.indexOf( sSearch
);
270 return sTmp
.getToken(1, '"', nPos
);
274 void XRMResParser::Error( const OString
&rError
)
276 yyerror(rError
.getStr());
282 XRMResExport::XRMResExport(
283 const OString
&rOutputFile
, const OString
&rFilePath
)
287 pOutputStream
.open( rOutputFile
, PoOfstream::APP
);
288 if (!pOutputStream
.isOpen())
290 Error( "Unable to open output file: " + rOutputFile
);
294 XRMResExport::~XRMResExport()
296 pOutputStream
.close();
299 void XRMResExport::Output( const OString
& ) {}
301 void XRMResExport::WorkOnDesc(
302 const OString
&rOpenTag
,
305 const OString sDescFileName
{ sInputFileName
.replaceAll("description.xml", OString())
306 + GetAttribute( rOpenTag
, "xlink:href" ) };
307 ifstream
file (sDescFileName
.getStr(), ios::in
|ios::binary
|ios::ate
);
308 if (file
.is_open()) {
309 int size
= static_cast<int>(file
.tellg());
310 std::unique_ptr
<char[]> memblock(new char [size
+1]);
311 file
.seekg (0, ios::beg
);
312 file
.read (memblock
.get(), size
);
314 memblock
[size
] = '\0';
315 rText
= OString(memblock
.get());
317 WorkOnText( rOpenTag
, rText
);
318 EndOfText( rOpenTag
, rOpenTag
);
321 void XRMResExport::WorkOnText(
322 const OString
&rOpenTag
,
325 OString
sLang( GetAttribute( rOpenTag
, sLangAttribute
));
329 pResData
.reset( new ResData( GetGID() ) );
331 pResData
->sText
[sLang
] = rText
;
334 void XRMResExport::EndOfText(
340 OString sAct
= pResData
->sText
["en-US"];
342 if( !sAct
.isEmpty() )
343 common::writePoEntry(
344 "Xrmex", pOutputStream
, sPath
, sResourceType
,
345 pResData
->sGId
, OString(), OString(), sAct
);
353 XRMResMerge::XRMResMerge(
354 const OString
&rMergeSource
, const OString
&rOutputFile
,
355 const OString
&rFilename
)
357 sFilename( rFilename
)
359 if (!rMergeSource
.isEmpty() && sLanguage
.equalsIgnoreAsciiCase("ALL"))
361 pMergeDataFile
.reset(new MergeDataFile(
362 rMergeSource
, sInputFileName
, false));
363 aLanguages
= pMergeDataFile
->GetLanguages();
366 aLanguages
.push_back( sLanguage
);
368 rOutputFile
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
369 if (!pOutputStream
.is_open()) {
370 Error( "Unable to open output file: " + rOutputFile
);
374 XRMResMerge::~XRMResMerge()
376 pOutputStream
.close();
379 void XRMResMerge::WorkOnDesc(
380 const OString
&rOpenTag
,
383 WorkOnText( rOpenTag
, rText
);
384 if ( pMergeDataFile
&& pResData
) {
385 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
388 OString sDescFilename
= GetAttribute ( rOpenTag
, "xlink:href" );
389 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
390 sCur
= aLanguages
[ n
];
392 if ( !sCur
.equalsIgnoreAsciiCase("en-US") &&
393 ( pEntrys
->GetText( sText
, sCur
, true )) &&
396 OString sAdditionalLine
{ "\n " + rOpenTag
};
397 OString sSearch
{ sLangAttribute
+ "=\"" };
398 OString
sReplace( sSearch
);
400 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
402 sAdditionalLine
= sAdditionalLine
.replaceFirst(
405 sSearch
= OString("xlink:href=\"");
408 const OString sLocDescFilename
= sDescFilename
.replaceFirst( "en-US", sCur
);
410 sSearch
+= sDescFilename
;
411 sReplace
+= sLocDescFilename
;
412 sAdditionalLine
= sAdditionalLine
.replaceFirst(
415 Output( sAdditionalLine
);
417 sal_Int32 i
= sOutputFile
.lastIndexOf('/');
420 << "Error: output file " << sOutputFile
421 << " does not contain any /\n";
424 OString
sOutputDescFile(
425 sOutputFile
.subView(0, i
+ 1) + sLocDescFilename
);
426 ofstream
file(sOutputDescFile
.getStr());
427 if (file
.is_open()) {
432 << "Error: cannot write "
433 << sOutputDescFile
<< '\n';
443 void XRMResMerge::WorkOnText(
447 if ( pMergeDataFile
&& !pResData
) {
448 pResData
.reset( new ResData( GetGID(), sFilename
) );
449 pResData
->sResTyp
= sResourceType
;
453 void XRMResMerge::Output( const OString
& rOutput
)
455 if (!rOutput
.isEmpty())
456 pOutputStream
<< rOutput
;
459 void XRMResMerge::EndOfText(
460 const OString
&rOpenTag
,
461 const OString
&rCloseTag
)
465 if ( pMergeDataFile
&& pResData
) {
466 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
469 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
470 sCur
= aLanguages
[ n
];
472 if (!sCur
.equalsIgnoreAsciiCase("en-US") &&
473 ( pEntrys
->GetText( sContent
, sCur
, true )) &&
474 !sContent
.isEmpty() &&
475 helper::isWellFormedXML( sContent
))
477 const OString
& sText( sContent
);
478 OString sAdditionalLine
{ "\n " + rOpenTag
};
479 OString sSearch
{ sLangAttribute
+ "=\"" };
480 OString
sReplace( sSearch
);
482 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
485 sAdditionalLine
= sAdditionalLine
.replaceFirst(
486 sSearch
, sReplace
) + sText
+ rCloseTag
;
488 Output( sAdditionalLine
);
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */