xref: /trunk/main/l10ntools/source/helpmerge.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_l10ntools.hxx"
30 #include <tools/fsys.hxx>
31 #include <osl/file.hxx>
32 // local includes
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include "helpmerge.hxx"
36 #include "utf8conv.hxx"
37 #include <algorithm>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <iostream>
41 #include <fstream>
42 #include <vector>
43 #include "rtl/strbuf.hxx"
44 #ifdef WNT
45 #include <direct.h>
46 //#include <WinBase.h>
47 #include "tools/prewin.h"
48 #include <windows.h>
49 #include "tools/postwin.h"
50 #endif
51 
52 /*****************************************************************************/
53 void HelpParser::FillInFallbacks( LangHashMap& rElem_out, ByteString sLangIdx_in ){
54 /*****************************************************************************/
55     static const ByteString ENGLISH_LANGUAGECODE( "en-US" );
56     static const ByteString GERMAN_LANGUAGECODE ( "de"    );
57     ByteString sCur;
58     XMLElement* pTmp     = NULL;
59     XMLElement* pTmp2    = NULL;
60 
61     sCur = sLangIdx_in;
62     ByteString sFallback( sCur );
63     GetIsoFallback( sFallback );
64     if( (rElem_out.find( sFallback ) != rElem_out.end()) && rElem_out[ sFallback ] != NULL ){
65 	    pTmp2 = rElem_out[ sFallback ];
66         pTmp = new XMLElement( *pTmp2 )  ; // Copy
67         pTmp->SetPos( pTmp2->GetPos()+1 );
68         pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US) );
69         rElem_out[ sLangIdx_in ] = pTmp;
70         pTmp2 = NULL;
71     }
72     else if( (rElem_out.find( ENGLISH_LANGUAGECODE ) != rElem_out.end()) && rElem_out[ ENGLISH_LANGUAGECODE ] != NULL ){// No English
73 	    pTmp2 = rElem_out[ ENGLISH_LANGUAGECODE ];
74         pTmp = new XMLElement( *pTmp2 )  ; // Copy
75         pTmp->SetPos( pTmp2->GetPos()+1 );
76         pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US) );
77         rElem_out[ sCur ] = pTmp;
78         pTmp2 = NULL;
79     }
80     else if( (rElem_out.find( GERMAN_LANGUAGECODE ) != rElem_out.end() ) && rElem_out[ GERMAN_LANGUAGECODE ] != NULL ){// No English
81 	    pTmp2 = rElem_out[ GERMAN_LANGUAGECODE ];
82         pTmp = new XMLElement( *pTmp2 ); // Copy
83         pTmp->SetPos( pTmp2->GetPos()+1 );
84         pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US ) );
85         rElem_out[ sCur ] = pTmp;
86         pTmp2 = NULL;
87 	}else{
88         fprintf(stdout,"ERROR: No Fallback found for language %s:\n",sCur.GetBuffer());
89         rElem_out[ sCur ]=new XMLElement(); // Use dummy element
90 	}
91 }
92 
93 /*****************************************************************************/
94 void HelpParser::Dump(XMLHashMap* rElem_in) {
95 /*****************************************************************************/
96     for(XMLHashMap::iterator pos = rElem_in->begin();pos != rElem_in->end(); ++pos){
97 	    Dump(pos->second,pos->first);
98     }
99 }
100 /*****************************************************************************/
101 void HelpParser::Dump(LangHashMap* rElem_in,const ByteString sKey_in) {
102 /*****************************************************************************/
103     ByteString x;
104     OString y;
105     fprintf(stdout,"+------------%s-----------+\n",sKey_in.GetBuffer() );
106     for(LangHashMap::iterator posn=rElem_in->begin();posn!=rElem_in->end();++posn){
107         x=posn->first;
108         y=posn->second->ToOString();
109         fprintf(stdout,"key=%s value=%s\n",x.GetBuffer(),y.getStr());
110     }
111     fprintf(stdout,"+--------------------------+\n");
112 }
113 
114 HelpParser::HelpParser( const ByteString &rHelpFile, bool rUTF8 , bool rHasInputList  )
115         : sHelpFile( rHelpFile ),
116           bUTF8    ( rUTF8     ),
117           bHasInputList( rHasInputList )
118           {};
119 
120 /*****************************************************************************/
121 bool HelpParser::CreateSDF(
122 /*****************************************************************************/
123 	const ByteString &rSDFFile_in, const ByteString &rPrj_in,const ByteString &rRoot_in,
124     const ByteString &sHelpFile, XMLFile *pXmlFile, const ByteString &rGsi1){
125     // GSI File constants
126     static const String GSI_SEQUENCE1( String::CreateFromAscii("\t0\t")	);
127     static const String GSI_SEQUENCE2( String::CreateFromAscii("\t\t\t0\t")		);
128     static const String GSI_TAB      ( String::CreateFromAscii("\t")			);
129     static const String GSI_SEQUENCE4( String::CreateFromAscii("\t\t\t\t")		);
130 	static const String ret			 ( String::CreateFromAscii("\n")			);
131     static const String ret_char	 ( String::CreateFromAscii("")				);
132     static const String tab			 ( String::CreateFromAscii("\t")			);
133     static const String tab_char	 ( String::CreateFromAscii("")				);
134 
135     SimpleXMLParser aParser;
136     String sUsedTempFile;
137     String sXmlFile;
138 
139     if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) ){
140         DirEntry aTempFile = Export::GetTempFile();
141         DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
142         aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
143         String sTempFile = aTempFile.GetFull();
144         Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
145         sUsedTempFile = sTempFile;
146         sXmlFile = sTempFile;
147     }else{
148         sUsedTempFile = String::CreateFromAscii("");
149         sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
150     }
151 
152 //    ByteString fullFilePath;
153     //DirEntry aFile( sXmlFile );
154     //makeAbsolutePath( sHelpFile , rRoot_in);
155     ByteString fullFilePath = rPrj_in;
156     fullFilePath.Append( "\\" );
157     fullFilePath.Append( makeAbsolutePath( sHelpFile , rRoot_in ) );
158 	fullFilePath.SearchAndReplaceAll( "\\", "/" );
159 
160     String strFullPath( fullFilePath.GetBuffer() , RTL_TEXTENCODING_ASCII_US );
161 
162     //printf( "%s\n", fullFilePath.GetBuffer() );
163     std::auto_ptr <XMLFile> file ( aParser.Execute( strFullPath , sXmlFile, pXmlFile ) );
164 
165 	if(file.get() == NULL){
166 		printf("%s\n",ByteString(aParser.GetError().sMessage,RTL_TEXTENCODING_ASCII_US).GetBuffer());
167         exit(-1);
168 		//return false;
169 	}
170     file->Extract();
171     if( !file->CheckExportStatus() ){
172         return true;
173     }
174     SvFileStream aSDFStream( String( rSDFFile_in, RTL_TEXTENCODING_ASCII_US ),
175 		STREAM_STD_WRITE | STREAM_TRUNC );
176 
177 	if ( !aSDFStream.IsOpen()) {
178         fprintf(stdout,"Can't open file %s\n",rSDFFile_in.GetBuffer());
179         return false;
180 	}
181 
182     ByteString sActFileName = makeAbsolutePath( sHelpFile , rRoot_in );
183 
184 	XMLHashMap*  aXMLStrHM   = file->GetStrings();
185 	LangHashMap* pElem;
186 	XMLElement*  pXMLElement  = NULL;
187 
188 	//Dump(aXMLStrHM);
189 
190 	ByteString sTimeStamp( Export::GetTimeStamp() );
191     OUString sOUTimeStamp( sTimeStamp.GetBuffer() , sTimeStamp.Len() , RTL_TEXTENCODING_ASCII_US );
192 
193     OUStringBuffer sBuffer;
194     const OUString sOUPrj( rPrj_in.GetBuffer() , rPrj_in.Len() , RTL_TEXTENCODING_ASCII_US );
195     const OUString sOUActFileName(sActFileName.GetBuffer() , sActFileName.Len() , RTL_TEXTENCODING_ASCII_US );
196     const OUString sOUGsi1( rGsi1.GetBuffer() , rGsi1.Len() , RTL_TEXTENCODING_ASCII_US );
197 
198     Export::InitLanguages( false );
199     std::vector<ByteString> aLanguages = Export::GetLanguages();
200 
201     std::vector<ByteString> order = file->getOrder();
202     std::vector<ByteString>::iterator pos;
203     XMLHashMap::iterator posm;
204 
205     for( pos = order.begin(); pos != order.end() ; ++pos )
206 	{
207         posm = aXMLStrHM->find( *pos );
208         pElem = posm->second;
209         ByteString sCur;
210 
211         for( unsigned int n = 0; n < aLanguages.size(); n++ )
212 		{
213 			sCur = aLanguages[ n ];
214 			if(pElem->find( sCur )==pElem->end())
215 			{
216 				FillInFallbacks( *pElem , sCur );
217             }
218             pXMLElement = (*pElem)[ sCur ];
219 
220 			if( pXMLElement != NULL )
221 			{
222 				OUString data = pXMLElement->ToOUString();
223    				String sTmp = String(data.getStr());
224 				sTmp.SearchAndReplaceAll(ret,ret_char);    // Remove \n
225 				sTmp.SearchAndReplaceAll(tab,tab_char);    // Remove \t
226 
227                 data = OUString( sTmp );
228                 sBuffer.append( sOUPrj );
229                 sBuffer.append( GSI_TAB );				//"\t";
230                 if ( rRoot_in.Len())
231 					sBuffer.append( sOUActFileName );
232    				sBuffer.append( GSI_SEQUENCE1 );		//"\t0\t";
233    				sBuffer.append( sOUGsi1 );		        //"help";
234    				sBuffer.append( GSI_TAB );              //"\t";
235                 ByteString sID = posm->first;			// ID
236                 sBuffer.append( OUString( sID.GetBuffer() , sID.Len() , RTL_TEXTENCODING_UTF8 ) );
237                 sBuffer.append( GSI_TAB ); //"\t";
238    				ByteString sOldRef = pXMLElement->GetOldref(); // oldref
239                 sBuffer.append( OUString(sOldRef.GetBuffer() , sOldRef.Len() , RTL_TEXTENCODING_UTF8 ) );
240    				sBuffer.append( GSI_SEQUENCE2 );		//"\t\t\t0\t";
241                 sBuffer.append( OUString( sCur.GetBuffer() , sCur.Len() , RTL_TEXTENCODING_UTF8 ) );
242    				sBuffer.append( GSI_TAB );				//"\t";
243 				sBuffer.append( data );
244   				sBuffer.append( GSI_SEQUENCE4 );		//"\t\t\t\t";
245                 sBuffer.append( sOUTimeStamp );
246 				ByteString sOut( sBuffer.makeStringAndClear().getStr() , RTL_TEXTENCODING_UTF8 );
247                 //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( rPrj_in ) ) )
248 				//{
249 				if( data.getLength() > 0 ) aSDFStream.WriteLine( sOut );
250                 //}
251                 pXMLElement=NULL;
252 			}else fprintf(stdout,"\nDBG: NullPointer in HelpParser::CreateSDF , Language %s\n",sCur.GetBuffer() );
253 		}
254 
255 	}
256     //Dump(aXMLStrHM);
257 	aSDFStream.Close();
258 
259     if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
260         DirEntry aTempFile( sUsedTempFile );
261         aTempFile.Kill();
262     }
263     return sal_True;
264 }
265 
266 ByteString HelpParser::makeAbsolutePath( const ByteString& sHelpFile , const ByteString& rRoot_in )
267 {
268   	DirEntry aEntry( String( sHelpFile, RTL_TEXTENCODING_ASCII_US ));
269 	aEntry.ToAbs();
270 	String sFullEntry = aEntry.GetFull();
271 	aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
272 	aEntry += DirEntry( rRoot_in );
273 	ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
274 	ByteString sActFileName(
275 	sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
276 
277 	sActFileName.SearchAndReplaceAll( "/", "\\" );
278     return sActFileName;
279 }
280 bool HelpParser::Merge( const ByteString &rSDFFile, const ByteString &rDestinationFile  ,
281 		ByteString& sLanguage , MergeDataFile& aMergeDataFile )
282 {
283 
284     (void) rSDFFile;
285     bool hasNoError = true;
286 
287     SimpleXMLParser aParser;
288 
289     String sUsedTempFile;
290     String sXmlFile;
291 
292     if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) ){
293         DirEntry aTempFile = Export::GetTempFile();
294         DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
295         aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
296         String sTempFile = aTempFile.GetFull();
297         Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
298         sUsedTempFile = sTempFile;
299         sXmlFile = sTempFile;
300     }else{
301         sUsedTempFile = String::CreateFromAscii("");
302         sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
303     }
304 
305     OUString sOUHelpFile( sXmlFile );
306 	String fullFilePath;
307     DirEntry aFile( sXmlFile );
308 
309 	XMLFile* xmlfile = ( aParser.Execute( aFile.GetFull() , sOUHelpFile, new XMLFile( '0' ) ) );
310 	printf("Dest file %s\n",rDestinationFile.GetBuffer());
311 	hasNoError = MergeSingleFile( xmlfile , aMergeDataFile , sLanguage , rDestinationFile );
312 	delete xmlfile;
313     if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
314         DirEntry aTempFile( sUsedTempFile );
315         aTempFile.Kill();
316     }
317 	return hasNoError;
318 }
319 
320 bool ByteStringEqual( const ByteString& rKey1, const ByteString& rKey2 )  {
321     return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL;
322 };
323 bool ByteStringLess( const ByteString& rKey1, const ByteString& rKey2 )  {
324      return rKey1.CompareTo( rKey2 )==COMPARE_LESS;
325 }
326 
327 void HelpParser::parse_languages( std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile ){
328     std::vector<ByteString> aTmp;
329 
330     const ByteString DE		("de");
331 	const ByteString ENUS	("en-US");
332 	static const ByteString ALL( "ALL" );
333 
334 	Export::InitLanguages( false );
335 
336 	if( Export::sLanguages.EqualsIgnoreCaseAscii( ALL ) )
337 	{
338 		aLanguages = aMergeDataFile.GetLanguages();
339         aLanguages.push_back( DE );
340         aLanguages.push_back( ENUS );
341 
342         if( !Export::sForcedLanguages.Equals("") )
343 		{
344 			std::vector<ByteString> aFL = Export::GetForcedLanguages();
345             std::copy( aFL.begin() ,
346                        aFL.end() ,
347                        back_inserter( aLanguages )
348                      );
349             std::sort(   aLanguages.begin() , aLanguages.end() , ByteStringLess );
350             std::vector<ByteString>::iterator unique_iter =  std::unique( aLanguages.begin() , aLanguages.end() , ByteStringEqual );
351             std::copy( aLanguages.begin() , unique_iter , back_inserter( aTmp ) );
352             aLanguages = aTmp;
353         }
354     }
355     else{
356         aLanguages = Export::GetLanguages();
357     }
358 
359 }
360 
361 bool HelpParser::Merge(
362 	const ByteString &rSDFFile, const ByteString &rPathX , const ByteString &rPathY , bool bISO ,
363 	const std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile , bool bCreateDir )
364 {
365 
366 
367     (void) rSDFFile ;
368     bool hasNoError = true;
369     SimpleXMLParser aParser;
370     String sUsedTempFile;
371     String sXmlFile;
372 
373 	if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) )
374 	{
375         DirEntry aTempFile = Export::GetTempFile();
376         DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
377         aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
378         String sTempFile = aTempFile.GetFull();
379         Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
380         sUsedTempFile = sTempFile;
381         sXmlFile = sTempFile;
382     }
383 	else
384 	{
385         sUsedTempFile = String::CreateFromAscii("");
386         sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
387     }
388 
389 
390 	OUString sOUHelpFile( sXmlFile );
391   	String fullFilePath;
392     DirEntry aFile( sXmlFile );
393 
394 	XMLFile* xmlfile = ( aParser.Execute( aFile.GetFull() , sOUHelpFile, new XMLFile( '0' ) ) );
395 	xmlfile->Extract();
396 
397 	if( xmlfile == NULL)
398 	{
399 		printf("%s\n",ByteString(aParser.GetError().sMessage,RTL_TEXTENCODING_UTF8).GetBuffer());
400 		exit(-1);
401 		//return false;
402 	}
403 
404 
405     ByteString sCur;
406     for( unsigned int n = 0; n < aLanguages.size(); n++ ){
407 		sCur = aLanguages[ n ];
408 
409         ByteString sFilepath;
410         if( bISO )	sFilepath = GetOutpath( rPathX , sCur , rPathY );
411         else        sFilepath = rPathX;
412         if( bCreateDir ) MakeDir( sFilepath );
413 
414         XMLFile* file = new XMLFile( *xmlfile );
415         sFilepath.Append( sHelpFile );
416 		hasNoError = MergeSingleFile( file , aMergeDataFile , sCur , sFilepath );
417 		delete file;
418 
419 		if( !hasNoError ) return false;			// Stop on error
420      }
421 
422     if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) )
423 	{
424         DirEntry aTempFile( sUsedTempFile );
425         aTempFile.Kill();
426     }
427 	delete xmlfile;
428 	return hasNoError;
429 }
430 
431 bool HelpParser::MergeSingleFile( XMLFile* file , MergeDataFile& aMergeDataFile , const ByteString& sLanguage ,
432 								  ByteString sPath )
433 {
434 	file->Extract();
435 
436    	XMLHashMap*   aXMLStrHM     = file->GetStrings();
437 	LangHashMap*  aLangHM;
438 	static	ResData	pResData( "","","");
439 	pResData.sResTyp   = "help";
440 
441     ByteString sTmp             = Export::sLanguages;
442 
443     sTmp.EraseLeadingAndTrailingChars();
444 
445     for(XMLHashMap::iterator pos=aXMLStrHM->begin();pos!=aXMLStrHM->end();++pos)    // Merge every l10n related string
446     {
447 
448         aLangHM             = pos->second;
449         //printf("*********************DUMPING HASHMAP***************************************");
450 		//Dump( aXMLStrHM );
451 		//printf("DBG: sHelpFile = %s\n",sHelpFile.GetBuffer() );
452 
453         pResData.sGId      =  pos->first;
454 		pResData.sFilename  =  sHelpFile;
455 
456         ProcessHelp( aLangHM , sLanguage, &pResData , aMergeDataFile );
457      }
458 
459 
460     // Init temp and target file
461 	ByteString sTempFile;
462 	ByteString sTargetFile( sPath );
463     ByteString sTempFileCopy;
464 
465 	static const ByteString INPATH = Export::GetEnv( "INPATH" );
466 	Export::getRandomName( sPath , sTempFile , INPATH );
467   	Export::getRandomName( sPath , sTempFileCopy , INPATH );
468 	// Write in the temp file
469 	bool hasNoError = file->Write ( sTempFile );
470 	if( !hasNoError )
471     {
472         cerr << "ERROR: file->Write failed\n";
473         return false;
474     }
475 
476     DirEntry aTmp( sTempFile );
477     DirEntry aTmp2( sTempFileCopy );
478     DirEntry aTar( sTargetFile );
479 
480     if( !Export::CopyFile( sTempFile , sTempFileCopy ) )
481     {
482 #if defined(UNX) || defined(OS2)
483         sleep( 3 );
484 #else
485         Sleep( 3 );
486 #endif
487         if( !Export::CopyFile( sTempFile , sTempFileCopy ) )
488         {
489             cerr << "ERROR: Can not copy file from " << sTempFile.GetBuffer() << " to " << sTempFileCopy.GetBuffer() << "\n";
490             return false;
491         }
492     }
493     //remove( sTargetFile.GetBuffer() );
494 
495     FileStat aFSTest( aTar );
496     if( aFSTest.GetSize() < 1 )
497     {
498         remove( sTargetFile.GetBuffer() );
499     }
500     int rc;
501 #if defined(UNX) || defined(OS2)
502     rc = rename( sTempFile.GetBuffer() , sTargetFile.GetBuffer() );
503 #else
504     rc = MoveFileEx( sTempFile.GetBuffer() , sTargetFile.GetBuffer(), MOVEFILE_REPLACE_EXISTING );
505 #endif
506     FileStat aFS( aTar );
507 
508     //cout << "mv " << sTempFile.GetBuffer() << " " << sTargetFile.GetBuffer() << "\n";
509     //cout << "rc -> " << rc << " filesize -> " << aFS.GetSize() << "\n";
510 // Windows rename returns -1 if the file already exits
511 //#ifdef UNX
512     if( rc < 0 || aFS.GetSize() < 1 )
513 //#else
514 //    if( aFS.GetSize() < 1 )
515 //#endif
516     {
517 #if defined(UNX) || defined(OS2)
518         sleep( 3 );
519 #else
520         Sleep( 3 );
521 #endif
522         aFSTest.Update( aTar );
523         if( aFSTest.GetSize() < 1 )
524         {
525             remove( sTargetFile.GetBuffer() );
526         }
527 #if defined(UNX) || defined(OS2)
528         rc = rename( sTempFileCopy.GetBuffer() , sTargetFile.GetBuffer() );
529 #else
530         rc = MoveFileEx( sTempFileCopy.GetBuffer() , sTargetFile.GetBuffer() , MOVEFILE_REPLACE_EXISTING );
531 #endif
532         aFS.Update( aTar );
533 
534         //cout << "mv2 " << sTempFileCopy.GetBuffer() << " " << sTargetFile.GetBuffer() << "\n";
535         //cout << "rc -> " << rc << " filesize -> " << aFS.GetSize() << "\n";
536 
537 // Windows rename returns -1 if the file already exits
538 //#ifdef WNT
539 //        if( aFS.GetSize() < 1 )
540 //#else
541         if( rc < 0 || aFS.GetSize() < 1 )
542 //#endif
543         {
544             cerr << "ERROR: helpex Can't rename file " << sTempFileCopy.GetBuffer() << " to " << sTargetFile.GetBuffer() << " rename rc=" << rc << " filesize=" << aFS.GetSize() << "\n";
545             aTmp.Kill();
546             aTmp2.Kill();
547             if( aFS.GetSize() < 1 )
548                 aTar.Kill();
549             return false;
550         }
551     }
552     aTmp.Kill();
553     aTmp2.Kill();
554 
555 	return true;
556 }
557 
558 ByteString HelpParser::GetOutpath( const ByteString& rPathX , const ByteString& sCur , const ByteString& rPathY ){
559     ByteString testpath = rPathX;
560     static const ByteString sDelimiter( DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
561     testpath.EraseTrailingChars( '/' );
562     testpath.EraseTrailingChars( '\\' );
563     testpath += sDelimiter;
564     testpath += sCur;
565     testpath += sDelimiter;
566     ByteString sRelativePath( rPathY );
567     sRelativePath.EraseLeadingChars( '/' );
568     sRelativePath.EraseLeadingChars( '\\' );
569     testpath += sRelativePath;
570 	testpath += sDelimiter;
571     return testpath;
572 }
573 void HelpParser::MakeDir( const ByteString& sPath ){
574     ByteString sTPath( sPath );
575     ByteString sDelimiter( DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
576     sTPath.SearchAndReplaceAll( sDelimiter , '/' );
577     sal_uInt16 cnt = sTPath.GetTokenCount( '/' );
578     ByteString sCreateDir;
579     for( sal_uInt16 i = 0 ; i < cnt ; i++ )
580     {
581         sCreateDir += sTPath.GetToken( i , '/' );
582         sCreateDir += sDelimiter;
583 #ifdef WNT
584         _mkdir( sCreateDir.GetBuffer() );
585 #else
586         mkdir( sCreateDir.GetBuffer() , S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
587 #endif
588     }
589 }
590 
591 
592 /* ProcessHelp Methode: search for en-US entry and replace it with the current language*/
593 void HelpParser::ProcessHelp( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile ){
594 
595 	XMLElement*   pXMLElement = NULL;
596    	PFormEntrys   *pEntrys    = NULL;
597     XMLData       *data       = NULL;
598     XMLParentNode *parent     = NULL;
599 
600     String        sNewdata;
601 	ByteString sLId;
602     ByteString sGId;
603 
604     pEntrys = NULL;
605 
606 #ifdef MERGE_SOURCE_LANGUAGES
607     if( true ){                  // Merge en-US!
608 #else
609     if( !sCur.EqualsIgnoreCaseAscii("en-US") ){
610 #endif
611         pXMLElement = (*aLangHM)[ "en-US" ];
612         if( pXMLElement == NULL )
613 		{
614             printf("Error: Can't find en-US entry\n");
615         }
616         if( pXMLElement != NULL )
617 		{
618             parent  = pXMLElement->GetParent();
619             sLId    = pXMLElement->GetOldref();
620             pResData->sId     =  sLId;
621 
622             pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
623             if( pEntrys != NULL)
624 			{
625                 ByteString sNewText;
626 		        pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur , true );
627 		        sNewdata = String(  sNewText , RTL_TEXTENCODING_UTF8 );
628                 if ( sNewdata.Len())
629 				{
630                     if( pXMLElement != NULL )
631 					{
632 				        data   = new XMLData( sNewdata , NULL , true ); // Add new one
633                         pXMLElement->RemoveAndDeleteAllChilds();
634 						pXMLElement->AddChild( data );
635                         aLangHM->erase( sCur );
636 				    }
637 			    }
638             }else if( pResData == NULL ){fprintf(stdout,"Can't find GID=%s LID=%s TYP=%s\n",pResData->sGId.GetBuffer(),pResData->sId.GetBuffer(),pResData->sResTyp.GetBuffer());}
639             pXMLElement->ChangeLanguageTag( String( sCur , RTL_TEXTENCODING_ASCII_US) );
640         }
641 
642     }
643 }
644 /* Process() Method merges */
645 void HelpParser::Process( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile ){
646 
647 	XMLElement*   pXMLElement = NULL;
648    	PFormEntrys   *pEntrys    = NULL;
649     XMLData       *data       = NULL;
650     XMLParentNode *parent     = NULL;
651     XMLDefault    *xmldefault = NULL;
652 
653 	short		  curLang     = 0;
654     String        sNewdata;
655     bool          isFallback  = false;
656 	ByteString sLId;
657     ByteString sGId;
658 
659     pEntrys = NULL;
660 
661 #ifdef MERGE_SOURCE_LANGUAGES
662     if( true ){                  // Merge en-US!
663 #else
664     if( !sCur.EqualsIgnoreCaseAscii("en-US") ){
665 #endif
666         pXMLElement = (*aLangHM)[ sCur ];
667         if( pXMLElement == NULL )
668 		{
669             FillInFallbacks( *aLangHM , sCur );
670             pXMLElement =   ( *aLangHM )[ sCur ];
671             isFallback = true;
672         }
673         if( pXMLElement != NULL )
674 		{
675             parent  = pXMLElement->GetParent();
676             sLId    = pXMLElement->GetOldref();
677             pResData->sId     =  sLId;
678 
679             pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
680             if( pEntrys != NULL)
681 			{
682                 ByteString sNewText;
683 		        pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur , true );
684 		        sNewdata = String(  sNewText , RTL_TEXTENCODING_UTF8 );
685                 if ( sNewdata.Len())
686 				{
687 			        printf("Entries found\n");
688                     if( pXMLElement != NULL )
689 					{
690 				        data   = new XMLData( sNewdata , NULL , true ); // Add new one
691 					    if( pXMLElement->ToOUString().compareTo( OUString(data->GetData()) ) != 0 )
692 						{
693 					        pXMLElement->RemoveAndDeleteAllChilds();
694 						    pXMLElement->AddChild( data );
695                         }
696                         if( isFallback )
697 						{
698 					        xmldefault = new XMLDefault( String::CreateFromAscii("\n") , NULL );
699                             int pos = parent->GetPosition( pXMLElement->GetId() );
700                             if( pos != -1 ){
701 						        parent->AddChild(xmldefault , pos+1 );
702                                 parent->AddChild(pXMLElement , pos+2 );
703                             }
704 							else fprintf(stdout,"ERROR: Can't find reference Element of id %s language %d\n",pXMLElement->GetId().GetBuffer(),curLang);
705                         }
706 
707                         aLangHM->erase( sCur );
708 				    }
709 			    }
710 			    delete pResData;
711             }else if( pResData == NULL ){fprintf(stdout,"Can't find GID=%s LID=%s TYP=%s\n",pResData->sGId.GetBuffer(),pResData->sId.GetBuffer(),pResData->sResTyp.GetBuffer());}
712         }
713 
714     }
715 }
716 
717