1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_l10ntools.hxx"
26 #include <stdio.h>
27 #include <tools/string.hxx>
28 #include <tools/fsys.hxx>
29
30 // local includes
31 #include "export.hxx"
32 #include "xrmmerge.hxx"
33 #include "utf8conv.hxx"
34 #include "tokens.h"
35 #include <iostream>
36 #include <vector>
37
38 using namespace std;
39
40 extern "C" { int yyerror( char * ); }
41 extern "C" { int YYWarning( char * ); }
42
43 // defines to parse command line
44 #define STATE_NON 0x0001
45 #define STATE_INPUT 0x0002
46 #define STATE_OUTPUT 0x0003
47 #define STATE_PRJ 0x0004
48 #define STATE_ROOT 0x0005
49 #define STATE_MERGESRC 0x0006
50 #define STATE_ERRORLOG 0x0007
51 #define STATE_UTF8 0x000B
52 #define STATE_LANGUAGES 0x000C
53 #define STATE_ISOCODE99 0x000D
54
55 // set of global variables
56 sal_Bool bEnableExport;
57 sal_Bool bMergeMode;
58 sal_Bool bErrorLog;
59 sal_Bool bUTF8;
60 ByteString sPrj;
61 ByteString sPrjRoot;
62 ByteString sInputFileName;
63 ByteString sActFileName;
64 ByteString sOutputFile;
65 ByteString sMergeSrc;
66 String sUsedTempFile;
67 XRMResParser *pParser = NULL;
68
69 extern "C" {
70 // the whole interface to lexer is in this extern "C" section
71
72 /*****************************************************************************/
GetOutputFile(int argc,char * argv[])73 extern char *GetOutputFile( int argc, char* argv[])
74 /*****************************************************************************/
75 {
76 bEnableExport = sal_False;
77 bMergeMode = sal_False;
78 bErrorLog = sal_True;
79 bUTF8 = sal_True;
80 sPrj = "";
81 sPrjRoot = "";
82 sInputFileName = "";
83 sActFileName = "";
84 Export::sLanguages = "";
85 sal_uInt16 nState = STATE_NON;
86 sal_Bool bInput = sal_False;
87
88 // parse command line
89 for( int i = 1; i < argc; i++ ) {
90 if ( ByteString( argv[ i ] ).ToUpperAscii() == "-I" ) {
91 nState = STATE_INPUT; // next token specifies source file
92 }
93 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-O" ) {
94 nState = STATE_OUTPUT; // next token specifies the dest file
95 }
96 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-P" ) {
97 nState = STATE_PRJ; // next token specifies the cur. project
98 }
99 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-R" ) {
100 nState = STATE_ROOT; // next token specifies path to project root
101 }
102 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-M" ) {
103 nState = STATE_MERGESRC; // next token specifies the merge database
104 }
105 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-E" ) {
106 nState = STATE_ERRORLOG;
107 bErrorLog = sal_False;
108 }
109 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-UTF8" ) {
110 nState = STATE_UTF8;
111 bUTF8 = sal_True;
112 }
113 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-NOUTF8" ) {
114 nState = STATE_UTF8;
115 bUTF8 = sal_False;
116 }
117 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-L" ) {
118 nState = STATE_LANGUAGES;
119 }
120 else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-ISO99" ) {
121 nState = STATE_ISOCODE99;
122 }
123 else {
124 switch ( nState ) {
125 case STATE_NON: {
126 return NULL; // no valid command line
127 }
128 case STATE_INPUT: {
129 sInputFileName = argv[ i ];
130 bInput = sal_True; // source file found
131 }
132 break;
133 case STATE_OUTPUT: {
134 sOutputFile = argv[ i ]; // the dest. file
135 }
136 break;
137 case STATE_PRJ: {
138 sPrj = ByteString( argv[ i ]);
139 }
140 break;
141 case STATE_ROOT: {
142 sPrjRoot = ByteString( argv[ i ]); // path to project root
143 }
144 break;
145 case STATE_MERGESRC: {
146 sMergeSrc = ByteString( argv[ i ]);
147 bMergeMode = sal_True; // activate merge mode, cause merge database found
148 }
149 break;
150 case STATE_LANGUAGES: {
151 Export::sLanguages = ByteString( argv[ i ]);
152 }
153 break;
154 }
155 }
156 }
157
158 if ( bInput ) {
159 // command line is valid
160 bEnableExport = sal_True;
161 char *pReturn = new char[ sOutputFile.Len() + 1 ];
162 strcpy( pReturn, sOutputFile.GetBuffer()); // #100211# - checked
163 return pReturn;
164 }
165
166 // command line is not valid
167 return NULL;
168 }
removeTempFile()169 void removeTempFile(){
170 if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
171 DirEntry aTempFile( sUsedTempFile );
172 aTempFile.Kill();
173 }
174 }
175 /*****************************************************************************/
InitXrmExport(char * pOutput,char * pFilename)176 int InitXrmExport( char *pOutput , char* pFilename)
177 /*****************************************************************************/
178 {
179 // instanciate Export
180 ByteString sOutput( pOutput );
181 ByteString sFilename( pFilename );
182 Export::InitLanguages( false );
183
184 if ( bMergeMode )
185 pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
186 else if ( sOutputFile.Len()) {
187 pParser = new XRMResExport( sOutputFile, sPrj, sActFileName );
188 }
189
190 return 1;
191 }
192
193 /*****************************************************************************/
EndXrmExport()194 int EndXrmExport()
195 /*****************************************************************************/
196 {
197 delete pParser;
198 return 1;
199 }
getFilename()200 extern const char* getFilename()
201 {
202 return sInputFileName.GetBuffer();
203 }
204 /*****************************************************************************/
GetXrmFile()205 extern FILE *GetXrmFile()
206 /*****************************************************************************/
207 {
208 FILE *pFile = 0;
209 // look for valid filename
210 if ( sInputFileName.Len()) {
211 if( Export::fileHasUTF8ByteOrderMarker( sInputFileName ) ){
212 DirEntry aTempFile = Export::GetTempFile();
213 DirEntry aSourceFile( String( sInputFileName , RTL_TEXTENCODING_ASCII_US ) );
214 aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
215 String sTempFile = aTempFile.GetFull();
216 Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
217 pFile = fopen( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ).GetBuffer(), "r" );
218 sUsedTempFile = sTempFile;
219 }else{
220 // able to open file?
221 pFile = fopen( sInputFileName.GetBuffer(), "r" );
222 sUsedTempFile = String::CreateFromAscii("");
223 }
224 if ( !pFile ){
225 fprintf( stderr, "Error: Could not open file %s\n",
226 sInputFileName.GetBuffer());
227 }
228 else {
229 // this is a valid file which can be opened, so
230 // create path to project root
231 DirEntry aEntry( String( sInputFileName, RTL_TEXTENCODING_ASCII_US ));
232 aEntry.ToAbs();
233 ByteString sFullEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
234 aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
235 aEntry += DirEntry( sPrjRoot );
236 ByteString sPrjEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
237
238 // create file name, beginning with project root
239 // (e.g.: source\ui\src\menue.src)
240 sActFileName = sFullEntry.Copy( sPrjEntry.Len() + 1 );
241
242
243 sActFileName.SearchAndReplaceAll( "/", "\\" );
244
245 return pFile;
246 }
247 }
248 // this means the file could not be opened
249 return NULL;
250 }
251
252 /*****************************************************************************/
WorkOnTokenSet(int nTyp,char * pTokenText)253 int WorkOnTokenSet( int nTyp, char *pTokenText )
254 /*****************************************************************************/
255 {
256 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
257 pParser->Execute( nTyp, pTokenText );
258
259 return 1;
260 }
261
262 /*****************************************************************************/
SetError()263 int SetError()
264 /*****************************************************************************/
265 {
266 pParser->SetError();
267 return 1;
268 }
269 }
270
271 extern "C" {
272 /*****************************************************************************/
GetError()273 int GetError()
274 /*****************************************************************************/
275 {
276 return pParser->GetError();
277 }
278 }
279
280 //
281 // class XRMResParser
282 //
283
284
285 /*****************************************************************************/
XRMResParser()286 XRMResParser::XRMResParser()
287 /*****************************************************************************/
288 : bError( sal_False ),
289 bText( sal_False )
290 {
291 aLanguages = Export::GetLanguages();
292 }
293
294 /*****************************************************************************/
~XRMResParser()295 XRMResParser::~XRMResParser()
296 /*****************************************************************************/
297 {
298 }
299
300 /*****************************************************************************/
Execute(int nToken,char * pToken)301 int XRMResParser::Execute( int nToken, char * pToken )
302 /*****************************************************************************/
303 {
304 ByteString rToken( pToken );
305
306 switch ( nToken ) {
307 case XRM_README_START:
308 sLID = "";
309 sGID = GetAttribute( rToken, "name" );
310 break;
311
312 case XRM_README_END:
313 sGID = "";
314 break;
315
316 case XRM_SECTION_START:
317 sLID = "";
318 sGID += ".";
319 sGID += GetAttribute( rToken, "id" );
320 //sLocalized = "1";
321
322 //sLocalized = "X:";
323 sLocalized = true;
324 break;
325
326 case XRM_SECTION_END:
327 sGID = sGID.GetToken( 0, '.' );
328 break;
329
330 case XRM_PARAGRAPH_START:
331 sLID = "";
332 sGID += ".";
333 sGID += GetAttribute( rToken, "id" );
334 // if ( GetAttribute( rToken, "localized" ) == "false" )
335 // sLocalized += "0";
336 // sLocalized = false;
337 // else
338 // sLocalized += "1";
339 sLocalized = true;
340 break;
341
342 case XRM_PARAGRAPH_END: {
343 if ( sLID.Len())
344 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
345 ByteString sTmp = sGID;
346 sGID = "";
347 for ( sal_uInt16 i = 0; i + 1 < sTmp.GetTokenCount( '.' ); i++ ) {
348 if ( sGID.Len())
349 sGID += ".";
350 sGID += sTmp.GetToken( i, '.' );
351 }
352 //sLocalized = sLocalized.Copy( 0, sLocalized.Len() - 1 );
353 }
354 break;
355
356 case XRM_TEXT_START:{
357 //printf("->XRM_TEXT_START\n");
358 ByteString sNewLID = GetAttribute( rToken, "id" );
359 if ( sNewLID != sLID ) {
360 //EndOfText( sCurrentOpenTag, sCurrentCloseTag );
361 sLID = sNewLID;
362 }
363 bText = sal_True;
364 sCurrentText = "";
365 sCurrentOpenTag = rToken;
366 Output( rToken );
367 //printf("<-XRM_TEXT_START\n");
368 }
369 break;
370
371 case XRM_TEXT_END: {
372 sCurrentCloseTag = rToken;
373 //printf("->XRM_TEXT_END\n");
374 ByteString sLang = GetAttribute( sCurrentOpenTag, "xml:lang" );
375 WorkOnText( sCurrentOpenTag, sCurrentText );
376 Output( sCurrentText );
377 EndOfText( sCurrentOpenTag, sCurrentCloseTag );// <---
378 bText = sal_False;
379 rToken = ByteString("");
380 sCurrentText = ByteString("");
381 //printf("<-XRM_TEXT_END");
382 }
383 break;
384
385 case XRM_LIST_START:
386 sLID = "";
387 break;
388
389 case XRM_LIST_END:
390 if ( sLID.Len())
391 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
392 break;
393
394 default:
395 if ( bText ) {
396 sCurrentText += rToken;
397 }
398 break;
399 }
400
401 if ( !bText )
402 {
403 Output( rToken );
404 }
405 return 0;
406 }
407
408 /*****************************************************************************/
GetAttribute(const ByteString & rToken,const ByteString & rAttribute)409 ByteString XRMResParser::GetAttribute( const ByteString &rToken, const ByteString &rAttribute )
410 /*****************************************************************************/
411 {
412 ByteString sTmp( rToken );
413 sTmp.SearchAndReplaceAll( "\t", " " );
414
415 ByteString sSearch( " " );
416 sSearch += rAttribute;
417 sSearch += "=";
418 sal_uInt16 nPos = sTmp.Search( sSearch );
419
420 if ( nPos != STRING_NOTFOUND ) {
421 sTmp = sTmp.Copy( nPos );
422 ByteString sId = sTmp.GetToken( 1, '\"' );
423 return sId;
424 }
425 return "";
426 }
427
428
429 /*****************************************************************************/
Error(const ByteString & rError)430 void XRMResParser::Error( const ByteString &rError )
431 /*****************************************************************************/
432 {
433 yyerror(( char * ) rError.GetBuffer());
434 }
435
436 /*****************************************************************************/
ConvertStringToDBFormat(ByteString & rString)437 void XRMResParser::ConvertStringToDBFormat( ByteString &rString )
438 /*****************************************************************************/
439 {
440 ByteString sResult;
441 do {
442 sResult = rString;
443 rString.EraseLeadingChars( _LF );
444 // rString.EraseLeadingChars( ' ' );
445 rString.EraseLeadingChars( '\t' );
446 // rString.EraseTrailingChars( ' ' );
447 rString.EraseTrailingChars( '\t' );
448 } while ( sResult != rString );
449
450 rString.SearchAndReplaceAll( "\t", "\\t" );
451 }
452
453 /*****************************************************************************/
ConvertStringToXMLFormat(ByteString & rString)454 void XRMResParser::ConvertStringToXMLFormat( ByteString &rString )
455 /*****************************************************************************/
456 {
457 rString.SearchAndReplaceAll( "\\t", "\t" );
458 }
459
460
461
462 //
463 // class XRMResOutputParser
464 //
465
466 /*****************************************************************************/
XRMResOutputParser(const ByteString & rOutputFile)467 XRMResOutputParser::XRMResOutputParser ( const ByteString &rOutputFile )
468 /*****************************************************************************/
469 {
470 aLanguages = Export::GetLanguages();
471 pOutputStream =
472 new SvFileStream(
473 String( rOutputFile, RTL_TEXTENCODING_ASCII_US ),
474 STREAM_STD_WRITE | STREAM_TRUNC
475 );
476 pOutputStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
477 if ( !pOutputStream->IsOpen()) {
478 ByteString sError( "Unable to open output file: " );
479 sError += rOutputFile;
480 Error( sError );
481 delete pOutputStream;
482 pOutputStream = NULL;
483 }
484 }
485
486 /*****************************************************************************/
~XRMResOutputParser()487 XRMResOutputParser::~XRMResOutputParser()
488 /*****************************************************************************/
489 {
490 if ( pOutputStream ) {
491 pOutputStream->Close();
492 delete pOutputStream;
493 }
494 }
495
496 //
497 // class XMLResExport
498 //
499
500 /*****************************************************************************/
XRMResExport(const ByteString & rOutputFile,const ByteString & rProject,const ByteString & rFilePath)501 XRMResExport::XRMResExport(
502 const ByteString &rOutputFile, const ByteString &rProject,
503 const ByteString &rFilePath )
504 /*****************************************************************************/
505 : XRMResOutputParser( rOutputFile ),
506 pResData( NULL ),
507 sPrj( rProject ),
508 sPath( rFilePath )
509 {
510 aLanguages = Export::GetLanguages();
511 }
512
513 /*****************************************************************************/
~XRMResExport()514 XRMResExport::~XRMResExport()
515 /*****************************************************************************/
516 {
517 delete pResData;
518 }
519
Output(const ByteString & rOutput)520 void XRMResExport::Output( const ByteString& rOutput )
521 {
522 // Dummy to suppress warnings caused by poor class design
523 (void) rOutput;
524 }
525
526 /*****************************************************************************/
WorkOnText(const ByteString & rOpenTag,ByteString & rText)527 void XRMResExport::WorkOnText(
528 const ByteString &rOpenTag,
529 ByteString &rText
530 )
531 /*****************************************************************************/
532 {
533 ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
534
535 if ( !pResData ) {
536 ByteString sPlatform( "" );
537 pResData = new ResData( sPlatform, GetGID() );
538 pResData->sId = GetLID();
539 }
540
541 pResData->sText[ sLang ] = rText;
542 ConvertStringToDBFormat( pResData->sText[ sLang ] );
543 }
544
545 /*****************************************************************************/
EndOfText(const ByteString & rOpenTag,const ByteString & rCloseTag)546 void XRMResExport::EndOfText(
547 const ByteString &rOpenTag,
548 const ByteString &rCloseTag
549 )
550 /*****************************************************************************/
551 {
552
553 (void) rOpenTag; // FIXME
554 (void) rCloseTag; // FIXME
555
556 if ( pResData && pOutputStream ) {
557
558 char cSearch = 0x00;
559 ByteString sSearch( cSearch );
560
561 // if ( !pResData->sText[ ByteString("en-US") ].Len() )
562 // pResData->sText[ ByteString("en-US") ] = pResData->sText[ ByteString("de") ];
563
564 Export::FillInFallbacks( pResData );
565
566 ByteString sTimeStamp( Export::GetTimeStamp());
567 ByteString sCur;
568 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
569 sCur = aLanguages[ n ];
570
571 ByteString sAct = pResData->sText[ sCur ];
572 //Export::UnquotHTML( sAct );
573 sAct.EraseAllChars( 0x0A );
574
575 ByteString sOutput( sPrj ); sOutput += "\t";
576 sOutput += sPath;
577 sOutput += "\t0\t";
578 sOutput += "readmeitem\t";
579 sOutput += pResData->sId;
580 // USE LID AS GID OR MERGE DON'T WORK
581 //sOutput += pResData->sGId;
582 sOutput += "\t";
583 sOutput += pResData->sId;
584 sOutput += "\t\t\t0\t";
585 sOutput += sCur;
586 sOutput += "\t";
587
588 sOutput += sAct; sOutput += "\t\t\t\t";
589 sOutput += sTimeStamp;
590
591 sOutput.SearchAndReplaceAll( sSearch, "_" );
592 //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sPrj ) ) )
593 if( sAct.Len() > 1 )
594 pOutputStream->WriteLine( sOutput );
595 }
596 }
597 delete pResData;
598 pResData = NULL;
599 }
600
601 //
602 // class XRMResMerge
603 //
604
605 /*****************************************************************************/
XRMResMerge(const ByteString & rMergeSource,const ByteString & rOutputFile,ByteString & rFilename)606 XRMResMerge::XRMResMerge(
607 const ByteString &rMergeSource, const ByteString &rOutputFile,
608 ByteString &rFilename)
609 /*****************************************************************************/
610 : XRMResOutputParser( rOutputFile ),
611 pMergeDataFile( NULL ),
612 sFilename( rFilename ) ,
613 pResData( NULL )
614 {
615 if ( rMergeSource.Len())
616 pMergeDataFile = new MergeDataFile(
617 rMergeSource, sInputFileName , bErrorLog, RTL_TEXTENCODING_MS_1252);//, bUTF8 );
618 if( Export::sLanguages.EqualsIgnoreCaseAscii("ALL") ){
619 Export::SetLanguages( pMergeDataFile->GetLanguages() );
620 aLanguages = pMergeDataFile->GetLanguages();
621 }
622 else aLanguages = Export::GetLanguages();
623 }
624
625 /*****************************************************************************/
~XRMResMerge()626 XRMResMerge::~XRMResMerge()
627 /*****************************************************************************/
628 {
629 delete pMergeDataFile;
630 delete pResData;
631 }
632
633 /*****************************************************************************/
WorkOnText(const ByteString & rOpenTag,ByteString & rText)634 void XRMResMerge::WorkOnText(
635 const ByteString &rOpenTag,
636 ByteString &rText
637 )
638 /*****************************************************************************/
639 {
640 ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
641
642 if ( pMergeDataFile ) {
643 if ( !pResData ) {
644 ByteString sPlatform( "" );
645 // pResData = new ResData( sPlatform, GetGID() , sFilename );
646 pResData = new ResData( sPlatform, GetLID() , sFilename );
647 pResData->sId = GetLID();
648
649 pResData->sResTyp = "readmeitem";
650 }
651
652 PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
653 if ( pEntrys ) {
654 ByteString sContent;
655 if ( Export::isAllowed( sLang ) &&
656 ( pEntrys->GetText(
657 sContent, STRING_TYP_TEXT, sLang )) &&
658 ( sContent != "-" ) && ( sContent.Len()))
659
660 {
661 rText = sContent;
662 ConvertStringToXMLFormat( rText );
663 //Export::QuotHTMLXRM( rText );
664 }
665 }
666 }
667 }
668
669 /*****************************************************************************/
Output(const ByteString & rOutput)670 void XRMResMerge::Output( const ByteString& rOutput )
671 /*****************************************************************************/
672 {
673 //printf("W: %s\n",rOutput.GetBuffer());
674 if ( pOutputStream && rOutput.Len() > 0 )
675 pOutputStream->Write( rOutput.GetBuffer(), rOutput.Len());
676 }
677
678 /*****************************************************************************/
EndOfText(const ByteString & rOpenTag,const ByteString & rCloseTag)679 void XRMResMerge::EndOfText(
680 const ByteString &rOpenTag,
681 const ByteString &rCloseTag
682 )
683 /*****************************************************************************/
684 {
685
686 Output( rCloseTag );
687 if ( pMergeDataFile && pResData ) {
688 PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
689 if ( pEntrys ) {
690 ByteString sCur;
691 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
692 sCur = aLanguages[ n ];
693 ByteString sContent;
694 if ( !sCur.EqualsIgnoreCaseAscii("en-US") &&
695 ( pEntrys->GetText(
696 sContent, STRING_TYP_TEXT, sCur, sal_True )) &&
697 ( sContent != "-" ) && ( sContent.Len()))
698 {
699 ByteString sText( sContent );
700 //Export::QuotHTMLXRM( sText );
701
702 ByteString sAdditionalLine( "\t" );
703 sAdditionalLine += rOpenTag;
704 ByteString sSearch = "xml:lang=\"";
705 ByteString sReplace( sSearch );
706
707 sSearch += GetAttribute( rOpenTag, "xml:lang" );
708 sReplace += sCur;
709
710 sAdditionalLine.SearchAndReplace( sSearch, sReplace );
711
712 sAdditionalLine += sText;
713 sAdditionalLine += rCloseTag;
714 sAdditionalLine += "\n";
715
716 for ( sal_uInt16 i = 0; i + 1 < GetGID().GetTokenCount( '.' ); i++ )
717 sAdditionalLine += "\t";
718
719 Output( sAdditionalLine );
720 }
721 }
722 }
723 }
724 delete pResData;
725 pResData = NULL;
726 }
727
728