1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xrmmerge.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_transex3.hxx"
34 #include <tools/string.hxx>
35 #include <tools/fsys.hxx>
39 #include "xrmmerge.hxx"
40 #include "utf8conv.hxx"
47 extern "C" { int yyerror( char * ); }
48 extern "C" { int YYWarning( char * ); }
50 // defines to parse command line
51 #define STATE_NON 0x0001
52 #define STATE_INPUT 0x0002
53 #define STATE_OUTPUT 0x0003
54 #define STATE_PRJ 0x0004
55 #define STATE_ROOT 0x0005
56 #define STATE_MERGESRC 0x0006
57 #define STATE_ERRORLOG 0x0007
58 #define STATE_UTF8 0x000B
59 #define STATE_LANGUAGES 0x000C
60 #define STATE_ISOCODE99 0x000D
62 // set of global variables
70 ByteString sInputFileName
;
71 ByteString sActFileName
;
72 ByteString sOutputFile
;
75 XRMResParser
*pParser
= NULL
;
78 // the whole interface to lexer is in this extern "C" section
80 /*****************************************************************************/
81 extern char *GetOutputFile( int argc
, char* argv
[])
82 /*****************************************************************************/
84 bEnableExport
= FALSE
;
92 Export::sLanguages
= "";
94 USHORT nState
= STATE_NON
;
98 for( int i
= 1; i
< argc
; i
++ ) {
99 if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-I" ) {
100 nState
= STATE_INPUT
; // next token specifies source file
102 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-O" ) {
103 nState
= STATE_OUTPUT
; // next token specifies the dest file
105 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-P" ) {
106 nState
= STATE_PRJ
; // next token specifies the cur. project
108 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-R" ) {
109 nState
= STATE_ROOT
; // next token specifies path to project root
111 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-M" ) {
112 nState
= STATE_MERGESRC
; // next token specifies the merge database
114 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-QQ" ) {
117 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-E" ) {
118 nState
= STATE_ERRORLOG
;
121 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-UTF8" ) {
125 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-NOUTF8" ) {
129 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-L" ) {
130 nState
= STATE_LANGUAGES
;
132 else if ( ByteString( argv
[ i
] ).ToUpperAscii() == "-ISO99" ) {
133 nState
= STATE_ISOCODE99
;
138 return NULL
; // no valid command line
141 sInputFileName
= argv
[ i
];
142 bInput
= TRUE
; // source file found
146 sOutputFile
= argv
[ i
]; // the dest. file
150 sPrj
= ByteString( argv
[ i
]);
154 sPrjRoot
= ByteString( argv
[ i
]); // path to project root
157 case STATE_MERGESRC
: {
158 sMergeSrc
= ByteString( argv
[ i
]);
159 bMergeMode
= TRUE
; // activate merge mode, cause merge database found
162 case STATE_LANGUAGES
: {
163 Export::sLanguages
= ByteString( argv
[ i
]);
166 case STATE_ISOCODE99
: {
167 Export::sIsoCode99
= ByteString( argv
[ i
]);
175 // command line is valid
176 bEnableExport
= TRUE
;
177 char *pReturn
= new char[ sOutputFile
.Len() + 1 ];
178 strcpy( pReturn
, sOutputFile
.GetBuffer()); // #100211# - checked
182 // command line is not valid
185 void removeTempFile(){
186 if( !sUsedTempFile
.EqualsIgnoreCaseAscii( "" ) ){
187 DirEntry
aTempFile( sUsedTempFile
);
191 /*****************************************************************************/
192 int InitXrmExport( char *pOutput
, char* pFilename
)
193 /*****************************************************************************/
195 // instanciate Export
196 ByteString
sOutput( pOutput
);
197 ByteString
sFilename( pFilename
);
198 Export::InitLanguages( false );
201 pParser
= new XRMResMerge( sMergeSrc
, sOutputFile
, sFilename
);
202 else if ( sOutputFile
.Len()) {
203 pParser
= new XRMResExport( sOutputFile
, sPrj
, sActFileName
);
210 if( bQuiet
) return 1;
213 /*****************************************************************************/
215 /*****************************************************************************/
220 extern const char* getFilename()
222 return sInputFileName
.GetBuffer();
224 /*****************************************************************************/
225 extern FILE *GetXrmFile()
226 /*****************************************************************************/
229 // look for valid filename
230 if ( sInputFileName
.Len()) {
231 if( Export::fileHasUTF8ByteOrderMarker( sInputFileName
) ){
232 DirEntry aTempFile
= Export::GetTempFile();
233 DirEntry
aSourceFile( String( sInputFileName
, RTL_TEXTENCODING_ASCII_US
) );
234 aSourceFile
.CopyTo( aTempFile
, FSYS_ACTION_COPYFILE
);
235 String sTempFile
= aTempFile
.GetFull();
236 Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile
, RTL_TEXTENCODING_ASCII_US
) );
237 pFile
= fopen( ByteString( sTempFile
, RTL_TEXTENCODING_ASCII_US
).GetBuffer(), "r" );
238 sUsedTempFile
= sTempFile
;
240 // able to open file?
241 pFile
= fopen( sInputFileName
.GetBuffer(), "r" );
242 sUsedTempFile
= String::CreateFromAscii("");
245 fprintf( stderr
, "Error: Could not open file %s\n",
246 sInputFileName
.GetBuffer());
249 // this is a valid file which can be opened, so
250 // create path to project root
251 DirEntry
aEntry( String( sInputFileName
, RTL_TEXTENCODING_ASCII_US
));
253 ByteString
sFullEntry( aEntry
.GetFull(), RTL_TEXTENCODING_ASCII_US
);
254 aEntry
+= DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US
));
255 aEntry
+= DirEntry( sPrjRoot
);
256 ByteString
sPrjEntry( aEntry
.GetFull(), RTL_TEXTENCODING_ASCII_US
);
258 // create file name, beginnig with project root
259 // (e.g.: source\ui\src\menue.src)
260 sActFileName
= sFullEntry
.Copy( sPrjEntry
.Len() + 1 );
263 fprintf( stdout
, "\nProcessing File %s ...\n", sInputFileName
.GetBuffer());
265 sActFileName
.SearchAndReplaceAll( "/", "\\" );
270 // this means the file could not be opened
274 /*****************************************************************************/
275 int WorkOnTokenSet( int nTyp
, char *pTokenText
)
276 /*****************************************************************************/
278 // printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
279 pParser
->Execute( nTyp
, pTokenText
);
284 /*****************************************************************************/
286 /*****************************************************************************/
294 /*****************************************************************************/
296 /*****************************************************************************/
298 return pParser
->GetError();
303 // class XRMResParser
307 /*****************************************************************************/
308 XRMResParser::XRMResParser()
309 /*****************************************************************************/
313 aLanguages
= Export::GetLanguages();
316 /*****************************************************************************/
317 XRMResParser::~XRMResParser()
318 /*****************************************************************************/
322 /*****************************************************************************/
323 int XRMResParser::Execute( int nToken
, char * pToken
)
324 /*****************************************************************************/
326 ByteString
rToken( pToken
);
329 case XRM_README_START
:
331 sGID
= GetAttribute( rToken
, "name" );
338 case XRM_SECTION_START
:
341 sGID
+= GetAttribute( rToken
, "id" );
348 case XRM_SECTION_END
:
349 sGID
= sGID
.GetToken( 0, '.' );
352 case XRM_PARAGRAPH_START
:
355 sGID
+= GetAttribute( rToken
, "id" );
356 if ( GetAttribute( rToken
, "localized" ) == "false" )
357 // sLocalized += "0";
360 // sLocalized += "1";
364 case XRM_PARAGRAPH_END
: {
366 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
367 ByteString sTmp
= sGID
;
369 for ( USHORT i
= 0; i
+ 1 < sTmp
.GetTokenCount( '.' ); i
++ ) {
372 sGID
+= sTmp
.GetToken( i
, '.' );
374 //sLocalized = sLocalized.Copy( 0, sLocalized.Len() - 1 );
379 // if ( sLocalized.GetChar( sLocalized.Len() - 1 ) == '1' ) {
382 ByteString sNewLID
= GetAttribute( rToken
, "id" );
383 if ( sNewLID
!= sLID
) {
384 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
389 sCurrentOpenTag
= rToken
;
395 // if ( sLocalized.GetChar( sLocalized.Len() - 1 ) == '1' ) {
397 sCurrentCloseTag
= rToken
;
399 ByteString sLang
= GetAttribute( sCurrentOpenTag
, "xml:lang" );
400 if( sLang
.EqualsIgnoreCaseAscii("de") ){
402 while ( sCurrentText
.Len() != nLen
)
404 nLen
= sCurrentText
.Len();
405 sCurrentText
.SearchAndReplaceAll( "\n\t", "\n" );
406 sCurrentText
.SearchAndReplaceAll( "\n ", "\n" );
408 sCurrentText
.SearchAndReplaceAll( "\n", " " );
409 sCurrentCloseTag
= rToken
;
411 WorkOnText( sCurrentOpenTag
, sCurrentText
);
412 Output( sCurrentText
);
414 //fprintf( stdout, "%s %s\n", sGID.GetBuffer(), sLID.GetBuffer());
415 //fprintf( stdout, "%s\n\n", sCurrentText.GetBuffer());
428 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
433 sCurrentText
+= rToken
;
444 /*****************************************************************************/
445 ByteString
XRMResParser::GetAttribute( const ByteString
&rToken
, const ByteString
&rAttribute
)
446 /*****************************************************************************/
448 ByteString
sTmp( rToken
);
449 sTmp
.SearchAndReplaceAll( "\t", " " );
451 ByteString
sSearch( " " );
452 sSearch
+= rAttribute
;
454 USHORT nPos
= sTmp
.Search( sSearch
);
456 if ( nPos
!= STRING_NOTFOUND
) {
457 sTmp
= sTmp
.Copy( nPos
);
458 ByteString sId
= sTmp
.GetToken( 1, '\"' );
465 /*****************************************************************************/
466 void XRMResParser::Error( const ByteString
&rError
)
467 /*****************************************************************************/
469 yyerror(( char * ) rError
.GetBuffer());
472 /*****************************************************************************/
473 void XRMResParser::ConvertStringToDBFormat( ByteString
&rString
)
474 /*****************************************************************************/
479 rString
.EraseLeadingChars( _LF
);
480 // rString.EraseLeadingChars( ' ' );
481 rString
.EraseLeadingChars( '\t' );
482 // rString.EraseTrailingChars( ' ' );
483 rString
.EraseTrailingChars( '\t' );
484 } while ( sResult
!= rString
);
486 rString
.SearchAndReplaceAll( "\t", "\\t" );
489 /*****************************************************************************/
490 void XRMResParser::ConvertStringToXMLFormat( ByteString
&rString
)
491 /*****************************************************************************/
493 rString
.SearchAndReplaceAll( "\\t", "\t" );
499 // class XRMResOutputParser
502 /*****************************************************************************/
503 XRMResOutputParser::XRMResOutputParser ( const ByteString
&rOutputFile
)
504 /*****************************************************************************/
506 aLanguages
= Export::GetLanguages();
509 String( rOutputFile
, RTL_TEXTENCODING_ASCII_US
),
510 STREAM_STD_WRITE
| STREAM_TRUNC
512 pOutputStream
->SetStreamCharSet( RTL_TEXTENCODING_UTF8
);
513 if ( !pOutputStream
->IsOpen()) {
514 ByteString
sError( "Unable to open output file: " );
515 sError
+= rOutputFile
;
517 delete pOutputStream
;
518 pOutputStream
= NULL
;
522 /*****************************************************************************/
523 XRMResOutputParser::~XRMResOutputParser()
524 /*****************************************************************************/
526 if ( pOutputStream
) {
527 pOutputStream
->Close();
528 delete pOutputStream
;
533 // class XMLResExport
536 /*****************************************************************************/
537 XRMResExport::XRMResExport(
538 const ByteString
&rOutputFile
, const ByteString
&rProject
,
539 const ByteString
&rFilePath
)
540 /*****************************************************************************/
541 : XRMResOutputParser( rOutputFile
),
546 aLanguages
= Export::GetLanguages();
549 /*****************************************************************************/
550 XRMResExport::~XRMResExport()
551 /*****************************************************************************/
556 void XRMResExport::Output( const ByteString
& rOutput
)
558 // Dummy to suppress warnings caused by poor class design
562 /*****************************************************************************/
563 void XRMResExport::WorkOnText(
564 const ByteString
&rOpenTag
,
567 /*****************************************************************************/
569 ByteString
sLang( GetAttribute( rOpenTag
, "xml:lang" ));
572 ByteString
sPlatform( "" );
573 pResData
= new ResData( sPlatform
, GetGID() );
574 pResData
->sId
= GetLID();
577 pResData
->sText
[ sLang
] = rText
;
578 ConvertStringToDBFormat( pResData
->sText
[ sLang
] );
581 /*****************************************************************************/
582 void XRMResExport::EndOfText(
583 const ByteString
&rOpenTag
,
584 const ByteString
&rCloseTag
586 /*****************************************************************************/
589 (void) rOpenTag
; // FIXME
590 (void) rCloseTag
; // FIXME
592 if ( pResData
&& pOutputStream
) {
595 ByteString
sSearch( cSearch
);
597 // if ( !pResData->sText[ ByteString("en-US") ].Len() )
598 // pResData->sText[ ByteString("en-US") ] = pResData->sText[ ByteString("de") ];
600 Export::FillInFallbacks( pResData
);
602 ByteString
sTimeStamp( Export::GetTimeStamp());
604 for( unsigned int n
= 0; n
< aLanguages
.size(); n
++ ){
605 sCur
= aLanguages
[ n
];
607 ByteString sAct
= pResData
->sText
[ sCur
];
608 Export::UnquotHTML( sAct
);
609 sAct
.EraseAllChars( 0x0A );
611 ByteString
sOutput( sPrj
); sOutput
+= "\t";
614 sOutput
+= "readmeitem\t";
615 sOutput
+= pResData
->sGId
; sOutput
+= "\t";
616 sOutput
+= pResData
->sId
; sOutput
+= "\t\t\t0\t";
620 sOutput
+= sAct
; sOutput
+= "\t\t\t\t";
621 sOutput
+= sTimeStamp
;
623 sOutput
.SearchAndReplaceAll( sSearch
, "_" );
624 //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sPrj ) ) )
625 pOutputStream
->WriteLine( sOutput
);
636 /*****************************************************************************/
637 XRMResMerge::XRMResMerge(
638 const ByteString
&rMergeSource
, const ByteString
&rOutputFile
,
639 ByteString
&rFilename
)
640 /*****************************************************************************/
641 : XRMResOutputParser( rOutputFile
),
642 pMergeDataFile( NULL
),
643 sFilename( rFilename
) ,
646 if ( rMergeSource
.Len())
647 pMergeDataFile
= new MergeDataFile(
648 rMergeSource
, sInputFileName
, bErrorLog
, RTL_TEXTENCODING_MS_1252
);//, bUTF8 );
649 if( Export::sLanguages
.EqualsIgnoreCaseAscii("ALL") ){
650 Export::SetLanguages( pMergeDataFile
->GetLanguages() );
651 aLanguages
= pMergeDataFile
->GetLanguages();
653 else aLanguages
= Export::GetLanguages();
656 /*****************************************************************************/
657 XRMResMerge::~XRMResMerge()
658 /*****************************************************************************/
660 delete pMergeDataFile
;
664 /*****************************************************************************/
665 void XRMResMerge::WorkOnText(
666 const ByteString
&rOpenTag
,
669 /*****************************************************************************/
671 ByteString
sLang( GetAttribute( rOpenTag
, "xml:lang" ));
673 if ( pMergeDataFile
) {
675 ByteString
sPlatform( "" );
676 pResData
= new ResData( sPlatform
, GetGID() , sFilename
);
677 pResData
->sId
= GetLID();
678 pResData
->sResTyp
= "readmeitem";
681 PFormEntrys
*pEntrys
= pMergeDataFile
->GetPFormEntrys( pResData
);
684 if ( Export::isAllowed( sLang
) &&
686 sContent
, STRING_TYP_TEXT
, sLang
)) &&
687 ( sContent
!= "-" ) && ( sContent
.Len()))
691 ConvertStringToXMLFormat( rText
);
692 Export::QuotHTMLXRM( rText
);
698 /*****************************************************************************/
699 void XRMResMerge::Output( const ByteString
& rOutput
)
700 /*****************************************************************************/
703 pOutputStream
->Write( rOutput
.GetBuffer(), rOutput
.Len());
706 /*****************************************************************************/
707 void XRMResMerge::EndOfText(
708 const ByteString
&rOpenTag
,
709 const ByteString
&rCloseTag
711 /*****************************************************************************/
713 if ( pMergeDataFile
&& pResData
) {
714 PFormEntrys
*pEntrys
= pMergeDataFile
->GetPFormEntrys( pResData
);
717 for( unsigned int n
= 0; n
< aLanguages
.size(); n
++ ){
718 sCur
= aLanguages
[ n
];
720 //<<<<<<< xrmmerge.cxx
721 if ( !sCur
.EqualsIgnoreCaseAscii("en-US") &&
722 // ( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && Export::isMergingGermanAllowed( sPrj ) )) &&
724 // if ( Export::isAllowed( sCur ) &&
727 sContent
, STRING_TYP_TEXT
, sCur
, TRUE
)) &&
728 ( sContent
!= "-" ) && ( sContent
.Len()))
730 ByteString
sText( sContent
);
731 Export::QuotHTMLXRM( sText
);
733 ByteString
sAdditionalLine( "\t" );
734 sAdditionalLine
+= rOpenTag
;
735 ByteString sSearch
= "xml:lang=\"";
736 ByteString
sReplace( sSearch
);
738 sSearch
+= GetAttribute( rOpenTag
, "xml:lang" );
741 sAdditionalLine
.SearchAndReplace( sSearch
, sReplace
);
743 sAdditionalLine
+= sText
;
744 sAdditionalLine
+= rCloseTag
;
745 sAdditionalLine
+= "\n";
747 for ( USHORT i
= 0; i
+ 1 < GetGID().GetTokenCount( '.' ); i
++ )
748 sAdditionalLine
+= "\t";
750 Output( sAdditionalLine
);