bump product version to 4.1.6.2
[LibreOffice.git] / l10ntools / source / xrmmerge.cxx
blob8265b4afcbb148230ba2d6b21cf89d2ad1622654
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 <cstring>
24 #include <stdio.h>
26 #include "common.hxx"
27 #include "export.hxx"
28 #include "po.hxx"
29 #include "xrmmerge.hxx"
30 #include "tokens.h"
31 #include "helper.hxx"
32 #include <iostream>
33 #include <fstream>
34 #include <vector>
36 using namespace std;
38 void yyerror( const char * );
39 void YYWarning( const char * );
41 // set of global variables
42 bool bMergeMode;
43 sal_Bool bDisplayName;
44 sal_Bool bExtensionDescription;
45 OString sLanguage;
46 OString sInputFileName;
47 OString sOutputFile;
48 OString sMergeSrc;
49 OString sLangAttribute;
50 OString sResourceType;
51 XRMResParser *pParser = NULL;
53 extern "C" {
54 // the whole interface to lexer is in this extern "C" section
56 extern char *GetOutputFile( int argc, char* argv[])
58 bDisplayName = sal_False;
59 bExtensionDescription = sal_False;
61 common::HandledArgs aArgs;
62 if ( common::handleArguments(argc, argv, aArgs) )
64 bMergeMode = aArgs.m_bMergeMode;
65 sLanguage = aArgs.m_sLanguage;
66 sInputFileName = aArgs.m_sInputFile;
67 sOutputFile = aArgs.m_sOutputFile;
68 sMergeSrc = aArgs.m_sMergeSrc;
69 char *pReturn = new char[ sOutputFile.getLength() + 1 ];
70 std::strcpy( pReturn, sOutputFile.getStr());
71 return pReturn;
73 else
75 // command line is not valid
76 common::writeUsage("xrmex","*.xrm/*.xml");
77 return NULL;
81 int InitXrmExport( char*, char* pFilename)
83 // instanciate Export
84 OString sFilename( pFilename );
86 if ( bMergeMode )
87 pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
88 else if (!sOutputFile.isEmpty()) {
89 pParser = new XRMResExport( sOutputFile, sInputFileName );
92 return 1;
95 int EndXrmExport()
97 delete pParser;
98 return 1;
100 extern const char* getFilename()
102 return sInputFileName.getStr();
105 extern FILE *GetXrmFile()
107 // look for valid filename
108 if (!sInputFileName.isEmpty()) {
109 //TODO: explicit BOM handling?
110 FILE * pFile = fopen(sInputFileName.getStr(), "r");
111 if ( !pFile ){
112 fprintf( stderr, "Error: Could not open file %s\n",
113 sInputFileName.getStr());
115 else {
116 return pFile;
119 // this means the file could not be opened
120 return NULL;
123 int WorkOnTokenSet( int nTyp, char *pTokenText )
125 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
126 pParser->Execute( nTyp, pTokenText );
128 return 1;
131 int SetError()
133 pParser->SetError();
134 return 1;
138 extern "C" {
140 int GetError()
142 return pParser->GetError();
147 // class XRMResParser
151 XRMResParser::XRMResParser()
152 : bError( sal_False ),
153 bText( sal_False )
157 XRMResParser::~XRMResParser()
161 int XRMResParser::Execute( int nToken, char * pToken )
163 OString rToken( pToken );
165 switch ( nToken ) {
166 case XRM_TEXT_START:{
167 OString sNewGID = GetAttribute( rToken, "id" );
168 if ( sNewGID != sGID ) {
169 sGID = sNewGID;
171 bText = sal_True;
172 sCurrentText = "";
173 sCurrentOpenTag = rToken;
174 Output( rToken );
176 break;
178 case XRM_TEXT_END: {
179 sCurrentCloseTag = rToken;
180 sResourceType = OString ( "readmeitem" );
181 sLangAttribute = OString ( "xml:lang" );
182 WorkOnText( sCurrentOpenTag, sCurrentText );
183 Output( sCurrentText );
184 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
185 bText = sal_False;
186 rToken = OString("");
187 sCurrentText = OString("");
189 break;
191 case DESC_DISPLAY_NAME_START:{
192 bDisplayName = sal_True;
194 break;
196 case DESC_DISPLAY_NAME_END:{
197 bDisplayName = sal_False;
199 break;
201 case DESC_TEXT_START:{
202 if (bDisplayName) {
203 sGID = OString("dispname");
204 bText = sal_True;
205 sCurrentText = "";
206 sCurrentOpenTag = rToken;
207 Output( rToken );
210 break;
212 case DESC_TEXT_END: {
213 if (bDisplayName) {
214 sCurrentCloseTag = rToken;
215 sResourceType = OString ( "description" );
216 sLangAttribute = OString ( "lang" );
217 WorkOnText( sCurrentOpenTag, sCurrentText );
218 Output( sCurrentText );
219 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
220 bText = sal_False;
221 rToken = OString("");
222 sCurrentText = OString("");
225 break;
227 case DESC_EXTENSION_DESCRIPTION_START: {
228 bExtensionDescription = sal_True;
230 break;
232 case DESC_EXTENSION_DESCRIPTION_END: {
233 bExtensionDescription = sal_False;
235 break;
237 case DESC_EXTENSION_DESCRIPTION_SRC: {
238 if (bExtensionDescription) {
239 sGID = OString("extdesc");
240 sResourceType = OString ( "description" );
241 sLangAttribute = OString ( "lang" );
242 sCurrentOpenTag = rToken;
243 sCurrentText = OString("");
244 Output( rToken );
245 WorkOnDesc( sCurrentOpenTag, sCurrentText );
246 sCurrentCloseTag = rToken;
247 Output( sCurrentText );
248 rToken = OString("");
249 sCurrentText = OString("");
252 break;
254 default:
255 if ( bText ) {
256 sCurrentText += rToken;
258 break;
261 if ( !bText )
263 Output( rToken );
265 return 0;
268 OString XRMResParser::GetAttribute( const OString &rToken, const OString &rAttribute )
270 OString sTmp( rToken );
271 sTmp = sTmp.replace('\t', ' ');
273 OString sSearch( " " );
274 sSearch += rAttribute;
275 sSearch += "=";
276 sal_Int32 nPos = sTmp.indexOf( sSearch );
278 if ( nPos != -1 )
280 sTmp = sTmp.copy( nPos );
281 OString sId = sTmp.getToken(1, '"');
282 return sId;
284 return OString();
288 void XRMResParser::Error( const OString &rError )
290 yyerror(( char * ) rError.getStr());
294 // class XMLResExport
297 XRMResExport::XRMResExport(
298 const OString &rOutputFile, const OString &rFilePath )
299 : XRMResParser(),
300 pResData( NULL ),
301 sPath( rFilePath )
303 pOutputStream.open( rOutputFile, PoOfstream::APP );
304 if (!pOutputStream.isOpen())
306 OString sError( "Unable to open output file: " );
307 sError += rOutputFile;
308 Error( sError );
312 XRMResExport::~XRMResExport()
314 pOutputStream.close();
315 delete pResData;
318 void XRMResExport::Output( const OString& ) {}
320 void XRMResExport::WorkOnDesc(
321 const OString &rOpenTag,
322 OString &rText )
324 OString sDescFileName(
325 sInputFileName.replaceAll("description.xml", OString()));
326 sDescFileName += GetAttribute( rOpenTag, "xlink:href" );
327 ifstream file (sDescFileName.getStr(), ios::in|ios::binary|ios::ate);
328 if (file.is_open()) {
329 int size = static_cast<int>(file.tellg());
330 char* memblock = new char [size+1];
331 file.seekg (0, ios::beg);
332 file.read (memblock, size);
333 file.close();
334 memblock[size] = '\0';
335 rText = OString(memblock);
336 delete[] memblock;
338 WorkOnText( rOpenTag, rText );
339 EndOfText( rOpenTag, rOpenTag );
342 void XRMResExport::WorkOnText(
343 const OString &rOpenTag,
344 OString &rText )
346 OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
348 if ( !pResData )
350 pResData = new ResData( GetGID() );
352 pResData->sText[sLang] = rText;
355 void XRMResExport::EndOfText(
356 const OString &,
357 const OString & )
359 if ( pResData )
361 OString sAct = pResData->sText["en-US"];
363 if( !sAct.isEmpty() )
364 common::writePoEntry(
365 "Xrmex", pOutputStream, sPath, sResourceType,
366 pResData->sGId, OString(), OString(), sAct );
368 delete pResData;
369 pResData = NULL;
373 // class XRMResMerge
376 XRMResMerge::XRMResMerge(
377 const OString &rMergeSource, const OString &rOutputFile,
378 const OString &rFilename )
379 : XRMResParser(),
380 pMergeDataFile( NULL ),
381 sFilename( rFilename ) ,
382 pResData( NULL )
384 if (!rMergeSource.isEmpty() && sLanguage.equalsIgnoreAsciiCase("ALL"))
386 pMergeDataFile = new MergeDataFile(
387 rMergeSource, sInputFileName, false);
388 aLanguages = pMergeDataFile->GetLanguages();
390 else
391 aLanguages.push_back( sLanguage );
392 pOutputStream.open(
393 rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
394 if (!pOutputStream.is_open()) {
395 OString sError( "Unable to open output file: " );
396 sError += rOutputFile;
397 Error( sError );
401 XRMResMerge::~XRMResMerge()
403 pOutputStream.close();
404 delete pMergeDataFile;
405 delete pResData;
408 void XRMResMerge::WorkOnDesc(
409 const OString &rOpenTag,
410 OString &rText )
412 WorkOnText( rOpenTag, rText);
413 if ( pMergeDataFile && pResData ) {
414 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
415 if ( pEntrys ) {
416 OString sCur;
417 OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
418 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
419 sCur = aLanguages[ n ];
420 OString sContent;
421 if ( !sCur.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) &&
422 ( pEntrys->GetText(
423 sContent, STRING_TYP_TEXT, sCur, sal_True )) &&
424 !sContent.isEmpty())
426 OString sText( sContent );
427 OString sAdditionalLine( "\n " );
428 sAdditionalLine += rOpenTag;
429 OString sSearch = sLangAttribute;
430 sSearch += "=\"";
431 OString sReplace( sSearch );
433 sSearch += GetAttribute( rOpenTag, sLangAttribute );
434 sReplace += sCur;
435 sAdditionalLine = sAdditionalLine.replaceFirst(
436 sSearch, sReplace);
438 sSearch = OString("xlink:href=\"");
439 sReplace = sSearch;
441 OString sLocDescFilename = sDescFilename;
442 sLocDescFilename = sLocDescFilename.replaceFirst(
443 "en-US", sCur);
445 sSearch += sDescFilename;
446 sReplace += sLocDescFilename;
447 sAdditionalLine = sAdditionalLine.replaceFirst(
448 sSearch, sReplace);
450 Output( sAdditionalLine );
452 sal_Int32 i = sOutputFile.lastIndexOf('/');
453 if (i == -1) {
454 std::cerr
455 << "Error: output file " << sOutputFile.getStr()
456 << " does not contain any /\n";
457 throw false; //TODO
459 OString sOutputDescFile(
460 sOutputFile.copy(0, i + 1) + sLocDescFilename);
461 ofstream file(sOutputDescFile.getStr());
462 if (file.is_open()) {
463 file << sText.getStr();
464 file.close();
465 } else {
466 std::cerr
467 << "Error: cannot write "
468 << sOutputDescFile.getStr() << '\n';
469 throw false; //TODO
475 delete pResData;
476 pResData = NULL;
479 void XRMResMerge::WorkOnText(
480 const OString &,
481 OString & )
483 if ( pMergeDataFile ) {
484 if ( !pResData ) {
485 pResData = new ResData( GetGID(), sFilename );
486 pResData->sResTyp = sResourceType;
491 void XRMResMerge::Output( const OString& rOutput )
493 if (!rOutput.isEmpty())
494 pOutputStream << rOutput.getStr();
497 void XRMResMerge::EndOfText(
498 const OString &rOpenTag,
499 const OString &rCloseTag )
502 Output( rCloseTag );
503 if ( pMergeDataFile && pResData ) {
504 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
505 if ( pEntrys ) {
506 OString sCur;
507 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
508 sCur = aLanguages[ n ];
509 OString sContent;
510 if (!sCur.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) &&
511 ( pEntrys->GetText(
512 sContent, STRING_TYP_TEXT, sCur, sal_True )) &&
513 !sContent.isEmpty() &&
514 helper::isWellFormedXML( sContent ))
516 OString sText( sContent );
517 OString sAdditionalLine( "\n " );
518 sAdditionalLine += rOpenTag;
519 OString sSearch = sLangAttribute;
520 sSearch += "=\"";
521 OString sReplace( sSearch );
523 sSearch += GetAttribute( rOpenTag, sLangAttribute );
524 sReplace += sCur;
526 sAdditionalLine = sAdditionalLine.replaceFirst(
527 sSearch, sReplace);
529 sAdditionalLine += sText;
530 sAdditionalLine += rCloseTag;
532 Output( sAdditionalLine );
537 delete pResData;
538 pResData = NULL;
541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */