blob: e9fae96845c59d1f321add056144bb31d0d01c20 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_l10ntools.hxx"
#include <stdio.h>
#include <tools/string.hxx>
#include <tools/fsys.hxx>
// local includes
#include "export.hxx"
#include "xrmmerge.hxx"
#include "utf8conv.hxx"
#include "tokens.h"
#include <iostream>
#include <vector>
using namespace std;
extern "C" { int yyerror( char * ); }
extern "C" { int YYWarning( char * ); }
// defines to parse command line
#define STATE_NON 0x0001
#define STATE_INPUT 0x0002
#define STATE_OUTPUT 0x0003
#define STATE_PRJ 0x0004
#define STATE_ROOT 0x0005
#define STATE_MERGESRC 0x0006
#define STATE_ERRORLOG 0x0007
#define STATE_UTF8 0x000B
#define STATE_LANGUAGES 0x000C
#define STATE_ISOCODE99 0x000D
// set of global variables
sal_Bool bEnableExport;
sal_Bool bMergeMode;
sal_Bool bErrorLog;
sal_Bool bUTF8;
ByteString sPrj;
ByteString sPrjRoot;
ByteString sInputFileName;
ByteString sActFileName;
ByteString sOutputFile;
ByteString sMergeSrc;
String sUsedTempFile;
XRMResParser *pParser = NULL;
extern "C" {
// the whole interface to lexer is in this extern "C" section
/*****************************************************************************/
extern char *GetOutputFile( int argc, char* argv[])
/*****************************************************************************/
{
bEnableExport = sal_False;
bMergeMode = sal_False;
bErrorLog = sal_True;
bUTF8 = sal_True;
sPrj = "";
sPrjRoot = "";
sInputFileName = "";
sActFileName = "";
Export::sLanguages = "";
sal_uInt16 nState = STATE_NON;
sal_Bool bInput = sal_False;
// parse command line
for( int i = 1; i < argc; i++ ) {
if ( ByteString( argv[ i ] ).ToUpperAscii() == "-I" ) {
nState = STATE_INPUT; // next token specifies source file
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-O" ) {
nState = STATE_OUTPUT; // next token specifies the dest file
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-P" ) {
nState = STATE_PRJ; // next token specifies the cur. project
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-R" ) {
nState = STATE_ROOT; // next token specifies path to project root
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-M" ) {
nState = STATE_MERGESRC; // next token specifies the merge database
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-E" ) {
nState = STATE_ERRORLOG;
bErrorLog = sal_False;
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-UTF8" ) {
nState = STATE_UTF8;
bUTF8 = sal_True;
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-NOUTF8" ) {
nState = STATE_UTF8;
bUTF8 = sal_False;
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-L" ) {
nState = STATE_LANGUAGES;
}
else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-ISO99" ) {
nState = STATE_ISOCODE99;
}
else {
switch ( nState ) {
case STATE_NON: {
return NULL; // no valid command line
}
case STATE_INPUT: {
sInputFileName = argv[ i ];
bInput = sal_True; // source file found
}
break;
case STATE_OUTPUT: {
sOutputFile = argv[ i ]; // the dest. file
}
break;
case STATE_PRJ: {
sPrj = ByteString( argv[ i ]);
}
break;
case STATE_ROOT: {
sPrjRoot = ByteString( argv[ i ]); // path to project root
}
break;
case STATE_MERGESRC: {
sMergeSrc = ByteString( argv[ i ]);
bMergeMode = sal_True; // activate merge mode, cause merge database found
}
break;
case STATE_LANGUAGES: {
Export::sLanguages = ByteString( argv[ i ]);
}
break;
}
}
}
if ( bInput ) {
// command line is valid
bEnableExport = sal_True;
char *pReturn = new char[ sOutputFile.Len() + 1 ];
strcpy( pReturn, sOutputFile.GetBuffer()); // #100211# - checked
return pReturn;
}
// command line is not valid
return NULL;
}
void removeTempFile(){
if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
DirEntry aTempFile( sUsedTempFile );
aTempFile.Kill();
}
}
/*****************************************************************************/
int InitXrmExport( char *pOutput , char* pFilename)
/*****************************************************************************/
{
// instanciate Export
ByteString sOutput( pOutput );
ByteString sFilename( pFilename );
Export::InitLanguages( false );
if ( bMergeMode )
pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
else if ( sOutputFile.Len()) {
pParser = new XRMResExport( sOutputFile, sPrj, sActFileName );
}
return 1;
}
/*****************************************************************************/
int EndXrmExport()
/*****************************************************************************/
{
delete pParser;
return 1;
}
extern const char* getFilename()
{
return sInputFileName.GetBuffer();
}
/*****************************************************************************/
extern FILE *GetXrmFile()
/*****************************************************************************/
{
FILE *pFile = 0;
// look for valid filename
if ( sInputFileName.Len()) {
if( Export::fileHasUTF8ByteOrderMarker( sInputFileName ) ){
DirEntry aTempFile = Export::GetTempFile();
DirEntry aSourceFile( String( sInputFileName , RTL_TEXTENCODING_ASCII_US ) );
aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
String sTempFile = aTempFile.GetFull();
Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
pFile = fopen( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ).GetBuffer(), "r" );
sUsedTempFile = sTempFile;
}else{
// able to open file?
pFile = fopen( sInputFileName.GetBuffer(), "r" );
sUsedTempFile = String::CreateFromAscii("");
}
if ( !pFile ){
fprintf( stderr, "Error: Could not open file %s\n",
sInputFileName.GetBuffer());
}
else {
// this is a valid file which can be opened, so
// create path to project root
DirEntry aEntry( String( sInputFileName, RTL_TEXTENCODING_ASCII_US ));
aEntry.ToAbs();
ByteString sFullEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
aEntry += DirEntry( sPrjRoot );
ByteString sPrjEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
// create file name, beginnig with project root
// (e.g.: source\ui\src\menue.src)
sActFileName = sFullEntry.Copy( sPrjEntry.Len() + 1 );
sActFileName.SearchAndReplaceAll( "/", "\\" );
return pFile;
}
}
// this means the file could not be opened
return NULL;
}
/*****************************************************************************/
int WorkOnTokenSet( int nTyp, char *pTokenText )
/*****************************************************************************/
{
//printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
pParser->Execute( nTyp, pTokenText );
return 1;
}
/*****************************************************************************/
int SetError()
/*****************************************************************************/
{
pParser->SetError();
return 1;
}
}
extern "C" {
/*****************************************************************************/
int GetError()
/*****************************************************************************/
{
return pParser->GetError();
}
}
//
// class XRMResParser
//
/*****************************************************************************/
XRMResParser::XRMResParser()
/*****************************************************************************/
: bError( sal_False ),
bText( sal_False )
{
aLanguages = Export::GetLanguages();
}
/*****************************************************************************/
XRMResParser::~XRMResParser()
/*****************************************************************************/
{
}
/*****************************************************************************/
int XRMResParser::Execute( int nToken, char * pToken )
/*****************************************************************************/
{
ByteString rToken( pToken );
switch ( nToken ) {
case XRM_README_START:
sLID = "";
sGID = GetAttribute( rToken, "name" );
break;
case XRM_README_END:
sGID = "";
break;
case XRM_SECTION_START:
sLID = "";
sGID += ".";
sGID += GetAttribute( rToken, "id" );
//sLocalized = "1";
//sLocalized = "X:";
sLocalized = true;
break;
case XRM_SECTION_END:
sGID = sGID.GetToken( 0, '.' );
break;
case XRM_PARAGRAPH_START:
sLID = "";
sGID += ".";
sGID += GetAttribute( rToken, "id" );
// if ( GetAttribute( rToken, "localized" ) == "false" )
// sLocalized += "0";
// sLocalized = false;
// else
// sLocalized += "1";
sLocalized = true;
break;
case XRM_PARAGRAPH_END: {
if ( sLID.Len())
EndOfText( sCurrentOpenTag, sCurrentCloseTag );
ByteString sTmp = sGID;
sGID = "";
for ( sal_uInt16 i = 0; i + 1 < sTmp.GetTokenCount( '.' ); i++ ) {
if ( sGID.Len())
sGID += ".";
sGID += sTmp.GetToken( i, '.' );
}
//sLocalized = sLocalized.Copy( 0, sLocalized.Len() - 1 );
}
break;
case XRM_TEXT_START:{
//printf("->XRM_TEXT_START\n");
ByteString sNewLID = GetAttribute( rToken, "id" );
if ( sNewLID != sLID ) {
//EndOfText( sCurrentOpenTag, sCurrentCloseTag );
sLID = sNewLID;
}
bText = sal_True;
sCurrentText = "";
sCurrentOpenTag = rToken;
Output( rToken );
//printf("<-XRM_TEXT_START\n");
}
break;
case XRM_TEXT_END: {
sCurrentCloseTag = rToken;
//printf("->XRM_TEXT_END\n");
ByteString sLang = GetAttribute( sCurrentOpenTag, "xml:lang" );
WorkOnText( sCurrentOpenTag, sCurrentText );
Output( sCurrentText );
EndOfText( sCurrentOpenTag, sCurrentCloseTag );// <---
bText = sal_False;
rToken = ByteString("");
sCurrentText = ByteString("");
//printf("<-XRM_TEXT_END");
}
break;
case XRM_LIST_START:
sLID = "";
break;
case XRM_LIST_END:
if ( sLID.Len())
EndOfText( sCurrentOpenTag, sCurrentCloseTag );
break;
default:
if ( bText ) {
sCurrentText += rToken;
}
break;
}
if ( !bText )
{
Output( rToken );
}
return 0;
}
/*****************************************************************************/
ByteString XRMResParser::GetAttribute( const ByteString &rToken, const ByteString &rAttribute )
/*****************************************************************************/
{
ByteString sTmp( rToken );
sTmp.SearchAndReplaceAll( "\t", " " );
ByteString sSearch( " " );
sSearch += rAttribute;
sSearch += "=";
sal_uInt16 nPos = sTmp.Search( sSearch );
if ( nPos != STRING_NOTFOUND ) {
sTmp = sTmp.Copy( nPos );
ByteString sId = sTmp.GetToken( 1, '\"' );
return sId;
}
return "";
}
/*****************************************************************************/
void XRMResParser::Error( const ByteString &rError )
/*****************************************************************************/
{
yyerror(( char * ) rError.GetBuffer());
}
/*****************************************************************************/
void XRMResParser::ConvertStringToDBFormat( ByteString &rString )
/*****************************************************************************/
{
ByteString sResult;
do {
sResult = rString;
rString.EraseLeadingChars( _LF );
// rString.EraseLeadingChars( ' ' );
rString.EraseLeadingChars( '\t' );
// rString.EraseTrailingChars( ' ' );
rString.EraseTrailingChars( '\t' );
} while ( sResult != rString );
rString.SearchAndReplaceAll( "\t", "\\t" );
}
/*****************************************************************************/
void XRMResParser::ConvertStringToXMLFormat( ByteString &rString )
/*****************************************************************************/
{
rString.SearchAndReplaceAll( "\\t", "\t" );
}
//
// class XRMResOutputParser
//
/*****************************************************************************/
XRMResOutputParser::XRMResOutputParser ( const ByteString &rOutputFile )
/*****************************************************************************/
{
aLanguages = Export::GetLanguages();
pOutputStream =
new SvFileStream(
String( rOutputFile, RTL_TEXTENCODING_ASCII_US ),
STREAM_STD_WRITE | STREAM_TRUNC
);
pOutputStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
if ( !pOutputStream->IsOpen()) {
ByteString sError( "Unable to open output file: " );
sError += rOutputFile;
Error( sError );
delete pOutputStream;
pOutputStream = NULL;
}
}
/*****************************************************************************/
XRMResOutputParser::~XRMResOutputParser()
/*****************************************************************************/
{
if ( pOutputStream ) {
pOutputStream->Close();
delete pOutputStream;
}
}
//
// class XMLResExport
//
/*****************************************************************************/
XRMResExport::XRMResExport(
const ByteString &rOutputFile, const ByteString &rProject,
const ByteString &rFilePath )
/*****************************************************************************/
: XRMResOutputParser( rOutputFile ),
pResData( NULL ),
sPrj( rProject ),
sPath( rFilePath )
{
aLanguages = Export::GetLanguages();
}
/*****************************************************************************/
XRMResExport::~XRMResExport()
/*****************************************************************************/
{
delete pResData;
}
void XRMResExport::Output( const ByteString& rOutput )
{
// Dummy to suppress warnings caused by poor class design
(void) rOutput;
}
/*****************************************************************************/
void XRMResExport::WorkOnText(
const ByteString &rOpenTag,
ByteString &rText
)
/*****************************************************************************/
{
ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
if ( !pResData ) {
ByteString sPlatform( "" );
pResData = new ResData( sPlatform, GetGID() );
pResData->sId = GetLID();
}
pResData->sText[ sLang ] = rText;
ConvertStringToDBFormat( pResData->sText[ sLang ] );
}
/*****************************************************************************/
void XRMResExport::EndOfText(
const ByteString &rOpenTag,
const ByteString &rCloseTag
)
/*****************************************************************************/
{
(void) rOpenTag; // FIXME
(void) rCloseTag; // FIXME
if ( pResData && pOutputStream ) {
char cSearch = 0x00;
ByteString sSearch( cSearch );
// if ( !pResData->sText[ ByteString("en-US") ].Len() )
// pResData->sText[ ByteString("en-US") ] = pResData->sText[ ByteString("de") ];
Export::FillInFallbacks( pResData );
ByteString sTimeStamp( Export::GetTimeStamp());
ByteString sCur;
for( unsigned int n = 0; n < aLanguages.size(); n++ ){
sCur = aLanguages[ n ];
ByteString sAct = pResData->sText[ sCur ];
//Export::UnquotHTML( sAct );
sAct.EraseAllChars( 0x0A );
ByteString sOutput( sPrj ); sOutput += "\t";
sOutput += sPath;
sOutput += "\t0\t";
sOutput += "readmeitem\t";
sOutput += pResData->sId;
// USE LID AS GID OR MERGE DON'T WORK
//sOutput += pResData->sGId;
sOutput += "\t";
sOutput += pResData->sId;
sOutput += "\t\t\t0\t";
sOutput += sCur;
sOutput += "\t";
sOutput += sAct; sOutput += "\t\t\t\t";
sOutput += sTimeStamp;
sOutput.SearchAndReplaceAll( sSearch, "_" );
//if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sPrj ) ) )
if( sAct.Len() > 1 )
pOutputStream->WriteLine( sOutput );
}
}
delete pResData;
pResData = NULL;
}
//
// class XRMResMerge
//
/*****************************************************************************/
XRMResMerge::XRMResMerge(
const ByteString &rMergeSource, const ByteString &rOutputFile,
ByteString &rFilename)
/*****************************************************************************/
: XRMResOutputParser( rOutputFile ),
pMergeDataFile( NULL ),
sFilename( rFilename ) ,
pResData( NULL )
{
if ( rMergeSource.Len())
pMergeDataFile = new MergeDataFile(
rMergeSource, sInputFileName , bErrorLog, RTL_TEXTENCODING_MS_1252);//, bUTF8 );
if( Export::sLanguages.EqualsIgnoreCaseAscii("ALL") ){
Export::SetLanguages( pMergeDataFile->GetLanguages() );
aLanguages = pMergeDataFile->GetLanguages();
}
else aLanguages = Export::GetLanguages();
}
/*****************************************************************************/
XRMResMerge::~XRMResMerge()
/*****************************************************************************/
{
delete pMergeDataFile;
delete pResData;
}
/*****************************************************************************/
void XRMResMerge::WorkOnText(
const ByteString &rOpenTag,
ByteString &rText
)
/*****************************************************************************/
{
ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
if ( pMergeDataFile ) {
if ( !pResData ) {
ByteString sPlatform( "" );
// pResData = new ResData( sPlatform, GetGID() , sFilename );
pResData = new ResData( sPlatform, GetLID() , sFilename );
pResData->sId = GetLID();
pResData->sResTyp = "readmeitem";
}
PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
if ( pEntrys ) {
ByteString sContent;
if ( Export::isAllowed( sLang ) &&
( pEntrys->GetText(
sContent, STRING_TYP_TEXT, sLang )) &&
( sContent != "-" ) && ( sContent.Len()))
{
rText = sContent;
ConvertStringToXMLFormat( rText );
//Export::QuotHTMLXRM( rText );
}
}
}
}
/*****************************************************************************/
void XRMResMerge::Output( const ByteString& rOutput )
/*****************************************************************************/
{
//printf("W: %s\n",rOutput.GetBuffer());
if ( pOutputStream && rOutput.Len() > 0 )
pOutputStream->Write( rOutput.GetBuffer(), rOutput.Len());
}
/*****************************************************************************/
void XRMResMerge::EndOfText(
const ByteString &rOpenTag,
const ByteString &rCloseTag
)
/*****************************************************************************/
{
Output( rCloseTag );
if ( pMergeDataFile && pResData ) {
PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
if ( pEntrys ) {
ByteString sCur;
for( unsigned int n = 0; n < aLanguages.size(); n++ ){
sCur = aLanguages[ n ];
ByteString sContent;
if ( !sCur.EqualsIgnoreCaseAscii("en-US") &&
( pEntrys->GetText(
sContent, STRING_TYP_TEXT, sCur, sal_True )) &&
( sContent != "-" ) && ( sContent.Len()))
{
ByteString sText( sContent );
//Export::QuotHTMLXRM( sText );
ByteString sAdditionalLine( "\t" );
sAdditionalLine += rOpenTag;
ByteString sSearch = "xml:lang=\"";
ByteString sReplace( sSearch );
sSearch += GetAttribute( rOpenTag, "xml:lang" );
sReplace += sCur;
sAdditionalLine.SearchAndReplace( sSearch, sReplace );
sAdditionalLine += sText;
sAdditionalLine += rCloseTag;
sAdditionalLine += "\n";
for ( sal_uInt16 i = 0; i + 1 < GetGID().GetTokenCount( '.' ); i++ )
sAdditionalLine += "\t";
Output( sAdditionalLine );
}
}
}
}
delete pResData;
pResData = NULL;
}